在 Django ListView 中实现查询表单的最佳方式是什么?
What is the best way to implement Query Form in Django ListView?
上周我在 Django 中遇到了一个与 listView 和 Forms 相关的任务,我想知道在 ListView 中实现搜索表单的最佳方式(+Pythonic)是什么,在我阅读 1 and 2 之后我明白了一个主要想法,所以我实施了第一个解决方案,我想收到您的反馈。这里的目标是通过代码字段执行查询并保留查询集以便与分页同步。
forms.py
class InscriptionQueryForm(forms.Form):
query_inscription = forms.CharField(label=_('Code'), required=False)
models.py
class Inscription(models.Model):
code = models.CharField(max_length=10, unique=True)
start_on = models.DateField()
finish_on = models.DateField()
active = models.BooleanField(default=False)
views.py
class InscriptionListView(ListView, FormMixin):
model = Inscription
paginate_by = 4
context_object_name = 'inscriptions'
form_class = InscriptionQueryForm
form = None
object_list = None
search = False
def get_queryset(self):
form = self.form_class(self.request.POST)
if form.is_valid() and self.request.method == 'POST':
self.request.session['query_inscription'] = \
form.cleaned_data['query_inscription']
return self.model.objects.filter(
code__icontains=form.cleaned_data['query_inscription']).\
order_by('-active')
if self.request.method == 'GET' and \
'query_inscription' in self.request.session:
return self.model.objects.filter(
code__icontains=self.request.session.get(
'query_inscription', '')).order_by('-active')
return self.model.objects.all().order_by('-active')
def get(self, request, *args, **kwargs):
# From ProcessFormMixin
self.form = self.get_form(self.form_class)
# From BaseListView
if self.request.GET.get('page', False) or self.search:
self.object_list = self.get_queryset()
else:
self.search = False
self.object_list = self.model.objects.all().order_by('-active')
if 'query_inscription' in self.request.session:
del self.request.session['query_inscription']
context = self.get_context_data(
object_list=self.object_list, form=self.form)
return self.render_to_response(context)
def post(self, request, *args, **kwargs):
self.search = True
return self.get(request, *args, **kwargs)
大家怎么看?我相信还有很多其他更好的方法。
上周我遇到了类似的问题。我的模型是一个普通的 django 用户。然而,这里可以使用相同的方法。
我猜您想使用搜索字段搜索铭文并对结果进行分页。当您浏览这些页面时,您希望看到搜索查询的结果。
您的 models.py 保持原样。我们将修改 forms.py 因为它将能够初始化搜索请求
class InscriptionQueryForm(forms.Form):
query_inscription = forms.CharField(label='Code', required=False)
def __init__(self, query_inscription):
super(InscriptionQueryForm, self).__init__()
self.fields['query_inscription'].initial = query_inscription
现在让我们看看views.py。您不需要像 schillingt 在他的评论中提到的那样在会话中存储您的请求值。您只需使用搜索请求初始化您的表单。
class InscriptionListView(ListView):
model = Inscription
paginate_by = 4
context_object_name = 'inscriptions'
query_inscription = ''
def get_context_data(self, **kwargs):
context = super(InscriptionListView, self).get_context_data(**kwargs)
context['form'] = InscriptionQueryForm(self.query_inscription)
# this parameter goes for the right pagination
context['search_request'] = ('query_inscription=' +
unicode(self.query_inscription))
return context
def get(self, request, *args, **kwargs):
self.query_inscription = request.GET.get('query_inscription', '')
return super(InscriptionListView, self).get(request, *args, **kwargs)
def get_queryset(self):
if not self.query_inscription:
inscription_list = Inscription.objects.all()
else:
inscription_list = Inscription.objects.filter(
code__icontains=self.query_inscription)
return inscription_list.order_by('-active')
最后要提到的是分页
inscription_list.html
<form action="">
{{ form.as_p }}
<input type="submit" value="search"/>
</form>
<hr/>
{% if inscriptions %}
{% for inscription in inscriptions %}
{{ inscription.code }} {{ inscription.start_on }} {{ inscription.finish_on }}
<hr/>
{% endfor %}
{% if is_paginated %}
<div class="pagination">
<span class="page-links">
{% if page_obj.has_previous %}
<a href="?{{ search_request }}&page={{ page_obj.previous_page_number }}">previous</a>
{% endif %}
<span class="page-current">
Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}
</span>
{% if page_obj.has_next %}
<a href="?{{ search_request }}&page={{ page_obj.next_page_number }}">next</a>
{% endif %}
</span>
</div>
{% endif %}
{% endif %}
就是这样!
上周我在 Django 中遇到了一个与 listView 和 Forms 相关的任务,我想知道在 ListView 中实现搜索表单的最佳方式(+Pythonic)是什么,在我阅读 1 and 2 之后我明白了一个主要想法,所以我实施了第一个解决方案,我想收到您的反馈。这里的目标是通过代码字段执行查询并保留查询集以便与分页同步。
forms.py
class InscriptionQueryForm(forms.Form):
query_inscription = forms.CharField(label=_('Code'), required=False)
models.py
class Inscription(models.Model):
code = models.CharField(max_length=10, unique=True)
start_on = models.DateField()
finish_on = models.DateField()
active = models.BooleanField(default=False)
views.py
class InscriptionListView(ListView, FormMixin):
model = Inscription
paginate_by = 4
context_object_name = 'inscriptions'
form_class = InscriptionQueryForm
form = None
object_list = None
search = False
def get_queryset(self):
form = self.form_class(self.request.POST)
if form.is_valid() and self.request.method == 'POST':
self.request.session['query_inscription'] = \
form.cleaned_data['query_inscription']
return self.model.objects.filter(
code__icontains=form.cleaned_data['query_inscription']).\
order_by('-active')
if self.request.method == 'GET' and \
'query_inscription' in self.request.session:
return self.model.objects.filter(
code__icontains=self.request.session.get(
'query_inscription', '')).order_by('-active')
return self.model.objects.all().order_by('-active')
def get(self, request, *args, **kwargs):
# From ProcessFormMixin
self.form = self.get_form(self.form_class)
# From BaseListView
if self.request.GET.get('page', False) or self.search:
self.object_list = self.get_queryset()
else:
self.search = False
self.object_list = self.model.objects.all().order_by('-active')
if 'query_inscription' in self.request.session:
del self.request.session['query_inscription']
context = self.get_context_data(
object_list=self.object_list, form=self.form)
return self.render_to_response(context)
def post(self, request, *args, **kwargs):
self.search = True
return self.get(request, *args, **kwargs)
大家怎么看?我相信还有很多其他更好的方法。
上周我遇到了类似的问题。我的模型是一个普通的 django 用户。然而,这里可以使用相同的方法。
我猜您想使用搜索字段搜索铭文并对结果进行分页。当您浏览这些页面时,您希望看到搜索查询的结果。
您的 models.py 保持原样。我们将修改 forms.py 因为它将能够初始化搜索请求
class InscriptionQueryForm(forms.Form):
query_inscription = forms.CharField(label='Code', required=False)
def __init__(self, query_inscription):
super(InscriptionQueryForm, self).__init__()
self.fields['query_inscription'].initial = query_inscription
现在让我们看看views.py。您不需要像 schillingt 在他的评论中提到的那样在会话中存储您的请求值。您只需使用搜索请求初始化您的表单。
class InscriptionListView(ListView):
model = Inscription
paginate_by = 4
context_object_name = 'inscriptions'
query_inscription = ''
def get_context_data(self, **kwargs):
context = super(InscriptionListView, self).get_context_data(**kwargs)
context['form'] = InscriptionQueryForm(self.query_inscription)
# this parameter goes for the right pagination
context['search_request'] = ('query_inscription=' +
unicode(self.query_inscription))
return context
def get(self, request, *args, **kwargs):
self.query_inscription = request.GET.get('query_inscription', '')
return super(InscriptionListView, self).get(request, *args, **kwargs)
def get_queryset(self):
if not self.query_inscription:
inscription_list = Inscription.objects.all()
else:
inscription_list = Inscription.objects.filter(
code__icontains=self.query_inscription)
return inscription_list.order_by('-active')
最后要提到的是分页 inscription_list.html
<form action="">
{{ form.as_p }}
<input type="submit" value="search"/>
</form>
<hr/>
{% if inscriptions %}
{% for inscription in inscriptions %}
{{ inscription.code }} {{ inscription.start_on }} {{ inscription.finish_on }}
<hr/>
{% endfor %}
{% if is_paginated %}
<div class="pagination">
<span class="page-links">
{% if page_obj.has_previous %}
<a href="?{{ search_request }}&page={{ page_obj.previous_page_number }}">previous</a>
{% endif %}
<span class="page-current">
Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}
</span>
{% if page_obj.has_next %}
<a href="?{{ search_request }}&page={{ page_obj.next_page_number }}">next</a>
{% endif %}
</span>
</div>
{% endif %}
{% endif %}
就是这样!