Объединение DetailView и CreateView в Django 1.6
У меня есть 2 отдельные модели, пост и комментарий. Я использую DetailView для отображения содержимого поста, и я хочу использовать CreateView для отображения формы создания комментариев на той же странице. Каков самый чистый способ сделать это?
Единственное, что приходит на ум, - это использовать пользовательский вид, который одновременно получает объект и обрабатывает форму комментария, но это выглядит слишком грязно:
def post_detail(request, slug):
post = get_object_or_404(Post, slug=slug)
if request.POST:
form = CommentForm(request.POST)
# do comment form processing here
return render(request, "post/post_detail.html", {
"object": post, "comment_form": form})
Есть ли какой-либо чистый способ сделать это, используя представления на основе классов? Или просто какой-то способ отделить пост-код дисплея от код обработки комментариев?
2 ответа:
Одним из вариантов было бы использовать DetailView для записи и templatetag для отображения формы комментария. Пусть форма комментария отправляется в Comment CreateView, который перенаправляет в DetailView при успешном выполнении.
Тем не менее, это может быть немного некрасиво, если форма недействительна. В крайнем случае вы всегда можете вызвать DetailView или его методы из одного из методов CreateView. Но Имо, который вводит больше сцепления, а не меньше. Или у вас может быть отдельная служебная функция, которую вы можете вызвать из CreateView, чтобы отобразить сообщение, если форма комментария содержит ошибки.
Другой вариант - использовать AJAX для обработки формы комментария (в отдельном CreateView) вместо загрузки новой страницы.
В конце концов, независимо от языка или фреймворка, существует ограничение на то, насколько можно отделить представление, которое должно отображать один тип объекта и создавать другой.
Можно комбинировать
DetailView
иCreateView
. Вы используете класс дляDetailView
и другой класс дляCreateView
, а затем создаете новый класс, который наследует от представления. Этот новый класс имеет метод get и post. Метод get вызываетDetailView
, а метод post -CreateView
. Обратите внимание на использование reverse_lazy дляsuccess_url
вCreateView
. Поэтому в основном ваш код должен выглядеть примерно так:class PostView(DetailView): # your code pass ; class CommentView(CreateView): def get_success_url(self): return reverse_lazy('post_detail', kwargs={'pk': self.get_object(Post.objects.all().pk}) pass class PostCommentView(View): def get(self, request, *args, **kwargs): view = PostView.as_view() return view(request, *args, **kwargs) def post(self, request, *args, **kwargs) : view = CommentView.as_view() return view(request, *args, **kwargs)
Так что ваш urls.py укажет на
PostCommentView
Я сделал переопределение get_success_url, потому что он попытается перейти к детальному представлению нового комментария, которого не существует, и не то, что вы хотите сделать. Таким образом, переопределение приведет вас к детальному представлению сообщения.
Есть объяснение в документации