Archive for the ‘generic views’ tag
create_object и дополнительные поля создаваемого объекта
Среди убойных возможностей django хочется отметить generic views. Поначалу я их не заметил и практически никак не использовал, но после прочтения этой статьи присмотрелся внимательней и проникся. Сейчас иногда получается, что они напрямую или через функции-обертки реализуют почти весь view-слой сайта.
Одной из проблем, с которой я столкнулся при использовании generic views — это вопрос о том, как добавить в объект, создаваемый через create_object, дополнительные данные. Например, при создании новой статьи хочется автоматом прописывать залогиненного пользователя, который её написал. Поскольку create_object создает и использует ModelForm внутри себя, то способ передачи request.user в эту форму не совсем очевиден.
А способ-то довольно прост — достаточно описать ModelForm внутри функции-обертки над create_object. Если в этом описании переопределить метод save(), то request будет в пределах видимости.
Вот наша модель (models.py):
from django.contrib.auth.models import User
from django.db import models
class Article(models.Model):
title = models.CharField(max_lentg=100)
content = models.TextField()
author = models.ForeignKey(User)
Вот форма (forms.py):
from django import forms
from articles.models import Article
class ArticleForm(forms.ModelForm):
class Meta:
model = Article
fields = ('title', 'content', )
А вот та самая функция обертка:
from django.views.generic.create_update import create_object
from articles.forms import ArticleForm
def create_article(request):
class AddArticleForm(ArticleForm):
def save(self):
article = super(AddArticleForm, self).save(commit=False)
article.author = request.user
article.save()
return article
return create_object(request, form_class=AddArticleForm, login_required=True)
direct_to_template вместо render_to_response
Везде и всюду для загрузки и рендеринга шаблона для последующей отдачи браузеру рекомендуется использовать функцию render_to_response. Однако, если её использовать правильно, а не так, как написано в туториале, то помимо самой функции приходится импортировать еще и RequestContext, и явно передавать его:
from django.shortcuts import render_to_response
from django.template import RequestContext
def my_view(request):
return render_to_response('my_template.html',
{'object_list': SomeModel.objects.all()},
context_instance=RequestContext(request))
То есть по факту получается, что это не такой уж и shortcut. Такой многословный код приводит к тому, что многие программисты делают собственные версии render_to_response, которые одним из параметров принимают request. А особо продвинутые джангонавты даже мудрят с декораторами.
Однако в django уже есть функция, которая фактически делает то же самое. Смотрите сами:
from django.views.generic.simple import direct_to_template
def my_view(request):
return direct_to_template(request, 'my_template.html',
{'object_list': SomeModel.objects.all()})
Все generic views правильно работают с RequestContext и direct_to_template тут не исключение.