Web осень 2013 лекция 8

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

email

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

42

Class Based Views

http://ccbv.co.uk/

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