Как объявить общие переменные для всех методов представления Django на основе классов? - PullRequest
0 голосов
/ 11 апреля 2020

У меня в приложении Django есть представление на основе классов, и оно работает нормально. Но я думаю, что это не очень хорошо закодировано, потому что это нарушает принцип DRY. В частности, у меня есть два абсолютно одинаковых объявления переменной posts_list внутри get() и post() методов:

class TopicView(View):
    def get(self, request, topic_id):
        post_form = PostForm()
        posts_list = Post.objects.filter(topic_id=self.kwargs['topic_id']).order_by('-creation_date')
        return render(request, 'discussions/topic.html', {'posts_list': posts_list,
                                                          'post_form': post_form,
                                                          'topic_id': topic_id})

    def post(self, request, topic_id):
        post_form = PostForm(request.POST)

        if post_form.is_valid():
            post = post_form.save(commit=False)
            post.author = request.user
            post.topic = Topic.objects.get(pk=topic_id)
            post.save()
            return redirect('discussions:topic', topic_id=topic_id)

        posts_list = Post.objects.filter(topic_id=self.kwargs['topic_id']).order_by('-creation_date')
        return render(request, 'discussions/topic.html', {'posts_list': posts_list,
                                                          'post_form': post_form,
                                                          'topic_id': topic_id})

Есть ли способ, как я могу объявить эту переменную как атрибут класса вместо простая переменная внутри каждого из методов? Когда я объявляю его, я использую topic_id в качестве фильтра для объектов и извлекаю topic_id из URL (self.kwargs объект, self передается как get(), так и post() в качестве входного параметра) , Это главная проблема.

1 Ответ

1 голос
/ 11 апреля 2020

Есть несколько способов реорганизовать это. Но один простой способ - поместить общий код в его собственный метод, а затем вызывать его, когда вам это нужно .. например, так:

class TopicView(View):
    def get(self, request, topic_id):
        return self.post_list_response(PostForm())

    def post(self, request, topic_id):
        post_form = PostForm(request.POST)

        if post_form.is_valid():
            post = post_form.save(commit=False)
            post.author = request.user
            post.topic = Topic.objects.get(pk=topic_id)
            post.save()
            return redirect('discussions:topic', topic_id=topic_id)

        return self.post_list_response(post_form)

    def post_list_response(self, post_form):
        topic_id = self.kwargs['topic_id']
        posts_list = Post.objects.filter(topic_id=topic_id).order_by('-creation_date')
        return render(request, 'discussions/topic.html', {
            'posts_list': posts_list,
            'post_form': post_form,
            'topic_id': topic_id
        })

Вы также можете структурировать это немного лучше / иначе, используя Django класс FormView, а не просто View.

...