I want to filter the parent value from the child model with Django reverse reference and extract the data.

Asked 2 years ago, Updated 2 years ago, 67 views

I am currently doing a tutorial on Django, but I would like to filter out the values in views.py on the model below, but I don't know how to write the code.Could you please let me know the details?

I would like to filter returnQuestion.objects.filter(pub_date__lte=timezone.now()) in IndexView on views.py so that the choice_text in the Choice model does not return any data when there is no data.How can I access the data of the Choice model that is associated with the Question model?

Also, I would like DetailView to not create a URL in the same way. I would like to add a condition to returnQuestion.objects.filter(pub_date__lte=timezone.now()).

Thank you for your cooperation.

models.py

import datetime
from django.db import models
from django.utils import timezone

# Create your models here.
# Each model inherits models.Model.
# Become a subclass of models.model.
class Question (models.Model):
  # Define class variables.Represents a database field.
  # Char field is a character field
  question_text=models.CharField(max_length=200)

  # Date and Time Fields
  pub_date=models.DateTimeField('date published')

  def__str__(self):
    # When an instance is generated and printed, it is executed.
    # In addition to using question names for objects that appear in the shell,
    # It is also used to represent objects in admin, so it needs to be added.
    return self.question_text
  
  def was_published_recently(self):
    now=timezone.now()
    # Now-datetime.timedelta(days=1) gives the date minus one day from this time.
    # 2021-05-19 23:29:56.216634 The value will look like this.
    # A method that returns True if pub_date is older than the current time and less than one day from the current time.
    return now-datetime.timedelta(days=1)<=self.pub_date<=now

Class Choice (models.Model):

  # This tells you that Choice is associated with Question.
  # Corresponds to database relationships such as many-to-one, many-to-many, and one-to-one.
  # Interactive interaction with Question←→ Choice is now possible.
  question=models.ForeignKey (Question, on_delete=models.CASCADE)
  choice_text=models.CharField(max_length=200)
  votes=models.IntegerField(default=0)

  def__str__(self):
    return self.choice_text

views.py

 from django.shortcuts import render, get_object_or_404
from django.http import HttpResponseRedirect
from django.template import context
from.models import Choice, Question
from django.urls import reverse
from django.utils import timezone
from django.views import generic


classIndexView (generic.ListView):
    template_name = 'polls/index.html'
    # Set the name when calling Question.objects.order_by('-pub_date')[:5] on the template side.
    context_object_name = 'latest_question_list'

    def get_queryset(self):
        return Question.objects.filter(pub_date__lte=timezone.now()) .order_by('-pub_date')[:5]


class DetailView (generic.DetailView):
    # Question when accessing variables in a template.
    model=Question
    template_name = 'polls/detail.html'
    def get_queryset(self):
        return Question.objects.filter(pub_date__lte=timezone.now())



classResultsView (generic.DetailView):
    model=Question
    template_name = 'polls/results.html'


defvote(request, question_id):
    question=get_object_or_404(Question, pk=question_id)
    try:
        selected_choice=question.choice_set.get(pk=request.POST ['choice'])
    except(KeyError, Choice.DoesNotExist):
        return render(request, 'polls/detail.html', {
            'question': question,
            'error_message': "You didn't select a choice.",
        })
    else:
        selected_choice.votes+=1
        selected_choice.save()
        # Retrieving and redirecting the URL of the results page with reverse.You have passed question.id as an argument.
        return HttpResponseRedirect (reverse('polls:results', args=(question.id,)))

urls.py

 from django.urls import path

from.import views
app_name = 'polls'

urlpatterns = [
    # /polls/
    path(', views.IndexView.as_view(), name='index',

    # ex: /polls/5/
    path('<int:pk>/', views.DetailView.as_view(), name='detail'),
    path('<int:pk>/results/', views.ResultsView.as_view(), name='results',
    path('<int:question_id>/vote/', views.vote, name='vote'),
]

Add

polls:index

polls:index

If you don't have a filter on, questions like test3 that don't have an option will be displayed in the list.
I want to remove it.

test3

test3

what's up

what's up

So when I added filter to views.py as below, I was able to remove test3, but for some reason, I now see two questions about what's up, which is the only one.

class IndexView (generic.ListView):
    template_name = 'polls/index.html'
    # Set the name when calling Question.objects.order_by('-pub_date')[:5] on the template side.
    context_object_name = 'latest_question_list'

    def get_queryset(self):
        return Question.objects.filter(pub_date__lte=timezone.now(), choice__choice_text_isnull=False).order_by('-pub_date')[:5]

Edit

After Editing

python python3 django

2022-09-30 16:31

1 Answers

Am I correct in understanding that you want to extract only one question with at least one choice (because the choice_text will not be None or empty)?

You can extract such questions by doing the following:

 from django.db.models import Exists, OuterRef

Question.objects.filter(
    pub_date__lte = timezone.now()
) .filter(
    Exists(Choice.objects.filter(question=OuterRef('pk')))
)

add
If you add .filter(choice_text_isnull=False) to your question, you will get the same number of questions, so you must add .distinct() to remove the duplication.

As for why, in this case, we actually do JOIN.Of all the combinations of Question and Choice, all of the pairs corresponding to Question and Choice that meet the specified conditions are extracted, and only Question is extracted from them.Therefore, the same question will appear as many of the corresponding choices.


2022-09-30 16:31

If you have any answers or tips


© 2024 OneMinuteCode. All rights reserved.