简体   繁体   中英

How to set the question that an answer will be associated with?

I an building a Q&A website for practice and I want each answer to be associated with an author and a question, I managed to associate it with the user but I can not figure out the question part.

Here is the code:

models.py:

class Questiont(models.Model):
    question = models.CharField(max_length=200)
    description = models.TextField(null = True , blank=True)
    date_posted =models.DateTimeField(default=timezone.now)
    author = models.ForeignKey(User,on_delete=models.CASCADE)

    def __str__(self):
        return self.question

class Answer(models.Model):
    content = models.TextField(null=True,blank=True)
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    author = models.ForeignKey(User,on_delete=models.CASCADE)
    date_posted = models.DateTimeField(default=timezone.now)

views.py(where the association should take place):

class CreateAnswer(LoginRequiredMixin,CreateView):
    model = Answer
    fields = ['content']
    context_object_name = 'answer'
    success_url = reverse_lazy('Lisk home')


    def form_valid(self, form):
        form.instance.question = ?????????
        form.instance.author = self.request.user
        return super().form_valid(form)

How can I specify the question( form.instance.question ) that the answer is specified to? Granted that the ID of the question being answered is in the URL of the answering page(template).

The url is like this:

http://127.0.0.1:8000/question/22/createanswer/

urls.py(not root):

politicspost=questioon (sorry if this is messy)

 path('politics_topic/', views.Politics_topic.as_view(template_name='lisk_templates/politics_topic_template.html'),
         name='Politics_topic'),
    path('ask_politics/', views.Questionpolitics.as_view(template_name='lisk_templates/ask_politics_template.html'),
         name='ask_politics'),
    path('politicspost/<int:pk>/',views.Politics_post_details.as_view(template_name='lisk_templates/politics_post_details.html'),
         name='politics_post_details'),
    path('politicspost/<int:pk>/update/',views.Updatepolitics.as_view(template_name='lisk_templates/ask_politics_template.html'),
         name='updatepoliticspost'),
    path('politicspost/<int:pk>/delete/',views.Deletepoliticspost.as_view(template_name='lisk_templates/delete_politics_confirmation.html'),name ='deletepoliticspost'),

    #ANSWER
    path('politicspost/<int:id>/createanswer/',views.CreateAnswer.as_view(template_name='lisk_templates/createanswer.html'),name = 'createanswer'),
    path('answers/',views.Answerslist.as_view(template_name='lisk_templates/politics_post_details.html'),name ='answers')

Thanks in advance.

Seeing that you are already using a class-based view, I will suggest using the built-in UpdateView . In that way, you don't have to do the extra handlings as you will be required to enter the primary key of the question in the URL (which the answers are going to be a part of) and Django will fetch the corresponding question itself.

Although, to me, your view name is misleading. Yes, you are creating an answer, but you are also updating the parent question object, and I believe that led you to choose Createview over Updateview - which the second one will be more favorable.

Basically, you will be adding an answer, but it's more convenient to have it handled under a question object.

When you're dealing with multiple objects in one view / url path, it's always convenient to use descriptive names: use question_id not id , so that it differs from answer_id , which you may need later on: /politics_post/<int:question_id>/answers/<int:answer_id>/change/ for example.

These names are just labels. They are saved in the kwargs attribute of the CreateView. So /politics_post/42/answers/59/change will create: CreateView.kwargs = {'question_id': 42, 'answer_id': 59} . More information in the docs .

As @crimsonpython24 says, you can do this from a question perspective, but it's equally fine to use Answer as your model. Now, I'm going to assume that you changed the url to have a question_id. You would change your create view like this:

class CreateAnswer(LoginRequiredMixin,CreateView):
    model = Answer
    fields = ['content']
    context_object_name = 'answer'
    success_url = reverse_lazy('Lisk home')
    question_kwarg = 'question_id'


    def form_valid(self, form):
        try:
            question = Question.objects.get(pk=self.kwargs[self.question_kwarg])
        except Question.DoesNotExist:
            form.add_error(None, 'Invalid question')
            return self.form_invalid(form)
        form.instance.question = question
        form.instance.author = self.request.user
        return super().form_valid(form)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM