2015-02-02 7 views
0

Я пытаюсь перебрать форму результатов, и я не могу не думать, что я повторно изобретаю колесо здесь.итерация результатов формы django (не в шаблоне)

filterlist = [] 

if request.POST: 
     form = FilterForm(request.POST) 
     if form.is_valid(): 
      for key, value in form.cleaned_data.iteritems(): 
       filterlist.append(key) 
       filterlist.append(value) 

Это работает, но кажется очень неудобным и создает множество других проблем. Например, значения возвращаются с помощью u ', поэтому я должен использовать value.encode («utf8»), но если значение None, оно вызывает ошибку. Так что теперь я должен проверить, нет ли этого, если не закодировать. Там должен быть лучший путь.

EDIT: То, что я пытаюсь сделать.

Я пытаюсь отфильтровать то, что показано на странице. Проблема, с которой я сталкиваюсь, заключается в том, что если значение пустое (пользователь не заполняет поле, потому что он хочет только фильтровать один объект), то я не получаю никаких результатов. Например, пользователь хочет найти все книги по имени автора «Смит», но не хочет искать жанр.

results = Books.objects.filter(author=author, genre=genre) 

Пользователь не получит никаких результатов, потому что это И поиск. Но, если пользователь ставит «Смит» для автора и «тайну» для жанра, то он работает точно так, как я хочу, только давая результаты, где оба являются истинными.

Итак, я пытаюсь устранить пустой материал путем повторения результатов формы. Как я уже сказал, я, вероятно, снова изобретаю колесо.

+0

почему вы должны преобразовать его обратно в "нормальной" строки? – GwynBleidD

+0

Лучший способ сделать что? Вы не объяснили, почему вы это делаете, или как вы используете вывод таким образом, что имеет значение, что это Unicode. –

+0

Что именно вы пытаетесь сделать? Похоже, ваш 'filterlist' - это список ключей, за которыми следуют значения. – karthikr

ответ

2

Если имена полей одинаковы в модели и формы, попробуйте следующее:

filter = {} 

if request.method == 'POST': 
    form = FilterForm(request.POST) 
    if form.is_valid(): 
     for key, value in form.cleaned_data.iteritems(): 
      if value: 
       filter[key] = value 
     results = Books.objects.filter(**filter) 

Python является один из немногих языков, имеющих именованные параметры. Вы можете собрать dict с непустыми полями формы и передать его методу фильтрации с помощью операционного менеджера kwargs**.

Например:

kwargs = {"author": "Freud"} 
results = Books.objects.filter(**kwargs) 

То же самое, как:

results = Books.objects.filter(author="Freud") 
+0

Отлично! Это именно то, что я искал. Прежде чем я увидел ваш ответ, я также нашел это [сообщение в блоге] (http://www.nomadjourney.com/2009/04/dynamic-django-queries-with-kwargs/), в котором говорится об использовании аргументов ключевых слов в фильтре , Это то, что заставляет меня любить питона. –

0

Я думаю, проблема в том, что по умолчанию форма модели недействительна, если поле формы не имеет значения, введенного пользователем, если вы каждый раз не требуете поля от пользователя, вам нужно установить обязательное поле в false в классе ModelForm в forms.py, как показано в приведенном ниже коде. Помните, что поле имеет значение ложно только в виде модели не в самой модели

class myForm(forms.ModelForm): 
    myfield_id = forms.CharField(required=False) 
    myfield_foo = forms.CharField(required=False) 
    myfield_bar = forms.CharField(required=False) 
    myfield_name = forms.CharField(required=False) 
    class Meta: 
     model = myModel 
     exclude = ('myfield_ex','myfield_file') 
     fields = ['myfield_id','myfield_foo','myfield_bar','myfield_name',] 

После формы, введенные пользователем, что вам нужно это использовать объект Q, который может быть использован для создания сложных запросов, как описано на странице Manula здесь https://docs.djangoproject.com/en/1.7/topics/db/queries/#complex-lookups-with-q

простой пример кода будет выглядеть

if form.is_valid(): 
     qgroup = [] 
     for key,value in form.cleaned_data.iteritems(): 
      if value: 
       q_name = Q(**{"%s"%format(filterKey[key]) : value}) 
       qgroup.append(q_name) 
     q = None 
     # can use the reduce as shown here qgroup = reduce(operator.or_, (Q(**{"{0}".format(filterKey[key]): value}) for (key,value) in form.cleaned_data.iteritems())) 
     for key,value in form.cleaned_data.iteritems(): 
      if value: 
       q_name = Q(**{"%s"%format(filterKey[key]) : value}) 
       qgroup.append(q_name) 
     for x in qgroup: 
       q &= x ### Or use the OR operator or 
     if q: 
      resultL = myModel.objects.filter(q).select_related() 

filterKey может выглядеть на линиях

filterKey = {'myfield_id'   : "myfield_id", 
      'myfield_foo'   : "myfield_foo__icontains", 
      'myfield_bar'   : "myfield_bar__relative_field__icontains", 
      } 
+0

есть хороший ответ на использование Q в этом вопросе, используя сокращение на @Ignacio Vazquez-Abrams здесь http://stackoverflow.com/questions/852414/how-to-dynamically- compose-an-or-query-filter-in-django – cmidi

+0

cmidi, спасибо за ваш ответ. Я уверен, что это сработает, и если бы я делал более сложные фильтры, я, вероятно, использовал бы Q-объекты. Тем не менее, я пошел с решением, предоставленным Пауло Скардин. Его решение было проще и соответствовало моим потребностям. –

Смежные вопросы