Search in multiple columns using database query in Python/Django? - django

I have a model like this:
class Info(models.Model):
tape_id = models.TextField()
name = models.TextField()
video_type = models.TextField()
date = models.DateTimeField()
director = models.CharField(max_length=255)
cameraman = models.CharField(max_length=255)
editor = models.CharField(max_length=255)
time_code = models.TextField()
tag1 = models.TextField()
User can search from tape_id, name, director and cameraman using the same search input box.
I have a search view like this:
if request.method == 'POST':
search_inp = request.POST['search_box']
tape_id = Info.objects.filter(tape_id__exact=search_inp)
res = Info.objects.filter(name__icontains=search_inp)
res = Info.objects.filter(director__icontains=search_inp)
res = Info.objects.filter(cameraman__icontains=search_inp)
total_video = res.count()
if len(res) == 0 and len(tape_id) == 0 :
result = "No videos found!!"
return render_to_response('no_results_only.html', {'result':result}, context_instance=RequestContext(request))
else:
date1 = [i.date for i in res]
date = [i.strftime("%B %d, %Y") for i in date1]
a = zip(res, date)
return render_to_response('list_videos.html', {'a':a, 'total_video':total_video}, context_instance=RequestContext(request))
return HttpResponseRedirect('/')
I thought it would work at first but it doesn't. First res variable can contain the value whereas the last res be empty which will return to the no_results.html. I want to deploy this search using the same input box. How can I make this work?

First you need to import Q to use for OR filtering:
from django.db.models import Q
Then your code should look like this:
if request.method == 'POST':
search_inp = request.POST['search_box']
res = Info.objects.filter(
Q(tape_id__exact=search_inp) |
Q(name__icontains=search_inp) |
Q(director__icontains=search_inp) |
Q(cameraman__icontains=search_inp)
)
total_video = res.count()
if len(res) == 0:
result = "No videos found!!"
return render_to_response('no_results_only.html', {'result':result}, context_instance=RequestContext(request))
else:
date1 = [i.date for i in res]
date = [i.strftime("%B %d, %Y") for i in date1]
a = zip(res, date)
return render_to_response('list_videos.html', {'a':a, 'total_video':total_video}, context_instance=RequestContext(request))
return HttpResponseRedirect('/')

It is recommended to apply OR conditions in the filter. You can refer the documentation for the syntax.
Q(question__startswith='Who') | Q(question__startswith='What')
It will make sure that you will get an unique list of objects in the result.

Related

query that must exclude me from the whole list

hi i have a problem with this filter. group_to_add takes some values ​​which should filter out the problem that I don't want those values ​​but I want the others without those.
I would like to find a way to take those values ​​and subtract them from others.
group_to_add = DatiGruppi.objects.filter(gruppi_scheda = scheda.id)
GruppiForm.base_fields['dati_gruppo'] = forms.ModelChoiceField(queryset = group_to_add)
I asked a similar question I leave the link
select filtering and removal if they are already present in the db
models
class Schede(models.Model):
nome_scheda = models.CharField(max_length=100)
utente = models.ForeignKey(User, on_delete = models.CASCADE,related_name = 'utente')
class DatiGruppi(models.Model):
dati_gruppo = models.ForeignKey(Gruppi,on_delete = models.CASCADE, related_name = 'dati_gruppo')
gruppi_scheda = models.ForeignKey(Schede,on_delete = models.CASCADE, related_name = 'gruppi_scheda')
class Gruppi(models.Model):
nome_gruppo = models.CharField(max_length=100)
I have this tab where inside there are saved data groups that contain groups that are inside a select the correct exclusion would be
group_to_add = Gruppi.objects.exclude(dati_gruppo = 147)
but instead of 147 I have to put the id of the data group of that board
view
def creazione(request, nome):
scheda = get_object_or_404(Schede, nome_scheda = nome)
eserciziFormSet = formset_factory(EserciziForm, extra = 0)
if request.method == "POST":
gruppo_form = GruppiForm(request.POST, prefix = 'gruppo')
if gruppo_form.is_valid():
gruppo = gruppo_form.save(commit = False)
gruppo.gruppi_scheda = scheda
gruppoName = gruppo_form.cleaned_data['dati_gruppo']
gruppo.save()
esercizi_formset = eserciziFormSet(request.POST, prefix='esercizi')
for esercizi in esercizi_formset:
esercizi_instance = esercizi.save(commit = False)
esercizi_instance.gruppo_single = get_object_or_404(DatiGruppi, gruppi_scheda = scheda.id, dati_gruppo = gruppoName)
esercizi_instance.save()
return HttpResponseRedirect(request.path_info)
else:
group_to_add = Gruppi.objects.exclude(dati_gruppo = 147)
GruppiForm.base_fields['dati_gruppo'] = forms.ModelChoiceField(queryset = group_to_add)
gruppo_form = GruppiForm(prefix = 'gruppo')
esercizi_formset = eserciziFormSet(prefix='esercizi')
context = {'scheda' : scheda, 'gruppo_form' : gruppo_form, 'esercizi_formset': esercizi_formset}
return render(request, 'crea/passo2.html', context)
If I understand it correctly, you should use .exclude(…) [Django-doc] not .filter(…) [Django-doc]:
group_to_add = Gruppi.objects.exclude(
dati_gruppo__gruppi_scheda=scheda
)
GruppiForm.base_fields['dati_gruppo'] = forms.ModelChoiceField(queryset=group_to_add)

