将表单输入设置为get_queryset中的变量

时间:2018-06-23 07:57:44

标签: django django-forms

AIM

我希望使用与用户输入的locations相关的所有search_text渲染 results.html

为此,我试图过滤get_quersey()中的结果,但是正在努力设置form_input变量。我当前正在使用form_input = self.request.GET.get('search_text')

CODE

models.py

import re

from django.db import models
from twython import Twython


class Location(models.Model):
    """ Model representing a Location (which is attached to Hashtag objects
    through a M2M relationship) """

    name = models.CharField(max_length=1400)

    def __str__(self):
        return self.name


class Hashtag(models.Model):
    """ Model representing a specific Hashtag serch by user """

    search_text = models.CharField(max_length=140, primary_key=True)
    locations = models.ManyToManyField(Location, blank=True)

    def __str__(self):
        """ String for representing the Model object (search_text) """
        return self.search_text

    def display_locations(self):
        """ Creates a list of the locations attached to the Hashtag model """
        return list(self.locations.values_list('name', flat=True).all())

forms.py

from django import forms
from django.forms import ModelForm
from django.utils.translation import ugettext_lazy as _

from .models import Location, Hashtag


class SearchHashtagForm(ModelForm):
    ''' ModelForm for user to search by hashtag '''

    def clean_hashtag(self):
        data = self.cleaned_data['search_text']
        # Check search_query doesn't include '#'. If so, remove it.
        if data[0] == '#':
            data = data[1:]
        return data

    class Meta:
        model = Hashtag
        fields = ['search_text',]
        labels = {'search_text':_('Hashtag Search'), }
        help_texts = { 'search_text': _('Enter a hashtag to search.'), }

views.py

from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import get_object_or_404, render
from django.urls import reverse
from django.views import generic
from django.views.generic.edit import FormView

from .models import Location, Hashtag
from .forms import SearchHashtagForm


class HashtagSearch(FormView):
    """ FormView for user to enter hashtag search query """

    template_name = 'mapping_twitter/hashtag_search_form.html'
    form_class = SearchHashtagForm

    def get_success_url(self):
        return reverse('mapping_twitter:results')

    def form_valid(self, form):
        # the method is called when valid form data has been POSTed, and returns an HttpResponse
        form.clean_hashtag()
        form.save()
        return super().form_valid(form)

    def form_invalid(self, form):
        # Check if the search_text is invalid because it already exists in the database. If so, render results.html with that search_text
        search_text = self.request.POST.get('search_text')
        if search_text and Hashtag.objects.filter(pk=search_text).exists():
            return HttpResponseRedirect(reverse('mapping_twitter:results'))
        else:
            return super(HashtagSearch, self).form_invalid(form)


class SearchResultsView(generic.ListView):
    """ Generic class-based view listing search results of locations """
    model = Hashtag
    template_name = 'mapping_twitter/results.html'

    def get_queryset(self, **kwargs):

        # ISSUE: restrict the search_text displayed on results.html to the 'search_text' entered by the user
        qs = Hashtag.objects.all()

        form_input = self.request.GET.get('search_text')

        if form_input:
            qs = qs.filter(search_text__iexact=form_input)

        return qs


    def get_context_data(self, **kwargs):
        context = super(SearchResultsView, self).get_context_data(**kwargs)
        context['search_text'] = Hashtag.objects.all()
        return context

1 个答案:

答案 0 :(得分:2)

get_context_data中,您根本不使用get_queryset方法。您只需编写另一个查询即可获取所有Hashtag对象。您应该将其重写为:

def get_context_data(self, **kwargs):
    context = super(SearchResultsView, self).get_context_data(**kwargs)
    context['search_text'] = self.get_queryset()
    return context

请注意,self.get_queryset()正在使用,而不是Hashtag.objects.all()

还请注意,使用self.request.GET.get('search_text')时,您需要在search_text视图中执行重定向时,将HashtagSearch作为GET参数传递:

class HashtagSearch(FormView):
    """ FormView for user to enter hashtag search query """

    template_name = 'mapping_twitter/hashtag_search_form.html'
    form_class = SearchHashtagForm

    def get_success_url(self):
        return '{}?search_text={}'.format(reverse('mapping_twitter:results'),  self.request.POST.get('search_text'))

UPD

但是有两个视图,我建议您使用单个ListView。只需将GET表单添加到您的results.html并简单地覆盖get_queryset方法即可:

# template 
<form method="GET" action="">
      <input type="text"  name="search_text" placeholder="Search post" value="{{ request.GET.search_text }}">
      <input type="submit" value="Search">
</form>


# view
class SearchResultsView(generic.ListView):
    """ Generic class-based view listing search results of locations """
    model = Hashtag
    template_name = 'mapping_twitter/results.html'

    def get_queryset(self, **kwargs):

        # ISSUE: restrict the search_text displayed on results.html to the 'search_text' entered by the user
        qs = Hashtag.objects.all()

        form_input = self.request.GET.get('search_text')

        if form_input:
            qs = qs.filter(search_text__iexact=form_input)

        return qs