| Author: | voluntas(Twisted Mind) |
| Title: | Django and AJAX |
| Keywords: | Django, Python, JSON, jQuery, YUI |
| Version: | 1.0.1 |
| License: | GNU Free Document License |
| Date: | 6 Dec 2006 |
Note
Python Workshop 04 presentation materials.
Contents
фゃ≪ゃ фゃ憜
薛
ャ<潟絎障
ャ<潟鴻ユ茯膺肢┳障
gettextユ茯罧腟c障
鴻с障障c障
XML荐絎<ゃ?YAML荐絎<ゃ?с?
綣桁ActiveRecord帥若潟O/R Mapper
蕭潟若潟吾
URL潟潟若若∫d
MySQL PostgreSQL Oracle MSSQL SQLite絲上
膊∞脂≪ч冴罐
綣桁違鴻若
罨
DB篏睡с
AJAX腟粋昭障鐚緇祉荅宴障
潟障
request -> URL Dispatcher -> Views and Models -> Template -> request
激鴻
潟若ф吾
<ゃ絨筝荳祉腥冴c
Tip
Installing minimal Django on Win32 environemnt
| Django: | 0.96-pre 4150 + patch |
| Python: | 2.5 or 2.4.4 |
| PostgreSQL: | 8.1.5 |
$ django-admin.py startproject workshop $ cd workshop $ python manage.py startapp firststep $ cp urls.py ./firststep $ python manage.py runserver
| It worked!: | http://localhost:8000/ |
workshop/
firststep/
__init__.py
models.py
urls.py
views.py
__init__.py
manage.py
settings.py
urls.py
/workshop/settings.py:
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'workshop.firststep',
)
/workshop/urls.py:
from django.conf.urls.defaults import * urlpatterns = patterns('', (r'^firststep/', include('workshop.firststep.urls')), # Uncomment this for admin: # (r'^admin/', include('django.contrib.admin.urls')), )
/workshop/firststep/views.py:
from django.http import HttpResponse def hello_django(request): return HttpResponse('Hello, django!')
/workshop/firststep/urls.py:
from django.conf.urls.defaults import * from workshop.firststep.views import hello_django urlpatterns = patterns('', (r'^hello/django/$', hello_django), )
| Hello, world!: | http://localhost:8000/firststep/hello/django/ |
/workshop/firststep/urls.py:
from django.conf.urls.defaults import * from workshop.firststep.views import * urlpatterns = patterns('', (r'^hello/python/$', hello_python), (r'^hello/ruby/$', hello_ruby), (r'^hello/django/$', hello_django), )
/workshop/firststep/views.py:
from django.http import HttpResponse, HttpResponseRedirect def hello_django(request): return HttpResponse('Hello, django!') def hello_python(request): data = 'Simple is better than complex.' return HttpResponse(data) def hello_ruby(request): return HttpResponseRedirect('/firststep/hello/python/')
| Hello, Python!: | http://localhost:8000/firststep/hello/python/ |
| Hello, Ruby?: | http://localhost:8000/firststep/hello/ruby/ |
/workshop/firststep/urls.py:
from django.conf.urls.defaults import * from workshop.firststep.views import * urlpatterns = patterns('', (r'^hello/django/$', hello_django), (r'^hello/python/$', hello_python), (r'^hello/ruby/$', hello_ruby), (r'^which/(Python|ruby)/$', python_or_ruby), (r'^select/(?P<language>.+)/$', select_language), )
/workshop/django/views.py:
from django.http import HttpResponse, HttpResponseRedirect def hello_django(request): return HttpResponse('Hello, django!') def hello_python(request): data = 'Simple is better than complex.' return HttpResponse(data) def hello_ruby(request): return HttpResponseRedirect('/firststep/hello/python/') def python_or_ruby(request, language): return HttpResponse('%s is nice programing language...' % language) def select_language(request, language): return HttpResponse('%s is bad programing language...' % language)
Python? Ruby? Others?:
Any language:
| Java: | http://localhost:8000/firststep/select/Java/ |
| Perl: | http://localhost:8000/firststep/select/Perl/ |
$ python manage.py startapp blog $ cp urls.py ./blog
/workshop/blog/models.py:
from django.db import models from django.contrib.auth.models import User class Label(models.Model): name = models.CharField(maxlength=128) created = models.DateTimeField(auto_now_add=True) class Admin: pass class Entry(models.Model): title = models.CharField(maxlength=32) user = models.ForeignKey(User) body = models.TextField() created = models.DateTimeField(auto_now_add=True) updated = models.DateTimeField(auto_now=True) tag = models.ManyToManyField(Label) class Admin: pass class Meta: verbose_name_plural = 'entries' def get_absolute_url(self): return '/blog/%s/' % self.id class Comment(models.Model): name = models.CharField(maxlength=32) url = models.URLField() mail = models.EmailField() body = models.TextField() created = models.DateTimeField(auto_now_add=True) entry = models.ForeignKey(Entry) class Admin: pass
/workshop/settings.py:
DATABASE_ENGINE = 'postgresql_psycopg2' DATABASE_NAME = 'workshop' DATABASE_USER = 'django' DATABASE_PASSWORD = 'django' TIME_ZONE = 'Asia/Tokyo' LANGUAGE_CODE = 'ja' INSTALLED_APPS = ( 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.sites', 'workshop.firststep', 'workshop.blog', )
$ python manage.py syncdb Creating table auth_message Creating table auth_group Creating table auth_user Creating table auth_permission Creating table django_content_type Creating table django_session Creating table django_site Creating table blog_comment Creating table blog_entry Creating table blog_label You just installed Django's auth system, \ which means you don't have any superusers defined. Would you like to create one now? (yes/no): yes Username: admin E-mail address: admin@django.ja Password: admin Password (again): admin Superuser created successfully. Installing index for auth.Message model Installing index for auth.Permission model Installing index for blog.Comment model Installing index for blog.Entry model
CREATE TABLE SQL 阪
$ python manage.py sql blog
BEGIN; CREATE TABLE "blog_comment" ( "id" serial NOT NULL PRIMARY KEY, "name" varchar(32) NOT NULL, "url" varchar(200) NOT NULL, "mail" varchar(75) NOT NULL, "body" text NOT NULL, "created" timestamp with time zone NOT NULL, "entry_id" integer NOT NULL ); CREATE TABLE "blog_entry" ( "id" serial NOT NULL PRIMARY KEY, "title" varchar(32) NOT NULL, "user_id" integer NOT NULL REFERENCES "auth_user" ("id"), "body" text NOT NULL, "created" timestamp with time zone NOT NULL, "updated" timestamp with time zone NOT NULL ); ALTER TABLE "blog_comment" ADD CONSTRAINT entry_id_refs_id_2ebcee0 FOREIGN KEY ( "entry_id") REFERENCES "blog_entry" ("id"); CREATE TABLE "blog_label" ( "id" serial NOT NULL PRIMARY KEY, "name" varchar(128) NOT NULL, "created" timestamp with time zone NOT NULL ); CREATE TABLE "blog_entry_tag" ( "id" serial NOT NULL PRIMARY KEY, "entry_id" integer NOT NULL REFERENCES "blog_entry" ("id"), "label_id" integer NOT NULL REFERENCES "blog_label" ("id"), UNIQUE ("entry_id", "label_id") ); COMMIT;
DROP TABLE SQL 阪
$ python manage.py sqlclear blog
BEGIN; DROP TABLE "blog_entry_tag"; DROP TABLE "blog_label"; ALTER TABLE "blog_comment" DROP CONSTRAINT "entry_id_refs_id_2ebcee0"; DROP TABLE "blog_entry"; DROP TABLE "blog_comment";Django and AJAX Django and AJAX
Author: voluntas(Twisted Mind) Title: Django and AJAX Keywords: Django, Python, JSON, jQuery, YUI Version: 1.0.1 License: GNU Free Document License Date: 6 Dec 2006 Note
Python Workshop 04 presentation materials.
Contents
- Django and AJAX
- Django?
- Python Web Framework
- MTV(Model Template View)
- Simple is better than complex.
- Django!
- Install
- Development Environment
- Hello, django!
- View
- URL dispatcher
- Model
- django-admin.py or manage.py
- Admin
- Templates
- extends
- tag
- filter
- Generic Views
- simple
- date_base
- list_detail
- create_update
- Django and AJAX?
- Blog
- Serializers
- XML
- JSON
- JSON and XML
- Django and JSON
- simplejson
- Django and AJAX?
- jQuery
- YUI(Yahoo! User Interface)
- et cetera
- Windows
- Japanese Validator
Django?
Python Web Framework
фゃ≪ゃ фゃ憜
薛
ャ<潟絎障
ャ<潟鴻ユ茯膺肢┳障
gettextユ茯罧腟c障
鴻с障障c障
XML荐絎<ゃ?YAML荐絎<ゃ?с?
綣桁ActiveRecord帥若潟O/R Mapper
蕭潟若潟吾
URL潟潟若若∫d
MySQL PostgreSQL Oracle MSSQL SQLite絲上
膊∞脂≪ч冴罐
綣桁違鴻若
罨
DB篏睡с
AJAX腟粋昭障鐚緇祉荅宴障
MTV(Model Template View)
潟障
request -> URL Dispatcher -> Views and Models -> Template -> request
Simple is better than complex.
激鴻
潟若ф吾
<ゃ絨筝荳祉腥冴c
Django!
Install
Tip
Installing minimal Django on Win32 environemnt
Development Environment
Django: 0.96-pre 4150 + patch Python: 2.5 or 2.4.4 PostgreSQL: 8.1.5 Hello, django!
$ django-admin.py startproject workshop $ cd workshop $ python manage.py startapp firststep $ cp urls.py ./firststep $ python manage.py runserver
It worked!: http://localhost:8000/ workshop/ firststep/ __init__.py models.py urls.py views.py __init__.py manage.py settings.py urls.py/workshop/settings.py:
INSTALLED_APPS = ( 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.sites', 'workshop.firststep', )/workshop/urls.py:
from django.conf.urls.defaults import * urlpatterns = patterns('', (r'^firststep/', include('workshop.firststep.urls')), # Uncomment this for admin: # (r'^admin/', include('django.contrib.admin.urls')), )/workshop/firststep/views.py:
from django.http import HttpResponse def hello_django(request): return HttpResponse('Hello, django!')/workshop/firststep/urls.py:
from django.conf.urls.defaults import * from workshop.firststep.views import hello_django urlpatterns = patterns('', (r'^hello/django/$', hello_django), )
Hello, world!: http://localhost:8000/firststep/hello/django/ View
/workshop/firststep/urls.py:
from django.conf.urls.defaults import * from workshop.firststep.views import * urlpatterns = patterns('', (r'^hello/python/$', hello_python), (r'^hello/ruby/$', hello_ruby), (r'^hello/django/$', hello_django), )/workshop/firststep/views.py:
from django.http import HttpResponse, HttpResponseRedirect def hello_django(request): return HttpResponse('Hello, django!') def hello_python(request): data = 'Simple is better than complex.' return HttpResponse(data) def hello_ruby(request): return HttpResponseRedirect('/firststep/hello/python/')
Hello, Python!: http://localhost:8000/firststep/hello/python/ Hello, Ruby?: http://localhost:8000/firststep/hello/ruby/ URL dispatcher
/workshop/firststep/urls.py:
from django.conf.urls.defaults import * from workshop.firststep.views import * urlpatterns = patterns('', (r'^hello/django/$', hello_django), (r'^hello/python/$', hello_python), (r'^hello/ruby/$', hello_ruby), (r'^which/(Python|ruby)/$', python_or_ruby), (r'^select/(?P<language>.+)/$', select_language), )/workshop/django/views.py:
from django.http import HttpResponse, HttpResponseRedirect def hello_django(request): return HttpResponse('Hello, django!') def hello_python(request): data = 'Simple is better than complex.' return HttpResponse(data) def hello_ruby(request): return HttpResponseRedirect('/firststep/hello/python/') def python_or_ruby(request, language): return HttpResponse('%s is nice programing language...' % language) def select_language(request, language): return HttpResponse('%s is bad programing language...' % language)Python? Ruby? Others?:
Any language:
Java: http://localhost:8000/firststep/select/Java/ Perl: http://localhost:8000/firststep/select/Perl/ Model
$ python manage.py startapp blog $ cp urls.py ./blog/workshop/blog/models.py:
from django.db import models from django.contrib.auth.models import User class Label(models.Model): name = models.CharField(maxlength=128) created = models.DateTimeField(auto_now_add=True) class Admin: pass class Entry(models.Model): title = models.CharField(maxlength=32) user = models.ForeignKey(User) body = models.TextField() created = models.DateTimeField(auto_now_add=True) updated = models.DateTimeField(auto_now=True) tag = models.ManyToManyField(Label) class Admin: pass class Meta: verbose_name_plural = 'entries' def get_absolute_url(self): return '/blog/%s/' % self.id class Comment(models.Model): name = models.CharField(maxlength=32) url = models.URLField() mail = models.EmailField() body = models.TextField() created = models.DateTimeField(auto_now_add=True) entry = models.ForeignKey(Entry) class Admin: pass/workshop/settings.py:
DATABASE_ENGINE = 'postgresql_psycopg2' DATABASE_NAME = 'workshop' DATABASE_USER = 'django' DATABASE_PASSWORD = 'django' TIME_ZONE = 'Asia/Tokyo' LANGUAGE_CODE = 'ja' INSTALLED_APPS = ( 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.sites', 'workshop.firststep', 'workshop.blog', )$ python manage.py syncdb Creating table auth_message Creating table auth_group Creating table auth_user Creating table auth_permission Creating table django_content_type Creating table django_session Creating table django_site Creating table blog_comment Creating table blog_entry Creating table blog_label You just installed Django's auth system, \ which means you don't have any superusers defined. Would you like to create one now? (yes/no): yes Username: admin E-mail address: admin@django.ja Password: admin Password (again): admin Superuser created successfully. Installing index for auth.Message model Installing index for auth.Permission model Installing index for blog.Comment model Installing index for blog.Entry modeldjango-admin.py or manage.py
CREATE TABLE SQL 阪
$ python manage.py sql blogBEGIN; CREATE TABLE "blog_comment" ( "id" serial NOT NULL PRIMARY KEY, "name" varchar(32) NOT NULL, "url" varchar(200) NOT NULL, "mail" varchar(75) NOT NULL, "body" text NOT NULL, "created" timestamp with time zone NOT NULL, "entry_id" integer NOT NULL ); CREATE TABLE "blog_entry" ( "id" serial NOT NULL PRIMARY KEY, "title" varchar(32) NOT NULL, "user_id" integer NOT NULL REFERENCES "auth_user" ("id"), "body" text NOT NULL, "created" timestamp with time zone NOT NULL, "updated" timestamp with time zone NOT NULL ); ALTER TABLE "blog_comment" ADD CONSTRAINT entry_id_refs_id_2ebcee0 FOREIGN KEY ( "entry_id") REFERENCES "blog_entry" ("id"); CREATE TABLE "blog_label" ( "id" serial NOT NULL PRIMARY KEY, "name" varchar(128) NOT NULL, "created" timestamp with time zone NOT NULL ); CREATE TABLE "blog_entry_tag" ( "id" serial NOT NULL PRIMARY KEY, "entry_id" integer NOT NULL REFERENCES "blog_entry" ("id"), "label_id" integer NOT NULL REFERENCES "blog_label" ("id"), UNIQUE ("entry_id", "label_id") ); COMMIT;
DROP TABLE SQL 阪
$ python manage.py sqlclear blogBEGIN; DROP TABLE "blog_entry_tag"; DROP TABLE "blog_label"; ALTER TABLE "blog_comment" DROP CONSTRAINT "entry_id_refs_id_2ebcee0"; DROP TABLE "blog_entry"; DROP TABLE "blog_comment"; COMMIT;Admin
$ python manage.py shell >>> from workshop.blog.models import Entry >>> entry = Entry(title='Today is ...', user='admin', body='etc...') >>> entry.save()/workshop/settings.py:
INSTALLED_APPS = ( 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sites', 'django.contrib.admin', 'workshop.firststep', 'workshop.blog', )/workshop/urls.py:
from django.conf.urls.defaults import * urlpatterns = patterns('', (r'^firststep/', include('workshop.firststep.urls')), (r'^admin/', include('django.contrib.admin.urls')), )$ python manage.py syncdb Creating table django_admin_log Installing index for admin.LogEntry model
Django administration: http://localhost:8000/admin/ /workshop/blog/models.py:
from django.db import models from django.contrib.auth.models import User class Label(models.Model): name = models.CharField(maxlength=128) created = models.DateTimeField(auto_now_add=True) class Admin: list_display = ('name', 'created') def __str__(self): return self.name class Entry(models.Model): title = models.CharField(maxlength=32) user = models.ForeignKey(User) body = models.TextField() created = models.DateTimeField(auto_now_add=True) updated = models.DateTimeField(auto_now=True) tag = models.ManyToManyField(Label, filter_interface=models.HORIZONTAL) class Admin: list_display = ('title', 'user', 'created', 'updated') list_filter = ('created', 'updated') list_select_related = True search_fields = ('title', 'body') date_hierarchy = 'created' ordering = ('created', 'updated') class Meta: verbose_name_plural = 'entries' def __str__(self): return self.title def get_absolute_url(self): return '/blog/%s/' % self.id class Comment(models.Model): name = models.CharField(maxlength=32) url = models.URLField(null=True, blank=True) mail = models.EmailField(null=True, blank=True) body = models.TextField() created = models.DateTimeField(auto_now_add=True) entry = models.ForeignKey(Entry) class Admin: list_display = ('name', 'entry', 'created') list_filter = ('created', 'entry') search_fields = ('name', 'body') date_hierarchy = 'created' ordering = ('created', ) def __str__(self): return self.name
Django administration: http://localhost:8000/admin/ $ python manage.py shell >>> from workshop.blog.models import * >>> entries = Entry.objects.all() >>> entry = entries[0] >>> entry.user.username >>> entry.title >>> entry = Entry.objects.get(1) >>> entry.body >>> entry.createdNote
www.ymasuda.jp
Creating models: http://www.ymasuda.jp/python/django/docs/model-api.html
The database API: http://www.ymasuda.jp/python/django/docs/db-api.html
Templates
$ mkdir templates $ cd templates $ mkdir blogworkshop/ __init__.py manage.py settings.py urls.py firststep/ templates/ blog/ base.html entry_detail_template.html entry_list_template.html entry_detail_filter.html blog/ __init__.py models.py urls.py views.py/wrokshop/settings.py:
import os.path TEMPLATE_DIRS = ( os.path.join(os.path.dirname(__file__), 'templates'), )/workshop/urls.py:
from django.conf.urls.defaults import * urlpatterns = patterns('', (r'^firststep/', include('workshop.firststep.urls')), (r'^blog/', include('workshop.blog.urls')), (r'^admin/', include('django.contrib.admin.urls')), )/workshop/blog/views.py:
from django.shortcuts import render_to_response from workshop.blog.models import Entry def entry_detail(request, entry_id): entry = Entry.objects.get(pk=entry_id) return render_to_response('blog/entry_detail_template.html', dict(entry=entry)) def entry_list(request): entries = Entry.objects.all() return render_to_response('blog/entry_list_template.html', dict(entries=entries)) def entry_detail_and_filter(request, entry_id): entry = Entry.objects.get(pk=entry_id) return render_to_response('blog/entry_detail_filter.html', dict(entry=entry))/workshop/blog/urls.py:
from django.conf.urls.defaults import * from workshop.blog.views import * urlpatterns = patterns('', (r'^(?P<entry_id>\d)/$', entry_detail), (r'^$', entry_list), (r'^filter/(?P<entry_id>\d)/$', entry_detail_and_filter) )extends
/workshop/blog/views.py:
def entry_detail(request, entry_id): entry = Entry.objects.get(entry_id) return render_to_response('blog/entry_detail_template.html', dict(entry=entry))/workshop/templates/blog/base_template.html:
<html> <head> <title>{% block title %}{% endblock %}</title> </head> <body> {% block contents %} {% endblock %} </body> </html>/workshop/templates/blog/entry_detail_template.html:
{% extends "blog/base_template.html" %} {% block title %}{{ entry.title }}{% endblock %} {% block contents %} <p>{{ entry.title }}<p> <p>{{ entry.body }}</p> <p>{{ entry.created }} {{ entry.user.username }}</p> {% endblock %}
Entry Detail: http://localhost:8000/blog/1/ Page not found (404): http://localhost:8000/blog/10/ tag
/workshop/blog/views.py:
def entry_list(request): entries = Entry.objects.all() return render_to_response('blog/entry_list_template.html', dict(entries=entries))/workshop/template/blog/entry_list_template.html:
{% extends "blog/base_template.html" %} {% block title %}Blog Entry List{% endblock %} {% block contents %} <b>Blog Entry List</b> {% if entries %} <ul> {% for entry in entries %} <li> <a href="{{ entry.get_absolute_url }}"> {{ entry.title }} by {{ entry.user.username }}</a> </li> {% endfor %} </ul> {% endif %} {% endblock %}
Entry List: http://localhost:8000/blog/ filter
/workshop/blog/views.py:
def entry_detail_and_filter(request, entry_id): entry = Entry.objects.get(pk=entry_id) return render_to_response('blog/entry_detail_filter.html', dict(entry=entry))/workshop/templates/blog/entry_detail_filter.html:
{% extends "blog/base_template.html" %} {% block title %}{{ entry.title }}{% endblock %} {% block contents %} <p>{{ entry.title }}<p> <p>{{ entry.body|linebreaksbr }}</p> <p>{{ entry.created|date:"Y/m/d H:i:s" }} {{ entry.user.username|upper }}</p> {% endblock %}
Entry Detail and Filter: http://localhost:8000/blog/filter/1/ Entry Detail not Filter: http://localhost:8000/blog/1/ Note
www.ymasuda.jp
Guide for HTMLLauthors: http://www.ymasuda.jp/python/django/docs/templates.html
Guide for Python programmers: http://www.ymasuda.jp/python/django/docs/templates_python.html
Generic Views
simple
direct_to_template
direct_to:
from django.conf.urls.defaults import * from django.views.generic import simple urlpatterns = patterns('', (r'^hello/ruby/$', simple.direct_to, dict(url='/firststep/hello/python/')), )date_base
archive_index
archive_year
archive_month
archive_week
archive_day
archive_today
object_detail
list_detail
object_detail:
from django.conf.urls.defaults import * from django.views.generic import object_detail from workshop.blog.models import Entry queryset = dict(queryset=Entry.objects.all()) urlpatterns = patterns('', (r'^(?P<object_id>\d)/$', list_detail.object_detail, queryset), )
object_list:
from django.conf.urls.defaults import * from django.views.generic import object_detail from workshop.blog.models import Entry queryset = dict(queryset=Entry.objects.all()) urlpatterns = patterns('', (r'^$', list_detail.object_list, queryset), )create_update
create_object:
from django.conf.urls.defaults import * from django.views.generic import create_update from workshop.blog.models import Entry model = dict(model=Entry) urlpatterns = patterns('', (r'^create/$', create_update.object_create, model), )
update_object:
from django.conf.urls.defaults import * from django.views.generic import create_update from workshop.blog.models import Entry model = dict(model=Entry) urlpatterns = patterns('', (r'^update/(?P<object_id>\d+)/$', create_update.object_update, model), )
delete_object
Django and AJAX?
Blog
workshop/ __init__.py manage.py settings.py urls.py templates/ blog/ base.html entry_detail.html entry_list.html entry_detail_filter.html firststep/ blog/ __init__.py urls.py views.py models.pyTip
www.ymasuda.jp
Serving static/media files: http://ymasuda.jp/python/django/docs/static_files.html
/workshop/blog/urls.py:
from django.conf.urls.defaults import * from workshop.blog.models import Entry from workshop.blog.views import * entry_queryset = dict(queryset=Entry.objects.all()) urlpatterns = patterns('', (r'^(?P<entry_id>\d+)/ajax/xml/$', entry_ajax), (r'^(?P<entry_id>\d+)/ajaj/json/$', entry_ajaj), (r'^(xml|json)/$', entry_list_api), )/workshop/blog/views.py:
from django.http import HttpResponse from django.core import serializers from django.utils import simplejson from workshop.blog.models import Entry, Comment def entry_ajax(request, entry_id): entry = Entry.objects.filter(id=entry_id) data = serializers.serialize('xml', entry) return HttpResponse(data, mimetype='text/plain') # return HttpResponse(data, mimetype='appllication/xml') def entry_ajaj(request, entry_id): entry = Entry.objects.filter(id=entry_id) data = serializers.serialize('json', entry, ensure_ascii=False) return HttpResponse(data, mimetype='text/plain') # return HttpResponse(data, mimetype='appllication/json') def entry_list_api(request, output): entries = Entry.objects.all() if output == 'json': data = serializers.serialize(output, entries, ensure_ascii=False) else: data = serializers.serialize(output, entries) return HttpResponse(data, mimetype='text/plain') # return HttpResponse(data, mimetype='appllication/%s' % output)$ python manage.py syncdbSerializers
/workshop/bbs/views.py:
from django.http import HttpResponse from django.core import serializers def serialize_sample(request, type): queryset = Models.objects.all() data = serializers.serialize(type, queryset) return HttpResponse(data, mimetype='application/%s' % type)Warning
ユ篋冴篏羂 ensure_ascii=False 荐絎障
Note
www.ymasuda.jp
Serializing Django objects: http://www.ymasuda.jp/python/django/docs/serialization.html
XML
/workshop/blog/views.py:
def entry_ajax(request, entry_id): entry = Entry.objects.filter(id=entry_id) data = serializers.serialize('xml', entry) return HttpResponse(data, mimetype='text/plain') # return HttpResponse(data, mimetype='appllication/xml')/workshop/blog/urls.py:
(r'^(?P<entry_id>\d+)/ajax/xml/$', entry_ajax),
xml: http://localhost:8000/blog/1/ajax/xml/ <?xml version="1.0" encoding="utf-8"?> <django-objects version="1.0"> <object pk="1" model="blog.entry"> <field type="CharField" name="title">若鴻潟</field> <field to="auth.user" name="user" rel="ManyToOneRel">1</field> <field type="TextField" name="body">Django 鴻帥堺眼若若鴻潟違帥ゃ潟若吾с潟絎憗障鐚若若罕ゃゃ鐚綵綽荀翫ゃ鐚篋篋ャ鴻с鐚 箴逸潟若激鴻 Web 鴻∝ャ鐚若帥若鴻ゃゃ若帥茵腓冴∝ャ鐚ャ若激鴻違潟若激鴻篏帥∝ャ障鐚 箴炊с鐚 Django 鴻帥ゃ障鐚鴻帥純篋腴c障鐚</field> <field type="DateTimeField" name="created">2006-11-30 23:06:08</field> <field type="DateTimeField" name="updated">2006-11-30 23:06:08</field> </object> </django-objects>JSON
/workshop/blog/views.py:
def entry_ajaj(request, entry_id): entry = Entry.objects.filter(id=entry_id) data = serializers.serialize('json', entry, ensure_ascii=False) return HttpResponse(data, mimetype='text/plain') # return HttpResponse(data, mimetype='appllication/json')/workshop/blog/urls.py:
(r'^(?P<entry_id>\d+)/ajaj/json/$', entry_ajaj),
json: http://localhost:8000/blog/1/ajaj/json/ [ { "pk": "1", "model": "blog.entry", "fields": { "body": "Django 鴻帥堺眼若若鴻潟違帥ゃ潟若吾с潟絎憗障鐚若若罕ゃゃ鐚綵綽荀翫ゃ鐚篋篋ャ鴻с鐚\r\n\r\n箴逸潟若激鴻 Web 鴻∝ャ鐚若帥若鴻ゃゃ若帥茵腓冴∝ャ鐚ャ若激鴻違潟若激鴻篏帥∝ャ障鐚\r\n\r\n箴炊с鐚 Django 鴻帥ゃ障鐚鴻帥純篋腴c障鐚", "updated": "2006-11-30 23:06:08", "created": "2006-11-30 23:06:08", "user": 1, "title": "若鴻潟" } } ]JSON and XML
/workshop/blog/views.py:
def entry_list_api(request, output): entries = Entry.objects.all() if output == 'json': data = serializers.serialize(output, entries, ensure_ascii=False) else: data = serializers.serialize(output, entries) return HttpResponse(data, mimetype='text/plain') # return HttpResponse(data, mimetype='appllication/%s' % output)/workshop/blog/urls.py:
(r'^(xml|json)/$', entry_list_api),
json or xml: http://localhost:8000/blog/xml/ json or xml: http://localhost:8000/blog/json/ Django and JSON
simplejson
/workshop/blog/urls.py:
(r'^(?P<entry_id>\d+)/comments/json/$', comment_list_json),/workshop/blog/views.py:
def comment_list_json(request, entry_id): comments = Comment.objects.filter(entry__id=entry_id) data = [dict(name=c.name, url=c.url, body=c.body) for c in comments] values = simplejson.dumps(data, ensure_ascii=False) return HttpResponse(values, mimetype='text/plain') # return HttpResponse(simplejson.dumps(data), mimetype='application/json')Note
A simple, fast, extensible JSON encoder and decoder
return json: http://localhost:8000/blog/1/comments/json/ [ { "body": "models 宴若吾с≪吾ャ若cэmodels 荐荐鐚宴若娯賢茲違≪吾ャ若<ゃ臀≪絎茖荐荐鐚筝≪吾ャ若篏帥c荐荐障鐚", "url": "", "name": "ymasuda" }, { "body": "django.views.generic.simple ≪吾ャ若鐚膂≦ャ若ャc鐚ャ若吾綽荀潟潟違鐚ゃ肴篋ゃ宴若鴻сc障:", "url": "http://www.ymasuda.jp/", "name": "ymasuda" } ]Django and AJAX?
$ mkdir static/jsworkshop/ __init__.py manage.py settings.py urls.py templates/ blog/ base.html entry_list_jquery.html entry_list_yui.html entry_detail.html firststep/ blog/ __init__.py urls.py views.py models.py static/ css/ js/ yui/ yui-ext/ jquery//workshop/settings.py:
MEDIA_ROOT = os.path.join(os.path.dirname(__file__), 'static')/workshop/urls.py:
from django.conf.urls.defaults import * from django.conf import settings urlpatterns = patterns('', (r'^firststep/', include('workshop.firststep.urls')), (r'^blog/', include('workshop.blog.urls')), (r'^admin/', include('django.contrib.admin.urls')), ) if settings.DEBUG: urlpatterns += patterns('', (r'^static/(?P<path>.*)$', 'django.views.static.serve', dict(document_root=settings.MEDIA_ROOT)), )/workshop/blog/urls.py:
from django.conf.urls.defaults import * from django.views.generic import list_detail from workshop.blog.models import Entry from workshop.blog.views import * entry_queryset = dict(queryset=Entry.objects.all()) urlpatterns = patterns('', # Generic Views (r'^jquery/$', list_detail.object_list, dict(entry_queryset, template_name="blog/entry_list_jquery.html")), (r'^yui/$', list_detail.object_list, dict(entry_queryset, template_name="blog/entry_list_yui.html")), (r'^(?P<object_id>\d+)/$', list_detail.object_detail, entry_queryset), (r'^(?P<entry_id>\d+)/ajax/xml/$', entry_ajax), (r'^(?P<entry_id>\d+)/ajaj/json/$', entry_ajaj), (r'^(xml|json)/$', entry_list_api), )/workshop/templates/blog/base.html:
{% comment %} vim: syntax=htmldjango {% endcomment %} <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja"> <head> <meta http-equiv="Content-type" content="text/html; charset=utf-8" /> <meta http-equiv="Content-Language" content="ja" /> <title>{% block title %}{% endblock %}</title> {% block css %} {% endblock %} {% block importjs %} {% endblock %} {% block js %} {% endblock %} </head> <body> {% block body %} {% endblock %} </body> </html>jQuery
$.getJSON:
/workshop/templates/blog/entry_list_jquery.html:
{% comment %} vim: syntax=htmldjango {% endcomment %} {% extends "blog/base.html" %} {% block title %}Django and jQuery and JSON{% endblock %} {% block importjs %} <script type="text/javascript" src="/static/js/jquery/jquery.js"></script> {% comment %} <script type="text/javascript" src="/static/js/jquery/jquery.pack.js"></script> {% endcomment %} {% endblock %} {% block js %} <script language="javaScript" type="text/javascript"> $(function(){ $.getJSON("/blog/json/", function(json){ $.each(json, function(t){ $("#" + this.pk).html(this.fields.body); }); }); }); var getEntry = function(id){ $("#" + id).toggle("slow"); } </script> {% endblock %} {% block body %} {% if object_list %} {% for object in object_list %} <p> <a href="#" onClick="getEntry({{ object.id }})">{{ object.title }}</a> <div id="{{ object.id }}" style="display: none;"></div> </p> {% endfor %} {% endif %} {% endblock %}
jQuery and JSON: http://localhost:8000/blog/jquery/ YUI(Yahoo! User Interface)
YAHOO.util.Connect.asyncRequest:
/workshop/blog/urls.py:
(r'^(?P<entry_id>\d+)/comments/json/$', comment_list_json), (r'^post/comment/$', post_comment),/workshop/blog/views.py:
def comment_list_json(request, entry_id): comments = Comment.objects.filter(entry__id=entry_id) data = dict(comments=[dict(id=str(c.id), author=c.name, date=c.created.strftime("%Y/%m/%d %H:%M:%S"), link=c.url, text=c.body) for c in comments]) values = simplejson.dumps(data, ensure_ascii=False) return HttpResponse(values, mimetype='text/plain') # return HttpResponse(values, mimetype='application/json') def post_comment(request): if request.method == 'POST': new_data = request.POST.copy() name = new_data['author'] url = new_data['url'] body = new_data['comment'] entry_id = new_data['postId'] mail = new_data['email'] e = Entry.objects.get(pk=entry_id) c = Comment(name=name, url=url, body=body, mail=mail, entry=e) c.save() data = dict(comments=[dict(id=str(c.id), author=c.name, date=c.created.strftime("%Y/%m/%d %H:%M:%S"), link=c.url, text=c.body)]) value = simplejson.dumps(data, ensure_ascii=False) return HttpResponse(value, mimetype='text/plain') # return HttpResponse(value, mimetype='application/json') return HttpResponse(value, mimetype='text/plain')/workshop/templates/blog/entry_detail.html:
{% comment %} vim: syntax=htmldjango ts=8 sw=2 sts=2 {% endcomment %} {% extends "blog/base.html" %} {% block title %}{{ object.title }}{% endblock %} {% block importcss %} <link rel="stylesheet" type="text/css" href="/static/css/yui-ext/resources/css/reset-min.css" /> <link rel="stylesheet" type="text/css" href="/static/css/yui-ext/resources/css/resizable.css" /> <link rel="stylesheet" type="text/css" href="/static/css/yui-ext/resources/css/tabs.css" /> <link rel="stylesheet" type="text/css" href="/static/css/yui-ext/resources/css/basic-dialog.css" /> <link rel="stylesheet" type="text/css" href="/static/css/yui-ext/resources/css/post.css" /> {% endblock %} {% block importjs %} <script type="text/javascript" src="/static/js/yui/utilities/utilities.js"></script> <script type="text/javascript" src="/static/js/yui-ext/yui-ext.js"></script> {% endblock %} {% block js %} <script language="javaScript" type="text/javascript"> var Comments = function(){ var dialog, postLink, viewLink, txtComment; var tabs, commentsList, postBtn, renderer; var wait, error, errorMsg; var posting = false; return { init : function(){ txtComment = getEl('comment'); commentsList = getEl('comments-list'); postLink = getEl('post-comment'); viewLink = getEl('view-comments'); wait = getEl('post-wait'); error = getEl('post-error'); errorMsg = getEl('post-error-msg'); this.createDialog(); postLink.addHandler('click', true, function(){ tabs.activate('post-tab'); dialog.show(postLink); }); viewLink.addHandler('click', true, function(){ tabs.activate('view-tab'); dialog.show(viewLink); }); }, submitComment : function(){ postBtn.disable(); wait.radioClass('active-msg'); var formObj = document.getElementById('comment-form') var spam = YAHOO.util.Connect.setForm(formObj); var commentSuccess = function(o){ postBtn.enable(); var data = renderer.parse(o.responseText); if(data){ wait.removeClass('active-msg'); renderer.append(data.comments[0]); dialog.hide(); }else{ error.radioClass('active-msg'); errorMsg.update(o.responseText); } }; var commentFailure = function(o){ postBtn.enable(); error.radioClass('active-msg'); errorMsg.update('Unable to connect.'); }; YAHOO.util.Connect.asyncRequest('post', '/blog/post/comment/', {success: commentSuccess, failure: commentFailure}, spam); }, createDialog : function(){ dialog = new YAHOO.ext.BasicDialog("comments-dlg", { autoTabs:true, width:500, height:400, shadow:true, minWidth:300, minHeight:300 }); dialog.addKeyListener(27, dialog.hide, dialog); dialog.addButton('Close', dialog.hide, dialog); postBtn = dialog.addButton('Post', this.submitComment, this); dialog.on('hide', function(){ wait.removeClass('active-msg'); error.removeClass('active-msg'); txtComment.dom.value = ''; }); tabs = dialog.getTabs(); var sizeTextBox = function(){ txtComment.setSize(dialog.size.width-44, dialog.size.height-264); }; sizeTextBox(); dialog.on('resize', sizeTextBox); tabs.on('tabchange', function(panel, tab){ postBtn.setVisible(tab.id == 'post-tab'); }); renderer = new CommentRenderer(commentsList); var um = commentsList.getUpdateManager(); um.setRenderer(renderer); var commentsLoaded = false; tabs.getTab('view-tab').on('activate', function(){ if(!commentsLoaded){ um.update('/blog/{{ object.id }}/comments/json/'); commentsLoaded = true; } }); } }; }(); var CommentRenderer = function(list){ var tpl = new YAHOO.ext.DomHelper.Template( '<li id="comment-{id}">' + '<div class="cheader">' + '<div class="cuser">{author}:</div>' + '<div class="commentmetadata">{date}</div>' + '</div>{text}</li>' ); this.parse = function(json){ try{ return eval('(' + json + ')'); }catch(e){} return null; }; this.render = function(el, response){ var data = this.parse(response.responseText); if(!data || !data.comments || data.comments.length < 1){ el.update('There are no comments for this post.'); return; } el.update(''); for(var i = 0, len = data.comments.length; i < len; i++){ this.append(data.comments[i]); } }; this.append = function(data){ tpl.append(list.dom, data); }; }; YAHOO.ext.EventManager.onDocumentReady(Comments.init, Comments, true); </script> {% endblock %} {% block body %} <p> <h2>{{ object.title }}</h2> <p>{{ object.body|linebreaksbr }}</p> <div id="comment-box"> <ul> <li><a id="post-comment" href="#">Post Comment</a></li> <li><a id="view-comments" href="#">View Comments</a></li> </ul> </div> </p> <!-- comments dialog --> <div id="comments-dlg" style="visibility:hidden;"> <div class="ydlg-hd">Comments</div> <div class="ydlg-bd"> <div id="post-tab" class="ydlg-tab" title="Post Comment"> <div class="inner-tab"> <form action="" method="post" id="comment-form" onsubmit="return false;"> <input id="postId" type="hidden" name="postId" value="{{ object.id }}" /> <p> <label for="author"><small>Name</small></label> <input class="textinput" type="text" name="author" id="author" value="" size="22" tabindex="1" /> </p> <p><label for="email"><small>E-mail (will not be published)</small></label> <input class="textinput" type="text" name="email" id="email" value="" size="22" tabindex="2" /> </p> <p><label for="url"><small>Website</small></label> <input class="textinput" type="text" name="url" id="url" value="" size="22" tabindex="3" /> </p> <p> <label for="comment"><small>Comment</small></label> <textarea name="comment" id="comment" tabindex="4" cols="40" rows="10"></textarea> </p> </form> </div> </div> <div id="view-tab" class="ydlg-tab" title="View Comments"> <ul id="comments-list" class="inner-tab"> </ul> </div> </div> <div class="ydlg-ft"> <div id="dlg-msg"> <span id="post-error" class="posting-msg"> <img src="/static/images/warning.gif" width="16" height="16" align="absmiddle" /> <span id="post-error-msg"></span></span> <span id="post-wait" class="posting-msg"> <img src="/static/css/yui-ext/resources/images/grid/loading.gif" width="16" height="16" align="absmiddle" /> Posting Comment...</span> </div> </div> </div> {% endblock %}
YUI and JSON: http://localhost:8000/blog/yui/ Note
Yahoo! User Interface Library
Yahoo! UI Library (YUI):
yui-ext Documentation Center:
et cetera
Windows
Windowsф篆罩c:
- Timezone bug in development server using a Windows environment
Japanese Validator
ユ茯若帥泣潟с:
from django.core import validators from django.conf import settings import re zen_num = re.compile(u'[\uFF10-\uFF19]') zen_kana = re.compile(u'[\u30A1-\u30F6]') zen_hira = re.compile(u'[\u3041-\u3093]') han_kana = re.compile(u'[\uFF61-\uFF9F]') def isNotIncludeHalfWidthKatakana(field_data, all_data): from_data = unicode(field_data, settings.DEFAULT_CHARSET) if han_kana.search(from_data) is not None: raise validators.ValidationError(_('Half-width Kana characters' 'are not allowed.'))