How to chain a multi-feature search in Django

I have a 3 filter search for a job. One is for the job title/decription/company, one for job category for e.g Banking and one for the location for e.g New York
How do I chain the query such that it should render me the appropriate results if I specified any one filter and if I specified all 3 it should perform an AND. I tried doing it with if else, but it is becoming too long. Is there another way?
Here is my code:
views.py
if request.method == "POST":
internship_desc = request.POST['internship_desc']
internship_ind = request.POST['internship_industry']
internship_loc = request.POST['internship_location']
results = []
if internship_desc != "" and internship_desc is not None:
query_results = Internship.objects.filter(
Q(internship_title__icontains=internship_desc) |
Q(internship_desc__icontains=internship_desc) |
Q(recruiter__company_name__icontains=internship_desc)
)
if internship_ind !="" and internship_ind is not None:
if internship_desc != "" and internship_desc is not None:
query_results = query_results.objects.filter(
industry_type__iexact=internship_ind)
else:
query_results = Internship.objects.filter(industry_type__iexact=internship_ind)
if internship_loc !="" and internship_loc is not None:
if internship_desc != "" and internship_desc is not None and internship_ind !=""
and internship_ind is not None:
query_results = query_results.objects.filter(
industry_type__iexact=internship_ind)
query_results = query_results.objects.filter(
recruiter__company_region__iexact=internship_loc)
I think this is what you are trying to do.
result = Internship.objects.all()
if internship_desc:
result = result.filter(internship_desc__icontains=internship_desc)
if internship_ind:
result = result.filter(industry_type__iexact=internship_ind)
if internship_loc:
result = result.filter(recruiter__company_region__iexact=internship_loc)
Your best bet is using django_filters for these sort of filtering.
import django_filters
class InternshipFilter(django_filters.FilterSet):
company_name = django_filters.CharFilter(
field_name='recruiter__company_name',
lookup_expr='icontains'
)
class Meta:
model = Internship
fields = {
'internship_title': ['icontains'],
'internship_desc': ['icontains'],
}
and pass it to template like this:
context['filter_form'] = InternshipFilter().form
and use it in your view to return the filtered objects:
InternshipFilter(self.request.GET, queryset=Internship.objects.all()).qs
more info here

How do i disregard a django filter field if the field is empty?

