Reputation: 237
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
Upvotes: 0
Views: 58
Reputation: 53699
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)
Upvotes: 1
Reputation: 53386
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.
Upvotes: 2