How best to capture variables from within a for-loop in Django template

江枫思渺然 提交于 2021-01-07 02:48:49

问题


I have two querysets: type and age_group.

type queryset: <QuerySet [<Type: Cat>, <Type: Dog>, <Type: Other>]>

age_group queryset: <QuerySet [<AgeGroup: Young>, <AgeGroup: Baby>, <AgeGroup: Adult>, <AgeGroup: Senior>]>

I loop through these from within my template form so that I can grab the pk when one has been selected, but I cannot capture the variable from within the for loop. How do I capture a variable from within a for loop when using Django? I want to capture pk for type and pk for age_group and then use both to filter the model Animal and return a filtered list that matches the user's preferences. A directory search function, essentially.

Template:

    {% extends 'base.html' %}

    {% block content %}
        <h1>Animal Search</h1>

    <form class="form-inline" action= '.' method="post">
            {% csrf_token %}
       
         <select name= "TypeSearch" class="custom-select my-1 mr-sm-2" id="animal_list_type">
         <label class="sr-only type" for="animal_list_type">SEARCH</label>
             {% for i in animal_type_list %}
                    <option value="{{i.pk}}">{{i}}</option> #how to capture the selected pk??
            {% endfor %}
         </select>

         <select name="AgeSearch" class="custom-select my-1 mr-sm-2" id="animal_list_ageGroup">
         <label class="sr-only ageLabel" for="animal_list_ageGroup">SEARCH</label>
             {% for j in age_group_list %}
                    <option value="{{j.pk}}">{{j}}</option> #how to capture the selected pk??
            {% endfor %}
         </select>

        <input type="submit" value="SEARCH" onclick="window.location='{% url 'animals:matches_list' pk=4 %}'; return false;">
        <input type="submit" onclick="window.location='{% url 'animals:animals' %}'; return false;" value="Cancel">
    </form>

    {% endblock %}
  

views.py

    class VisitorSearchView(View):
    def get(self, request, pk=None):
        #first tried ModelForm but couldn't figure out how to capture and iterate through one field of value options at a time
        animalList = Animal.type.get_queryset()
        animalList2 = Animal.ageGroup.get_queryset()
        context = {
            "animal_type_list": animalList,
            "age_group_list": animalList2
            }

        return render(request, "animals/landing.html", context)

    def post(self, request, pk=None):
        theForm1 = AnimalSearchForm(request.POST)
        success_url = reverse_lazy('animals:matches_list')
        print(pk)
        print(theForm1)
        filler_for_now = Animals.objects.all()
        context = {
                'theMatches': filler_for_now
            }
        return render(request, success_url, context)

model.py

    class Animal(models.Model):
        name = models.CharField(max_length=500, blank=False, null=False)
        type = models.ForeignKey(Type, on_delete=models.SET_NULL, blank=False, null=True)
        ageGroup = models.ForeignKey(AgeGroup, max_length=300, on_delete=models.SET_NULL, blank=False, null=True)
        age = models.PositiveIntegerField(blank=False, null=False)
        sex = models.CharField(max_length=100, choices=SEX, blank=False, null=False, default='NA')
        breedGroup = models.ManyToManyField(BreedGroup, blank=False)
        breed = models.ManyToManyField(Breed, blank=False)
        tagLine = models.CharField(max_length=300, blank=False, null=False)
        goodWithCats = models.BooleanField(blank=False, null=False, default='Not Enough Information')
        goodWithDogs = models.BooleanField(null=False, blank=False, default='Not Enough Information')
        goodWKids = models.BooleanField(null=False, blank=False, default='Not Enough Information')

urls.py

    app_name = 'animals'

urlpatterns = [

    path('', views.AnimalListView.as_view(), name='animals'),
    path('landing/', views.VisitorSearchView.as_view(), name='landing'),
    path('matches/<int:pk>', views.VisitorSearchView.as_view(), name='matches_list'),

]

forms.py #(originally tried to use ModelForm but couldn't figure out how to grab the pk for both chooseType and chooseAge fields so chose to try to just use querysets from view)

    class AnimalSearchForm(ModelForm):
    chooseType = ModelChoiceField(queryset=Animal.objects.values_list('type', flat=True).distinct(),empty_label=None)
    chooseAge  = ModelChoiceField(queryset=Animal.objects.values_list('ageGroup', flat=True).distinct(), empty_label=None)
    class Meta:
        model = Animal
        exclude = '__all__'

Outside of Django, this would be a simple problem to solve. How do I capture a variable from within a for loop when using Django? I have tried to instantiate a variable outside the for-loop and then update that based off selection from within, but it seems that this cannot be done via the template...?


回答1:


Well the real issue here is that you really should be using FormView to display a form together with DetailView to display model data, in this particular case you should do something like this:

views.py

from django.views.generic import FormView, DetailView

class VisitorSearchView(FormView, DetailView):
    model = Animal
    template_name = 'animals/landing.html'
    form_class = AnimalSearchForm

    def form_valid(self, form):
        data = form.cleaned_data # Dict of submitted data
        # handle form validation and redirect

    def get_context_data(self, request):
        context = super(VisitorSearchView, self).get_context_data(**kwargs)
        animals = Animal.objects.all() # or use a custom filter
        context['animals'] = animals
        return context

Then in your landing.html

where you want a list of animal types:

{% for animal in animals %}
    {{ animal.type }}
{% endfor %}

and where you want a list of animal ages:

{% for animal in animals %}
    {{ animal.age }}
{% endfor %}

declare your form normally as you would.




回答2:


I think you need to remove the dot from the action attribute. Empty string in action use the current URL for form submission. Form opening line will be like

 <form class="form-inline" action= '' method="post">


来源:https://stackoverflow.com/questions/65483354/how-best-to-capture-variables-from-within-a-for-loop-in-django-template

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!