Django FAQ
Зміст
- 1 Основні команди та нюанси при роботі з системою Django
- 2 Модуль для роботи із зображеннями
- 3 Створення бази даних
- 4 Циклічний перебір
- 5 Перегрупування в шаблоні
- 6 Шаблон форми
- 7 Робота з формою в views.py
- 8 Збереження в змінній форми
- 9 Профілі користувачів
- 10 Pagination - розбиття на сторінки
- 11 Багатомовність
- 12 Групування в SQL
- 13 Дописування методів в адмінку
- 14 Приклад WSGI
- 15 Профілі користувачів
- 16 Профілі 2
- 17 Якщо є яйця в пітоні
- 18 Кеш в Апачі
- 19 Кеш в Django
- 20 Корзина
- 21 Використання unordered_list
- 22 Використання календаря
- 23 Рестарт WSGI без апача
- 24 Фільтрація в моделі в зовнішньому ключі
- 25 Django & Cron
- 26 Багато з'єднань з базою
- 27 Автоматична перегрузка коду (для Apache)
- 28 Доступ до url адмінки
- 29 Фільтрація по датам
- 30 RAW SQL
- 31 Тестовий поштовий сервер
- 32 Робота з великими об'ємами даних
Основні команди та нюанси при роботі з системою Django
django-admin.py startproject mysite python manage.py startapp books python manage.py validate python manage.py sqlall books python manage.py syncdb python manage.py inspectdb
Модуль для роботи із зображеннями
http://www.pythonware.com/products/pil/
Створення бази даних
create database exam2 charset=utf8; ALTER DATABASE exam2 DEFAULT CHARACTER SET 'utf8'
Циклічний перебір
{% cycle 'row1' 'row2' %}
Перегрупування в шаблоні
{% regroup people by gender as gender_list %}
{% regroup people|dictsort:"gender" by gender as gender_list %}
<ul>
{% for gender in gender_list %}
<li>{{ gender.grouper }}
<ul>
{% for item in gender.list %}
<li>{{ item.first_name }} {{ item.last_name }}</li>
{% endfor %}
</ul>
</li>
{% endfor %}
</ul>
Шаблон форми
<form method="post" action="">
<dl>
{% for field in form %}
<dt>{{ field.label_tag }}{% if field.field.required %}*{% endif %}</dt>
<dd>{{ field }}</dd>
{% if field.help_text %}<dd>{{ field.help_text }}</dd>{% endif %}
{% if field.errors %}<dd class="myerrors">{{ field.errors }}</dd>{% endif %}
{% endfor %}
</dl>
<input type="submit" />
</form>
Робота з формою в views.py
instance = Instance(required_field='value') form = InstanceForm(request.POST, instance=instance) new_instance = form.save()
instance = form.save(commit=False) instance.required_field = 'new value' new_instance = instance.save()
Збереження в змінній форми
allNodes = Form.serialize("myform");
Профілі користувачів
in settings.py: AUTH_PROFILE_MODULE = 'projectname.UserProfile'
в інших відповідних файлах
class UserProfile(models.Model):
user = models.OneToOneField(User, related_name='%(class)s', primary_key=True)
from django.contrib.auth.models import User u = User.objects.get(username='test') user_profile = u.profile.get()
Pagination - розбиття на сторінки
from django.core.paginator import Paginator objects = ['john', 'paul', 'george', 'ringo'] p = Paginator(objects, 2) page1 = p.page(1) page1.object_list
Багатомовність
django-admin.py makemessages -l uk django-admin.py compilemessages
Групування в SQL
qs = Schedule.objects.select_related().filter(pub_date__gte=datetime.now())
qs.query.group_by = ['country_id'] #!!!!!!
return {'schedule': qs}
>>> qs = TumbleItem.objects.all() >>> qs.query.group_by = ['item_type'] >>> qs.query.having = ['COUNT(item_type) > 1'] >>> item_types = [i.item_type for i in qs] >>> item_types
Дописування методів в адмінку
def remove(self):
from django.core.urlresolvers import reverse
return '<a href="%s" class="deletelink">Delete</a>' % reverse( "django.contrib.admin.views.main.delete_stage",
args = ( self.__class__._meta.app_label, self.__class__.__name__.lower(), self._get_pk_val(), ) )
remove.allow_tags = True
Приклад WSGI
sys.stdout = sys.stderr
import os, sys
sys.path.append('/usr/lib/python2.4/site-packages/django')
sys.path.append('/var/www/paradise/paradise')
sys.path.append('/var/www/paradise')
os.environ['DJANGO_SETTINGS_MODULE'] = 'paradise.settings'
import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()
Профілі користувачів
from django.contrib import admin
from profile.models import UserProfile
from django.contrib.auth.models import User
class ProfileInline(admin.StackedInline):
model = UserProfile
extra = 1
max_num = 1
class ProfileAdmin(admin.ModelAdmin):
inlines = (ProfileInline,)
admin.site.unregister(User) #!!!
admin.site.register(User, ProfileAdmin)
Профілі 2
from django.contrib.auth.models import User
User.add_to_class('department',models.CharField(max_length=250,blank=True))
User.add_to_class('position',models.CharField(max_length=250,blank=True))
User._meta.admin.fields += (('Custom', {'fields': ('department','position',)}),)
User._meta.admin.list_display += ('department','position',)
def get_user_name(self):
if self.first_name or self.last_name:
return self.first_name + " " + self.last_name
return self.username
User.add_to_class("get_user_name",get_user_name)
Якщо є яйця в пітоні
/etc/sysconfig/httpd export PYTHON_EGG_CACHE="/var/cache/python-eggs"
Кеш в Апачі
добавити в апач конфігурацію
<IfModule mod_expires.c>
<FilesMatch "\.(jpg|gif|png|css|js)$">
ExpiresActive on
ExpiresDefault "access plus 3 days"
</FilesMatch>
</IfModule>
Кеш в Django
from django.views.decorators.cache import cache_page
....
@cache_page(60 * 15)
def show_page(request, url=None, page_num=0):
....
....
у файлі admin.py:
from django.core.cache import cache
from django.conf import settings
....
def save_model(self, request, obj, form, change):
#cache.delete('views.decorators.cache.cache_header.%s./%s/' % (settings.CACHE_MIDDLEWARE_KEY_PREFIX, obj.url))
cache._cache.flush_all() # ось так для memcache!!!
obj.save()
Корзина
def delete(self, trash=True):
if not self.trashed_at and trash:
self.trashed_at = datetime.now()
self.save()
else:
super(SomeModel, self).delete()
Використання unordered_list
['States', ['Kansas', ['Lawrence', 'Topeka'], 'Illinois']], then {{ var|unordered_list }} would return:
<li>States
<ul>
<li>Kansas
<ul>
<li>Lawrence</li>
<li>Topeka</li>
</ul>
</li>
<li>Illinois</li>
</ul>
</li>
Використання календаря
class EventSplitDateTime(forms.SplitDateTimeWidget):
def __init__(self, attrs=None):
widgets = [forms.TextInput(attrs={'class': 'vDateField'}),
forms.TextInput(attrs={'class': 'vTimeField'})]
# Note that we're calling MultiWidget, not SplitDateTimeWidget, because
# we want to define widgets.
forms.MultiWidget.__init__(self, widgets, attrs)
def format_output(self, rendered_widgets):
return mark_safe(u'%s<br />%s' % (rendered_widgets[0], rendered_widgets[1]))
class EventForm(forms.Form):
start = forms.DateTimeField(label=ugettext("Start"), widget=EventSplitDateTime())
end = forms.DateTimeField(label=ugettext("End"), widget=EventSplitDateTime())
Рестарт WSGI без апача
@never_cache
def restart(request):
''' Перезапуск демона '''
if request.META['mod_wsgi.process_group'] != '':
import signal, os
os.kill(os.getpid(), signal.SIGINT)
ret = 'restarted'
else:
ret = 'not find porcess_group'
return HttpResponse(ret, mimetype='text/plain')
Фільтрація в моделі в зовнішньому ключі
models.ForeignKey(Test, limit_choices_to = {'pub_date__lte': datetime.now})
Django & Cron
# -*- coding: utf-8 -*-
import sys
import settings
from django.core.management import setup_environ
setup_environ(settings)
module_name = sys.argv[1]
exec('import %s' % module_name)
exec('%s.%s' % (module_name, ' '.join(sys.argv[2:])))
И теперь при помощи этого скрипта мы можем вызывать функции наших “вьюшек” из командной строки и из cron:
# python /path/to/project/run.py report.views "send_emails()"
Багато з'єднань з базою
from django.db import load_backend
myBackend = load_backend('postgresql_psycopg2') # or 'mysql', 'sqlite3', 'oracle'
myConnection = myBackend.DatabaseWrapper({
'DATABASE_HOST': '192.168.1.1',
'DATABASE_NAME': 'my_database',
'DATABASE_OPTIONS': {},
'DATABASE_PASSWORD': "",
'DATABASE_PORT': "",
'DATABASE_USER': "my_user",
'TIME_ZONE': "America/New_York",})
# Now we can do all the standard raw sql stuff with myConnection.
myCursor = myConnection.cursor()
myCursor.execute("SELECT COUNT(1) FROM my_table;")
myCursor.fetchone()
Автоматична перегрузка коду (для Apache)
в конфіг добавляємо
WSGIScriptReloading On WSGIReloadMechanism Process
$ touch my_project.wsgi
Доступ до url адмінки
from django.core import urlresolvers
url = urlresolvers.reverse('admin:mysite_product_change', args=(obj.id,))
Фільтрація по датам
extra_data = {"d": "date(created)"}
result = MyModel.objects.extra(extra_data).values('d').annotate(cnt=Count('pk')).order_by()
RAW SQL
authors = Author.objects.raw("SELECT *, age(birth_date) as age FROM library_authors")
for author in authors:
print "%s is %s." % (author.first_name, author.age)
Тестовий поштовий сервер
python -m smtpd -n -c DebuggingServer localhost:1025
Робота з великими об'ємами даних
1. MyModel.objects.all() – швидкий, для малих об'ємів 2. MyModel.objects.all().iterator() – середній, для великих об'ємів 3. queryset_iterator(MyModel.objects.all()) – повільний, для монстрів
import gc
def queryset_iterator(queryset, chunksize=1000):
'''''
Iterate over a Django Queryset ordered by the primary key
This method loads a maximum of chunksize (default: 1000) rows in it's
memory at the same time while django normally would load all rows in it's
memory. Using the iterator() method only causes it to not preload all the
classes.
Note that the implementation of the iterator does not support ordered query sets.
'''
pk = 0
last_pk = queryset.order_by('-pk')[0].pk
queryset = queryset.order_by('pk')
while pk < last_pk:
for row in queryset.filter(pk__gt=pk)[:chunksize]:
pk = row.pk
yield row
gc.collect()