Django 在get_queryset中将表单输入设置为变量 目标

Django 在get_queryset中将表单输入设置为变量 目标,django,django-forms,Django,Django Forms,我希望呈现results.html,其中包含与用户输入的搜索文本相关联的所有位置 为此,我试图在get\u query()中过滤结果,但我很难设置form\u input变量。我目前正在使用form\u input=self.request.GET.GET('search\u text') 代码 型号.py import re from django.db import models from twython import Twython class Location(models.Mod

我希望呈现results.html,其中包含与用户输入的
搜索文本相关联的所有
位置

为此,我试图在
get\u query()
中过滤结果,但我很难设置
form\u input
变量。我目前正在使用
form\u input=self.request.GET.GET('search\u text')

代码 型号.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())
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.'), }
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
forms.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())
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.'), }
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
视图.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())
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.'), }
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

get\u context\u data
中,根本不使用
get\u 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\u queryset()
正在使用而不是
Hashtag.objects.all()

另请注意使用
self.request.GET.GET('search_text')
HashtagSearch
视图中执行重定向时,需要将
search_text
作为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\u 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
#模板
#看法
类SearchResultsView(generic.ListView):
“”“列出位置搜索结果的基于类的通用视图”“”
模型=标签
template_name='mapping_twitter/results.html'
def get_queryset(自我,**kwargs):
#问题:将results.html上显示的搜索文本限制为用户输入的“搜索文本”
qs=Hashtag.objects.all()
form\u input=self.request.GET.GET('search\u text'))
如果表格输入:
qs=qs.filter(搜索\文本\ iexact=表单\输入)
返回qs

谢谢,我会设法弄清楚:)正在使用
self.request.GET.GET('search\u text')
并在
GET\u success\u url
中传递
search\u text
?或者,是否有其他更简单的方法来设置
get\u queryset
中的
form\u input
变量?@ycrad我建议您使用single
ListView
。使用单个文本框添加到result.html模板简单获取表单。并像在SearchResultsView`中那样覆盖
get\u queryset
。因为我的
表单
可以发布或获取(取决于
标签
模型中是否已经存在
搜索文本),这种方法有效吗?作为一项初步任务,我手动将
form\u输入设置为一个字符串'trump':'qs=
Hashtag.objects.filter(search\u text\uiexact='trump')
。该代码按预期执行,并返回了与
Hashtag
模型中的“trump”相关的所有
位置。因此,我假设我可以通过在
get\u queryset()
中简单地设置
form\u input
来完成目标,就像我在
form\u invalid()
中设置
search\u text
一样?