2015-03-31 2 views
0

На прошлой неделе я столкнулся с задачей, связанной с listView и Forms в Django, мне было интересно, как лучше всего (+ Pythonic) реализовать форму поиска внутри ListView после того, как я прочитал 1 и 2 У меня появилась основная идея, поэтому я реализовано первое решение, и я хотел бы получить вашу обратную связь. Цель здесь - выполнить запрос по коду и сохранить запрос, чтобы синхронизировать его с разбиением на страницы.Каков наилучший способ реализации формы запроса в Django ListView?

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) 

Что вы думаете г uys ?, я уверен, что есть много других способов.

+1

Почему вы используете сеанс? Разве '' '' query_inscription''' еще не существует в параметрах GET, даже когда вы находитесь между ними? – schillingt

+0

Я отправляю форму по почте, поэтому у меня есть только параметр request_inscription в первый раз. Я сохраняю query_inscription в переменной сеанса, чтобы сохранить правильную разбивку на страницы. Единственным параметром, который я использую get, является «страница». – jorlugaqui

ответ

1

На прошлой неделе я столкнулся с аналогичной проблемой. Моя модель была обычным пользователем 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. Вам не нужно сохранять значение своего запроса в сеансе, как сказано в его комментарии. Все, что вам нужно, - это запустить форму с запросом на поиск.

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 %} 

Вот и все!

+0

Спасибо @BernarditoLuis, я просто хотел избежать, чтобы передать поисковый запрос в ссылке на страницу. Однако ваше решение довольно понятно :) – jorlugaqui