Лучший способ сделать форму поиска модели? - PullRequest
5 голосов
/ 10 июля 2009

У меня есть эта модель:

class Aircraft(models.Model):
    model       =   models.CharField(max_length=64, blank=True)
    type        =   models.CharField(max_length=32)
    extra       =   models.CharField(max_length=32, blank=True)
    manufacturer    =   models.CharField(max_length=32)
    engine_type =   models.IntegerField("Engine Type", choices=ENGINE_TYPE, default=0)
    cat_class   =   models.IntegerField("Category/Class", choices=CAT_CLASSES, default=1)

И у меня есть страница «Найти самолет», где пользователю предоставляется форма, в которой он может вводить данные, которые будут использоваться для поиска всех самолетов, которые соответствуют его критериям. Например, пользователь может ввести «Боинг» в текстовое поле и «Джет» в поле engine_type, и он отобразит все самолеты Боинг в базе данных. То, как я делаю это сейчас, с помощью этой формы:

class AircraftSearch(ModelForm):
    search = forms.CharField(max_length=100, required=False)
    class Meta:
        model = Aircraft
        fields = ('engine_type', 'cat_class', )

И затем (излишне сложное) представление, которое преобразует данные из этой формы в набор filter(), которые добавляются к Aircraft.objects.all(). (Вместо того, чтобы иметь 4 отдельных поля поиска для каждого CharField, я объединил их все в одно поле поиска.)

Это все работает, но с одной проблемой. Если пользователь хочет исключить тип двигателя из своих критериев поиска, он ввернут, потому что «Любой» не является допустимым выбором для поля типа двигателя. Мне нужно будет создать новое поле / виджет для типа двигателя и категории / класса, включающий «Любой», что в первую очередь побеждает цель использования вида модели

Мне любопытно. Есть ли способ лучше? Это кажется очень распространенной задачей, которая уже была решена кем-то другим, но поиск в Google ничего не дает.

Ответы [ 2 ]

8 голосов
/ 10 июля 2009

Функционально, «любой» будет достигнут, просто не включая этот конкретный вектор поиска в фильтрацию.

Как правило, ModelForm s для создания и редактирования моделей; в этом случае, я не уверен, что это поможет вам гораздо больше, чем обычная форма:

class AircraftSearch(forms.Form):
    search = forms.CharField(max_length=100, required=False)
    engine_type = forms.ChoiceField(choices=ENGINE_TYPE)
    cat_class = forms.ChoiceField(choices=CAT_CLASS)

Чтобы выполнить поиск, вы просто фильтруете, когда поля не пустые:

def search(request):
    if request.method == 'POST':
        results = Aircraft.objects.all()

        search = request.POST.get('search', None)
        if search:
            results = results.filter(Q(model=search)|Q(type=search)|Q(extra=search)|Q(manufacturer=search))

        engine_type = request.POST.get('engine_type', None)
        if engine_type:
            results = results.filter(engine_type=engine_type)

        cat_class = request.POST.get('cat_class', None)
        if cat_class:
            results = results.filter(cat_class=cat_class)

        return render_to_response('aircraft.html', {'form': AircraftSearch(request.POST), 'aircraft': results})

    return render_to_response('aircraft.html', {'form': AircraftSearch()})
3 голосов
/ 10 июля 2009

Я думаю, вы не должны использовать ModelForm.
Типичный сценарий использования ModelForm - манипулирование данными, а не их поиск.

Вместо этого создайте совершенно новую форму, основанную на нужных полях и с флажками, которые пользователь (де) выберет, чтобы отключить поиск в определенном поле.
Конечно, вы все равно должны использовать варианты, определенные в модели, просто импортируя файл и используя этот список.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...