Django 使用表单输入来查询数据——应该很简单,不是(对我来说)

Posted

技术标签:

【中文标题】Django 使用表单输入来查询数据——应该很简单,不是(对我来说)【英文标题】:Django using form input to query data -- should be simple, isn't (for me) 【发布时间】:2013-01-04 18:30:54 【问题描述】:

我有一个如下所示的表单:

class AddressSearchForm(forms.Form):
    """
        A form that allows a user to enter an address to be geocoded
    """
    address = forms.CharField()

我没有存储这个值,但是,我正在对地址进行地理编码并检查以确保它有效:

def clean_address(self):
    address = self.cleaned_data["address"]
    return geocode_address(address, True)

地理编码函数如下所示:

def geocode_address(address, return_text = False):
    """ returns GeoDjango Point object for given address
        if return_text is true, it'll return a dictionary: text, coord
        otherwise it returns coord
    """ 
    g = geocoders.Google()
    try:
        #TODO: not really replace, geocode should use unicode strings
        address = address.encode('ascii', 'replace')            
        text, (lat,lon) = g.geocode(address)
        point = Point(lon,lat)
   except (GQueryError):
       raise forms.ValidationError('Please enter a valid address')
    except (GeocoderResultError, GBadKeyError, GTooManyQueriesError):
    raise forms.ValidationError('There was an error geocoding your address. Please try again')
    except:
        raise forms.ValidationError('An unknown error occured. Please try again')

    if return_text:
         address = 'text':text, 'coord':point
    else:
        address = 'coord':point

    return address

我现在需要做的是创建一个视图,该视图将使用地址数据查询模型以过滤结果。我很难弄清楚如何做到这一点。如果可能的话,我想使用 CBV。我可以用FormView来显示表单,用ListView来显示查询结果,但是如何在两者之间传递表单数据呢?

提前致谢。

更新:我知道如何查询我的模型来过滤结果。我只是不知道如何正确组合使用基于表单和基于类的视图,以便我可以访问我的过滤器的cleaned_data。例如:

流程应该是:

1) 在获取时显示表单 2)提交表格并在帖子上验证(地理编码地址) 3) 运行查询并显示结果

address = form.cleaned_data['address']
point = address['coord']
qs = model.objects.filter(point__distance_lte=(point, distance)

【问题讨论】:

【参考方案1】:

好的,这是一个基于 psjinx 方向的通用版本:

from django.views.generic.base import TemplateResponseMixin, View
from django.views.generic.edit import FormMixin
from django.views.generic.list import MultipleObjectMixin

class SearchView(FormMixin, MultipleObjectMixin, TemplateResponseMixin, View):
    """
     A View which takes a queryset and filters it via a validated form submission
    """
    queryset =  initial queryset  # you can use a model here too eg model=foo
    form_class =  form 

    def get(self, request, *args, **kwargs):
        form_class = self.get_form_class()
        form = self.get_form(form_class)
        return self.render_to_response(self.get_context_data(form=form))

    def post(self, request, *args, **kwargs):
        form_class = self.get_form_class()
        form = self.get_form(form_class)
        if form.is_valid():
            return self.form_valid(form)
        else:
            return self.form_invalid(form)    

    def form_valid(self, form):
        queryset = self.get_queryset()
        search_param = form.cleaned_data[' form field ']
        object_list = queryset.filter( filter operation =search_param)
        context = self.get_context_data(object_list=object_list, form=form, search_param=search_param)
        return self.render_to_response(context) 

【讨论】:

【参考方案2】:

这类似于此处提出的问题,或者我会说两个问题的组合。

    Django: Search form in Class Based ListView Search multiple fields of django model without 3rd party app django simple approach to multi-field search(如果您的模型与本问题中提到的模型相似)

请查看上述问题及其答案,如果您仍有任何问题,请在评论中回复此答案。


更新 1

from django.views.generic.base import TemplateResponseMixin, View
from django.views.generic.edit import FormMixin
from django.views.generic.list import MultipleObjectMixin

class SearchView(FormMixin, MultipleObjectMixin, TemplateResponseMixin, View):
    model = SomeModel
    form_class = AddressSearchForm
    template = "search.html"

    def get_queryset():
        ## Override it here
        pass

    def post():
        ## If your form is invalid then request won't reach here
        ## because FormMixin is in left most position
        ## do something
        ## call self.render_to_response()

    def form_valid():
        ## Your form is valid do something
        ## if form is invalid then next method will be called
        pass

    def form_invalid(self):
        ## form is not valid
        ## render to some template

有用的链接:

    https://github.com/django/django/blob/1.4.3/django/views/generic/base.py https://github.com/django/django/blob/1.4.3/django/views/generic/edit.py https://github.com/django/django/blob/1.4.3/django/views/generic/list.py

相关问题:

    Django - Mixing ListView and CreateView

【讨论】:

它类似于问题 1。但是,该问题的答案是使用硬编码形式的 GET。我想使用带有 POST 的 Form 类,以便我可以在该字段上进行验证。该答案还显示了使用 FBV 的解决方案,但如果可能,我想使用 CBV。我在这里找到了一些关于使用 mixins 执行类似操作的有用信息:docs.djangoproject.com/en/dev/topics/class-based-views/mixins,但没有什么能完全回答我的用例。 请看我更新的答案。我已经为您的视图添加了代码骨架。 谢谢,这真的很有帮助。我会试一试,看看我能不能让它工作。 好的。如果您遇到任何问题,请告诉我。

以上是关于Django 使用表单输入来查询数据——应该很简单,不是(对我来说)的主要内容,如果未能解决你的问题,请参考以下文章

django 编辑表单,数据怎么回显呀

有没有一种简单的方法来更改 Django 表单的日期时间输入字段的格式?

Django - 从一系列表单中抓取数据并立即保存它们

Django 模型表单不更新数据库记录

:用户账户)

Django:更新 X 数量模型的表单