Python Django несколько атрибутов в поиске - PullRequest
2 голосов
/ 04 мая 2020

Итак, у меня есть такая форма поиска: [Доктор] [Специальность] [Город]

Это форма в HTML:

          <form data-provide="validation" data-disable="true" class="input-glass mt-7" method='POST' action='annuaire/'>
            {% csrf_token %}
              <div class="row">
                <div class="col-md-4">
                  <div class="input-group">
                    <div class="input-group-prepend">
                      <span class="input-group-text"><i class="ti-search mt-1"></i></span>
                    </div>
                    <input type="text" class="form-control" placeholder="Doctor's Name" name="kw_name">
                  </div>
                </div>
                <div class="col-md-4">
                  <div class="input-group">
                    <div class="input-group-prepend">
                      <span class="input-group-text"><i class="ti-search mt-1"></i></span>
                    </div>
                      <select class="form-control" name="kw_specialty">
                        <option value="" disabled selected>Specialty</option>
                        {% for spec in specialties %}
                          <option>{{ spec }}</option>
                        {% endfor %}
                      </select>
                  </div>
                </div>

                <div class="col-md-4">
                  <div class="input-group">
                    <div class="input-group-prepend">
                      <span class="input-group-text"><i class="ti-search mt-1"></i></span>
                    </div>
                      <select class="form-control" name="kw_city">
                        <option value="" disabled selected>City</option>
                        {% for city in cities %}
                          <option>{{ city }}</option>
                        {% endfor %}
                      </select>
                  </div>
                </div>   
              </div>
              <div class="row mt-2">
                <div class="col-md-12">
                  <button class="btn btn-lg btn-block btn-outline-light" type="submit" name="search_btn">Search</button>
                </div>
              </div>
            </form>

Прежде чем я расскажу о своем взгляде. В первую очередь, я хотел бы упомянуть мою проблему: в форме поиска есть много случаев, и пользователям не нужно заполнять все три фильтра. Но если они оставят ввод текста пустым, результаты будут ВСЕ. Я хочу, чтобы функция поиска игнорировала текстовое поле, если оно пустое (только если оно имеет значение). Кроме того, если 2 раскрывающихся списка имеют значение Null (или None), функция выдает ошибку. В любом случае, мой желаемый результат - дать 3 различных выбора на выбор, и если кто-то использует более одного атрибута, все они должны быть истинными, если выбор пуст, его следует игнорировать.

Вот мой файл views.py:

def search(request):
    val_name = request.POST.get('kw_name')
    val_city = request.POST.get('kw_city')
    val_specialty = request.POST.get('kw_specialty')
    if val_city is None:
        val_city = ''
    if val_specialty is None:
        val_specialty = ''

    if 'search_btn' in request.POST:
        if val_city is None:
            if val_name is not None:
                doctors = Doctor.objects.filter(Q(user__first_name__icontains=val_name) | 
                                                Q(user__last_name__icontains=val_name) & 
                                                Q(specialty__title__icontains=val_specialty))
            else:
                doctors = Doctor.objects.filter(Q(user__first_name__icontains=val_name) | 
                                                Q(user__last_name__icontains=val_name) & 
                                                Q(specialty__title__icontains=val_specialty))
        elif val_specialty is None:
            doctors = Doctor.objects.filter(Q(user__first_name__icontains=val_name) | 
                                            Q(user__last_name__icontains=val_name) & 
                                            Q(city__title__icontains=val_city))


    elif 'closest_btn' in request.POST:
        # deleted because not related to the problem.

    context = {
        'page_title': 'Résultats des médecins',
        'doctors': doctors,
    }
    return render(request, "dashboard/results.html", context)

Спасибо за вашу большую помощь!

PS: Я уже добавил некоторые ifs и elses в представление, чтобы попробовать решить проблему, но она все еще не работает. Иногда это дает мне результаты, которые не удовлетворяют ни одному из критериев поиска.

1 Ответ

2 голосов
/ 04 мая 2020

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

def search(request):
    val_name = request.POST.get('kw_name', '')
    filters = {
        'city__title__icontains': request.POST.get('kw_city'),
        'specialty__title__icontains': request.POST.get('kw_specialty')
    }
    filters = {k: v for k, v in filters.items() if v}
    q = Q(user__first_name__icontains=val_name) | Q(user__last_name__icontains=val_name)
    doctors = Doctor.objects.filter(q, **filters)

    context = {
        'page_title': 'Résultats des médecins',
        'doctors': doctors,
    }
    return render(request, "dashboard/results.html", context)
...