Объединение 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 3

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, потому что он попытается перейти к детальному представлению нового комментария, которого не существует, и не то, что вы хотите сделать. Таким образом, переопределение приведет вас к детальному представлению сообщения.

Есть объяснение в документации

Https://docs.djangoproject.com/en/2.0/topics/class-based-views/mixins/#an-alternative-better-solution