سؤال

create a complex query?

please help to solve the problem.

I wrote a filter to search for people. Filter contains 2 fields: "name", "birth_date"

friends_search.html:

<form class="left filter" action="{% url 'friends_search' %}" method="POST">
    {% csrf_token %}

    <div class="cell">
        <label class="label lbl_name" for="fld_name">Имя</label>

        <input class="fld_name" type="text" name="fld_name" id="fld_name" value="{% if post.fld_name %}{{ post.fld_name }}{% endif %}" />
    </div>          

    <div class="cell">
        <label class="label lbl_birth_date" for="fld_birth_date">Дата рождения</label>

        <input class="fld_birth_date datepicker" type="text" name="fld_birth_date" id="fld_birth_date" value="{% if post.fld_birth_date %}{{ post.fld_birth_date }}{% endif %}" />
    </div>                  

    <div class="cell">
        <input class="submit btn btn-default btn-block" type="submit" name="fld_submit" id="fld_submit" value="Найти" />
    </div>
</form> 

views.py:

@login_required 
def friends_search(request):
    search_result = None
    post = None

    if request.method == 'POST':    
        post = request.POST

        if request.POST.get('fld_name'):
            try:
                fld_name = request.POST.get('fld_name')
                fld_birth_date = request.POST.get('fld_birth_date')

                if q_name:
                    q_name = Q(nickname__icontains=fld_name.strip()))               

                if q_birth_date:
                    q_birth_date = Q(birth_date__icontains=fld_birth_date.strip())

                search_result = UserProfile.objects.filter(q_name).filter(q_birth_date)     #???????????????????????????    
                if not search_result:
                    search_result = 'null'
            except Exception as exc:
                search_result = 'error' 

    t = loader.get_template('friends_search.html')
    c = RequestContext(request, {
        'city_list': UserProfile.get_city_list(),
        'post': post,
    }]) 
    return HttpResponse(t.render(c)) 

models.py:

class UserProfile(User):    
    nickname = models.CharField(
        'Отображаемое имя',
        max_length=30, 
        blank=False,
    )
    birth_date = models.DateField(
        'Дата рождения',
        blank=True,
        null=True,
    )

the problem is that I can not look from two fields:

search_result = UserProfile.objects.filter (q_name). filter (q_birth_date) 

but I can search for specific fields:

search_result = UserProfile.objects.filter (q_name) 

&

search_result = UserProfile.objects.filter (q_birth_date) 

I need you to search using two fields simultaneously

هل كانت مفيدة؟

المحلول 2

Never, ever catch the base class Exception unless you handle it properly (i.e. log the error message etc.). Why? Because that except clause hides the real problems in your code and makes debugging a huge pain in the ass.

The request.POST object only contains plain strings. While fld_birth_date may be a date-formatted string, you can't filter a DateField with a string object. You need an actual date object to filter.

What you need to do is convert the string to a date object. E.g. if your date always follows the format dd-mm-YYYY, you can do:

import datetime

date = datetime.datetime.strftime(request.POST.get('fld_birth_date'), '%d-%m-%Y').date()

On top of that, you use if q_name and if q_birth_date while neither are defined at all, both raising another exception.

The if request.method == 'POST' part of your code should probably look like this:

if request.method == 'POST':
    name = request.POST.get('fld_name', None)
    birth_date_string = request.POST.get('fld_birth_date', '')
    try:
        birth_date = datetime.datetime.strftime(birth_date_string, '%d-%m-%Y').date()
    except ValueError:
        birth_date = None

    search_results = UserProfile.objects.all()
    if name:
        search_results = search_results.filter(name__icontains=name.strip())
    if birth_date:
        search_results = search_results.filter(birth_date=birth_date)

Or if you want a result if either name or birth_date matches:

from django.db.models import Q

q = Q()
if name:
    q |= Q(name__icontains=name.strip())
if birth_date:
    q |= Q(birth_date=birth_date)
search_results = UserProfile.objects.filter(q)

نصائح أخرى

UserProfile.objects.filter(q_name).filter(q_birth_date)

Will search for both ie. nickname is something AND birth_date is something.

If you want to search on either one of them or both fields you can update your view as

            fld_name = request.POST.get('fld_name')
            fld_birth_date = request.POST.get('fld_birth_date')

            qs = UserProfile.objects.filter() #get all

            if fld_name:
                qs = qs.filter(nickname__icontains=fld_name.strip()))               

            if fld_birth_date:
                qs = qs.filter(birth_date__icontains=fld_birth_date.strip())

            search_result = qs     
            if not search_result:
                search_result = 'null'

You can do away with search_result variable as qs is same as that.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top