View
264
Download
1
Category
Preview:
Citation preview
Django. Дополнительн
ые темы
Александр Бекбулатов
2
1. Скрипт управления django приложением.
2. Middleware.
3. Использование сессий.
4. Приложение auth.
5. Class Based Views.
6. Расширение фильтров и тэгов в
шаблонизаторе.
7. Другие приложения из коробки.
8. Оптимизация производительности
План лекции
3
Скрипт управления django приложением
4
Зачем?
• Standalone скрипты
• Скрипты запуска по крону
Как?
• Ручная инициализация приложения
• Management команды
Управление django приложением
5
import osimport sys
if __name__ == "__main__": lib_path = 'path/to/project' if not lib_path in sys.path: sys.path.append(lib_path) os.environ['DJANGO_SETTINGS_MODULE'] = \ 'ask_pupkin.settings' # from django.conf import settings from ask.models import User …
Ручная инициализация
6
Куда поместить?
ask/ __init__.py models.py management/ __init__.py commands/ __init__.py fill_db.py tests.py views.py
Management команды
7
class Command(BaseCommand): help = 'Fill database with test data' def handle(self, *args, **options): verbosity = int(options.get('verbosity', 1)) for i in xrange(USER_COUNT): user = User( name=get_random_string(10), email=get_random_email() ) user.save() if verbosity > 1: self.stdout.write('Successfully imported %d users' % USER_COUNT)
Management команды
8
Возможности
• Запуск скриптов для конкретного
приложения (manage.py sqlall ask)
• Несколько команд в одном файле
(manage.py fill_db users, manage.py fill_db
questions)
• Дополнительные опции (--delete)
https
://docs.djangoproject.com/en/dev/howto/custom-man
agement-commands
/
Управление django приложением
9
Middleware
10
Middleware
11
Примеры
• Обработка запроса
• Статистика
• Аутентификация
• Защита от CSRF
• Редиректы
• Кеширование
Middleware
12
CSRF Атака
13
• «Небезопасные» методы POST, PUT и
DELETE
• Установка cookie (csrftoken)
• Установка hidden поля
(csrfmiddlewaretoken) или заголовка (X-
CSRFToken)
CSRF в Django
14
1. Для установки куки страница должна
отдаваться динамически
2. Кука может не ставиться, если передача
контекста идет через Context вместо
RequestContext
3. Скрытое поле ставится тегом {% csrf_token %},
используйте RequestContext (функция render)
4. Токен в ajax запросах удобнее передавать
заголовком
https://docs.djangoproject.com/en/dev/ref/contrib/csrf/
CSRF в Django
15
Способы хранения
• Файловые сессии
• Сессии в БД
• Сессии в куках
Использование сессий
16
def login(request): username = request.POST.get('username') try: user = User.objects.get(username=username) except User.DoesNotExist: return HttpResponse("Such user is not created.") # bad practice!!! if user.password == request.POST.get('password'): request.session['user_id'] = user.id return HttpResponse("You're logged in.") else: return HttpResponse("Your username and password didn't match.")
Использование сессий
17
def logout(request): try: del request.session['user_id'] except KeyError: pass return HttpResponse("You're logged out.")
Использование сессий
18
def makebold(fn): def wrapped(): return "<b>" + fn() + "</b>" return wrapped def makeitalic(fn): def wrapped(): return "<i>" + fn() + "</i>" return wrapped
Декораторы в python
19
@makebold@makeitalicdef hello(): return "hello world" // hello = makebold(makeitalic(hello)) print hello() ## returns <b><i>hello world</i></b>
Декораторы в python
20
@require_POSTdef vote_view(request): # only POST method is allowed pass либо url(r"^vote/", require_POST(vote)),
Декораторы для Views
21
Примеры
Проверка HTTP методов
Проверка прав доступа
Кеширование
Django Views
22
Django Auth
23
Возможности
Пользователи
Права и группы доступа
Контроллеры login/logout
Тесная интеграция с админкой
Django Auth
24
Модель User
username (обязательное поле)
first_name
last_name
password (обязательное поле)
is_staff
is_active
is_superuser
…
Django Auth
25
Создание пользователей
from django.contrib.auth.models import User
user = User.objects.create_user('masha', 'masha@mail.ru', 'password')
Django Auth
26
Login
def login_view(request): username = request.POST.get('username') password = request.POST.get('password') user = authenticate(username=username, password=password) if user is not None: if user.is_active: login(request, user) # Redirect to a success page. else: # 'disabled account' error message else: # 'invalid login' error message.
Django Auth
27
Logout
def logout_view(request): logout(request) # Redirect to a success page.
Django Auth
28
Login/Logout средствами django
1. Подключить в роутинге контроллеры входа и
выхода
(r'^accounts/login/$',
'django.contrib.auth.views.login')
(r'^accounts/logout/$',
'django.contrib.auth.views.logout')
2. Создать шаблоны
registration/login.html
registration/logged_out.html
3. GET параметр next для возврата
Django Auth
29
Login/Logout средствами django
Страница авторизации:
LOGIN_URL = '/accounts/login/'
Страница профиля:
LOGIN_REDIRECT_URL = '/accounts/profile/'
Страница выхода:
LOGOUT_URL = '/accounts/logout/’
https://docs.djangoproject.com/en/dev/topics/auth/de
fault
/
Django Auth
30
Проверка авторизации во views
def my_view(request): if not request.user.is_authenticated(): return redirect('/login/?next=%s' % request.path) user = request.user
@login_requireddef my_view(request): ...
Django Auth
31
Проверка авторизации в шаблонах
{% if user.is_authenticated %} Welcome, {{ user.username }}{% else %} Please log in.{% endif %}
Django Auth
32
Расширение текущего пользователя
from django.contrib.auth.models import User class UserProfile(models.Model): user = models.OneToOneField(User, related_name='profile') rating = models.PositiveIntegerField()
>>> u = User.objects.get(username='masha')>>> print u.profile.rating
Django Auth
33
Расширение текущего пользователя
• Другой уникальный ключ пользователя (email вместо
username)
• Дополнительные поля (в т. ч. обязательные)
https://docs.djangoproject.com/en/dev/topics/auth/customizing
/#extending-the-existing-user-
model
Django Auth
34
Class Based Views
35
• TemplateView
• RedirectView
• ListView
• DetailView
• FormView
• CreateView
• UpdateView
• DeleteView
• ArchiveIndexView
• YearArchiveView
• …
Class Based Views
36
Контроллер-функция (пример 1)def post_detail(request, pk): try: object = Post.objects.get(pk=pk) except Post.DoesNotExist: raise Http404 return render( request, 'blog/post_detail.html', {'object': object} ) urlpatterns = patterns('', url(r'^post/(?P<pk>\d+)/$', post_detail, name='post_detail'),)
Class Based Views
37
Контроллер-класс (пример 1)
class PostDetail(generic.DetailView): model=Post
urlpatterns = patterns('', url(r'^post/(?P<pk>\d+)/$', PostDetail.as_view(), name='post_detail'),)
Class Based Views
38
Контроллер-функция (пример 2)def post_list(request): paginator = Paginator(Post.objects.all(), 25) page = request.GET.get('page') try: posts = paginator.page(page) except PageNotAnInteger: posts = paginator.page(1) except EmptyPage: posts = paginator.page(paginator.num_pages) return render( request, 'blog/post_list.html', {'object_list': posts} )
Class Based Views
39
Контроллер-класс (пример 2)
class PostList(generic.ListView): model = Post paginate_by = 25
Class Based Views
40
Контроллер-функция (пример 3)
@login_requireddef category(request, pk): cat = get_object_or_404(Category, pk=pk) post_list = Post.objects.filter(category=cat) return render(request, 'blog/category.html', { 'category': cat, 'post_list' : post_list })
Class Based Views
41
Контроллер-класс (пример 3)class CategoryListView(generic.ListView): template_name = 'blog/category.html’
def get_queryset(self): self.cat = get_object_or_404(Category, pk=self.kwargs['pk']) return Post.objects.filter(category=self.cat)
@method_decorator(login_required) def dispatch(self, *args, **kwargs): return super(CategoryListView, self).dispatch(*args, **kwargs)
def get_context_data(self, **kwargs): context = super(CategoryListView, self).get_context_data(**kwargs) context['category'] = self.cat return context
Class Based Views
43
Фильтры и теги в шаблонизаторе
44
Модель
class Post(models.Model): … @models.permalink def get_absolute_url(self): return ('post_detail', (self.pk,)) # либо def get_absolute_url(self): return reverse('post_detail', args=(self.pk,))
Построение урлов
45
Роутинг
url(r'^(?P<pk>\d+)/$', 'post_detail', name='post_detail'), Шаблоны <a href="{{ post.get_absolute_url }}">{{ post }}</a>
<a href="{% url 'post_detail' post.pk %}">{{ post }}</a>
Построение урлов
46
Фильтр
{{ post.content|cut:"<cut>" }}
Simple Tag
{% current_time "%Y-%m-%d %I:%M %p" %}
Inclusion tag
{% popular_tags 20 %}
Фильтры и теги в шаблонизаторе
47
Assignment tags
{% get_current_time "%Y-%m-%d %I:%M %p" as the_time %}
Блок с закрывающим тегом
{% switch %} {% endswitch %}
Фильтры и теги в шаблонизаторе
48
Добавление тега
blog/ __init__.py models.py templatetags/ __init__.py blog_tags.py tests.py views.py
Фильтры и теги в шаблонизаторе
49
from django import templatefrom blog.models import Post
register = template.Library() @register.inclusion_tag('blog/tags/lastposts.html')def last_posts(): return {'post_list': Post.objects.all()[:5]}
Фильтры и теги в шаблонизаторе
50
Шаблон
<ul>{% for object in post_list %} <li><a href="{{ object.get_absolute_url}}">{{ object }}</a></li>{% endfor %}</ul>
Подключение{% load blog_tags %}{% last_posts %}
https://docs.djangoproject.com/en/dev/howto/custom-template-tags/
Фильтры и теги в шаблонизаторе
51
Приложения из коробки
52
Подключение
from django.conf.urls import patterns, include, url # Uncomment the next two lines to enable the admin:from django.contrib import adminadmin.autodiscover() urlpatterns = patterns('', … # Uncomment the next line to enable the admin: url(r'^admin/', include(admin.site.urls)),)
Административная консоль
53
Подключение
from blog.models import Category, Postfrom django.contrib import admin class PostAdmin(admin.ModelAdmin): date_hierarchy = 'creation_date' list_display = ('title', 'category') list_filter = ('category',) search_fields = ('title',) admin.site.register(Category)admin.site.register(Post, PostAdmin)
Административная консоль
54
Административная консоль
55
Административная консоль
56
Административная консоль
57
Возможности
Сбор статики
Отдача статики (???)
Шаблонные теги
Сбор статики
STATIC_ROOT = "/var/www/blog.me/static/"
python manage.py collectstatic
Static Files
58
ContentTypes framework
Article
id
title
…
Photo
idtitle
…
Tag
id
title
…
TaggedItem
id
content_type_idobject_id
tag_id
59
Оптимизация
производительности
60
Схема кеширования
Ищем значение в кеше
Если находим:
возвращаем значение из кеша
Если нет:
генерируем значение
сохраняем в кеш
возвращаем значение
Кеширование
61
Условия кеширования
1. Быстрый доступ к кешу
2. Высокая вероятность использования кеша
3. Временное хранилище
Кеширование
62
Поддержка
1. Memcached
2. База данных
3. Файловая система
4. Локальная память
5. Dummy (для разработки)
Кеширование в Django
63
Уровни кеширования
1. Весь сайт
2. Контроллер
3. Часть шаблона
4. Часть данных (ручное управление)
Кеширование в Django
64
Premature optimization is the root of all evil in programming.
• Оптимизация запросов к базе данных
• Кеширование данных
• Кеширование шаблонов
Производительность Django
65
• Профилируйте запросы с Django Debug Toolbar
• Используйте правильные индексы (db_index)
• Делайте выборки по тем полям, которые вам
нужны (методы only, values and values_list)
• Не делайте лишних запросов к БД (методы
select_related и prefetch_related, тег {% with %},
внешние ключи)
• Python не должен делать работу за БД (методы
count, exist)
Производительность Django
66
Избегайте дублирования кода DRY
Делайте короче и проще KISS
Полезные советы
67
1. Авторизация и регистрация пользователей на сайте
2. Блок с последними зарегистрированными пользователями
http://tp.mail.ru/blog/Web/935.html
Домашнее задание
Спасибо за внимание
Александр Бекбулатов, a.bekbulatov@corp.mail.r
u
Recommended