So, i started to code a filtering system to my django application. It goes like this
class Person(models.Model):
first_name = models.CharField(max_length = 50)
middle_name = models.CharField(max_length = 50)
last_name = models.CharField(max_length = 50)
i wanted to filter which Person has a field containing x value if other fields are empty, like this algorithm
results = Person.objects.filter(first_name__contains = "a")
but if other fields are not empty, i want to filter it like this
results = Person.objects.filter(first_name__contains = "a", middle_name__contains = "a", last_name__contains = "a")
depending on which fields have none empty value.
my first attempt was this:
if first_name != "":
results = Person.objects.filter(first_name__contains = first_name)
if middle_name != "":
results = results.filter(middle_name__contains = middle_name)
if last_name != "":
results = results.filter(last_name__contains = last_name)
My problem here is that it filters it sequentially, so if i filter the middle_name only or last_name only, it would return me an error since results is not yet defined, could anyone help me with this?
is there an algorithm that goes like this?
results = Person.objects.filter(first_name__contains = first_name if first_name != "" else JUST REMOVE THIS FILTER)?
because if it filters a "" it would return all your data. Thank you in advance
You can build up a queryset in stages
qs = Person.objects.all()
if first_name != "":
qs = qs.filter( first_name__contains=first_name )
if middle_name != "":
qs = qs.filter( middle_name__contains=middle_name )
if last_name != "":
qs = qs.filter( last_name__contains=last_name )
You can do much the same with Q objects for OR-type matching (it's a bit fiddlier)
qs = Person.objects.all()
q = None
for op, name in (( "first_name__contains", first_name),
( "middle_name__contains", middle_name),
( "last_name__contains", last_name)) :
if name != "":
if q:
q = q | Q( **{ op: name} )
else
q = Q( **{ op: name} )
if q:
qs = qs.filter(q)
In simple words, you want to do an ORing between first_name, last_name, and middle_name, when querying for a specific provided string.
I highly recommend you using Q Object Lookups in Django
your code will be simpler like the following:
text = 'a'
results = Person.objects.filter(Q(first_name__contains=text) | Q(middle_name__contains=text) | Q(last_name__contains=text))

Django 'Post' object has no attribute '__getitem__'

I'd like to append a quoted pots to user's post before saving it.
Here is the view:
#login_required
def quote_reply(request, quote_id):
tform = PostForm()
print 'quote_id is:' + quote_id
quote = Post.objects.get(pk = quote_id)
topic_id = quote.topic_id
topic = Topic.objects.get(id= topic_id)
print 'quote is' + quote.body
args = {}
if request.method == 'POST':
post = PostForm(request.POST)
if post.is_valid():
p = post.save(commit = False)
p.topic = topic
p.title = post.cleaned_data['title']
p.body = post.cleaned_data['body']
p['body'].append(str(quote)) #problematic line
p.creator = request.user
p.user_ip = request.META['REMOTE_ADDR']
if len(p.title)< 1:
p.title=p.body[:60]
p.save()
tid = int(topic_id)
return HttpResponseRedirect('/forum/topic/%s' % topic_id)
else:
args.update(csrf(request))
args['form'] = tform
args['post'] = quote
args['topic_id'] = topic_id
return render_to_response('myforum/qoute_reply.html', args,
context_instance=RequestContext(request))
I tried also tried
p['body'].append(unicode(quote))
but gives the same error.
Appreciate your help to resolve this.
Update: Here is the Post model
class Post(models.Model):
title = models.CharField(max_length=75, null=True, blank=True)
created = models.DateTimeField(auto_now_add=True)
creator = models.ForeignKey(User, blank=True, null=True)
updated = models.DateTimeField(auto_now=True)
topic = models.ForeignKey(Topic)
body = models.TextField(max_length=10000)
user_ip = models.GenericIPAddressField(blank=True, null=True)
def __unicode__(self):
return u"%s - %s - %s" % (self.creator, self.topic, self.title)
def short(self):
return u"%s - %s\n%s" % (self.creator, self.title, self.created.strftime("%b %d, %I:%M %p"))
short.allow_tags = True
Not sure what to do.
The main problem here is that p is a model instance, which does not support dict-style attribute access syntax. To access the post attribute, use the standard dot syntax, p.post.
The second problem is that you can't use append to change a Unicode or string object - they're immutable. Instead, you should create a new Unicode object containing the content you want and assign that. For instance:
p.post = post.cleaned_data['body'] + unicode(quote)

IntegrityError error while saving value of to foreign key in django

Hey folks i am getting integrity error while saving my views .Please tell me what i am doing wrong
Here is my django model
class Ruleinfo(models.Model):
rule = models.IntegerField(null=False)
From = models.IPAddressField(null=True)
to = models.IPAddressField(null=True)
priority = models.ForeignKey('Priority',related_name='pri_no')
cisp =models.ForeignKey('Priority',related_name = 'CISP_no')
def __unicode__(self):
return u'%s' %(self.rule)
class Priority(models.Model):
pri = models.IntegerField(null = True)
Ruleno = models.ForeignKey('Ruleinfo',related_name = 'ruleno_no')
CISP = models.IntegerField(null = True)
def __unicode__(self):
return u'%s ' % (self.priority)
My model form is looking like .
class RuleInfoForm(ModelForm):
class Meta:
model = Ruleinfo
fields = ("rule","From","to")
here is my views.py
def multiwanrule_info(request):
data = {}
no_of_isp = MultiWAN.objects.all()
try:
form = RuleInfoForm(request.POST)
except:
pass
print "----------------------------printing form"
print form
if form.is_valid():
rl_frm = form.save(commit=False)
get_priorities = request.POST.getlist('priority')
get_cisp_info = request.POST.getlist('cisp')
rule_object = Ruleinfo()
for get_pri,get_ci in zip(get_priorities,get_cisp_info,):
pri_object = Priority.objects.get_or_create(Ruleno = rule_object)
pri_object.pri = get_pri
pri_object.CISP = get_ci
rl_frm.save()
else:
form = RuleInfoForm()
data['form'] = form
data['number_of_isp'] = no_of_isp
return render_to_response('networking.html',data)
I am getting the above error along this
networking_priority.Ruleno_id may not be NULL
help me out so that i could get back on track .
rule_object = Ruleinfo()
This just instantiates a new model object. It is not saved or assigned values. Since it is not saved it does not have an id value.
assigning your rule_object values: rule, from, to, priority, and cisp values, should fix your problem.