在Django中创建通用搜索视图

在Django中创建通用搜索视图,django,django-generic-views,Django,Django Generic Views,我正在努力在django中创建我的自定义通用视图,以便为某些模型轻松创建搜索页面。我想这样使用它: class MyModelSearchView(SearchView): template_name = 'path/to/template.html' model = MyModel fields = ['name', 'email', 'whatever'] 这将导致一个视图,该视图在GET时返回搜索表单,在POST时返回表单和结果。 字段指定用户可以搜索MyMode

我正在努力在django中创建我的自定义通用视图,以便为某些模型轻松创建搜索页面。我想这样使用它:

class MyModelSearchView(SearchView):
    template_name = 'path/to/template.html'
    model = MyModel
    fields = ['name', 'email', 'whatever']
这将导致一个视图,该视图在GET时返回搜索表单,在POST时返回表单和结果。
字段
指定用户可以搜索
MyModel
的哪些字段

class SearchView(FormView):
    def get_form(self, form_class=None):
        # what I'v already tried:
        class SearchForm(ModelForm):
            class Meta:
                model = self.model
                fields = self.fields
        return SearchForm()

    def post(self, request, *args, **kwargs):
        # perform searching and return results
上述代码的问题是,如果某些字段没有正确填写,则不会提交表单。应该允许用户只提供部分要搜索的字段,但使用我提供的代码,使用
ModelForm
生成的表单可以防止出现这种情况(例如,因为模型中的字段不能为空)

我的问题是:

  • 是否可以基于模型生成表单以忽略此行为
  • 或者有没有更简单的方法来创建
    SearchView

如果可能的话,我不想手动编写表单

实现这一点的一种方法是在
MyModel
中的字段上设置
blank=True
,如下所示:

如果模型字段有
blank=True
,则表单字段上的
required
设置为
False
。否则,
required=True

但要使其成为通用解决方案,您不能指望能够修改模型字段。您可以在创建实例后立即将字段“
required
属性设置为
False

类搜索表单(ModelForm):
类元:
model=self.model
字段=self.fields
定义初始化(self,*args,**kwargs):
super()
对于self.fields.items()中的(字段名称,字段):
field.required=False

实现这一点的一种方法是在
MyModel
中的字段上设置
blank=True
,如下所示:

如果模型字段有
blank=True
,则表单字段上的
required
设置为
False
。否则,
required=True

但要使其成为通用解决方案,您不能指望能够修改模型字段。您可以在创建实例后立即将字段“
required
属性设置为
False

类搜索表单(ModelForm):
类元:
model=self.model
字段=self.fields
定义初始化(self,*args,**kwargs):
super()
对于self.fields.items()中的(字段名称,字段):
field.required=False

由于您正在使用ModelForm进行搜索,因此应通过覆盖
\uuuu init\uuu
方法将所有字段设置为
required=False

def get_form(self, form_class=None):
    # what I'v already tried:
    class SearchForm(ModelForm):
        class Meta:
            model = self.model
            fields = self.fields

        def __init__(self, *args, **kwargs):
            super(SearchForm, self).__init__(*args, **kwargs)
            for field in self.fields:
                self.fields[field].required = False

            return SearchForm()
虽然我建议你应该使用用户
django过滤器
,这样可以更容易更干净地过滤你的搜索。首先,您需要安装它:

pip install django-filter
然后将其添加到您的
已安装的应用程序中。之后,您可以在应用程序中创建
filters.py
文件:

# myapp/filters.py

import django_filters as filters
from .models import MyModel

MyModelFilterSet(filters.FilterSet):

    class Meta:
        model = MyModel
        fields = ['name', 'email', 'whatever']
默认情况下,它将使用
\uuuu精确的
查找进行过滤。你可以通过两种方式来改变这一点,只要看一看,然后。要知道可以使用哪些查找,请查看

创建
filters.py
文件后,可以将其添加到视图中,如ListView:

# myapp/views.py
from django.views.generic import ListView
from .filters import MyModelFilterSet
from .models import MyModel

class MyModelSearchView(ListView):
    template_name = 'path/to/template.html'
    model = MyModel

    def get_queryset(self):
        qs = self.model.objects.all()
        filtered_model_list = MyModelFilterSet(self.request.GET, queryset=qs)
        return filtered_model_list.qs

使用
django过滤器
可以做更多的事情。以下是完整信息。

因为您使用的是ModelForm进行搜索,所以应该通过覆盖
\uuu init\uuu
方法将所有字段设置为
required=False

def get_form(self, form_class=None):
    # what I'v already tried:
    class SearchForm(ModelForm):
        class Meta:
            model = self.model
            fields = self.fields

        def __init__(self, *args, **kwargs):
            super(SearchForm, self).__init__(*args, **kwargs)
            for field in self.fields:
                self.fields[field].required = False

            return SearchForm()
虽然我建议你应该使用用户
django过滤器
,这样可以更容易更干净地过滤你的搜索。首先,您需要安装它:

pip install django-filter
然后将其添加到您的
已安装的应用程序中。之后,您可以在应用程序中创建
filters.py
文件:

# myapp/filters.py

import django_filters as filters
from .models import MyModel

MyModelFilterSet(filters.FilterSet):

    class Meta:
        model = MyModel
        fields = ['name', 'email', 'whatever']
默认情况下,它将使用
\uuuu精确的
查找进行过滤。你可以通过两种方式来改变这一点,只要看一看,然后。要知道可以使用哪些查找,请查看

创建
filters.py
文件后,可以将其添加到视图中,如ListView:

# myapp/views.py
from django.views.generic import ListView
from .filters import MyModelFilterSet
from .models import MyModel

class MyModelSearchView(ListView):
    template_name = 'path/to/template.html'
    model = MyModel

    def get_queryset(self):
        qs = self.model.objects.all()
        filtered_model_list = MyModelFilterSet(self.request.GET, queryset=qs)
        return filtered_model_list.qs
使用
django过滤器
可以做更多的事情。这是完整的