search multiple fields django - python

I'm trying to build a search system, and I want to search by multiple fieldsname, state, city, in my django models. I wrote the below code, yet I've been unable to figure out how to go about it. I use Q but it seems not working:
views.py:
def data_consulting(request):
if request.method == 'POST':
form = FilterForm(request.POST)
if form.is_valid():
conditions = [('toBuy', form.cleaned_data['toBuy']), ('name__contains', form.cleaned_data['searchName']),(('price__gte', form.cleaned_data['searchPriceBegin']), ('price__lte',form.cleaned_data['searchPriceEnd'])),(('calories__gte', form.cleaned_data['searchCalorieBegin']), ('calories__lte', form.cleaned_data['searchCalorieEnd'])), (('date__gte',form.cleaned_data['DateBegin']), ('date__lte', form.cleaned_data['DateEnd']))]
all_products = Product.objects.filter(reduce(operator.or_, [Q(condition) for condition in conditions]))
send = True
all_products = Product.objects.filter(reduce(operator.or_, [Q(condition) for condition in conditions]))
else:
form = FilterForm()
all_products = Product.objects.all()
return render(request, 'mealManager/data_consulting.html', locals())

Have a think about what
reduce(operator.or_, [Q(condition) for condition in conditions])
becomes with e.g. [('toBuy', 'bread'), ('name__contains', 'bread')]. It becomes
Q(('toBuy', 'bread')) | Q(('name_contains', 'bread'))
which is obviously wrong syntax, since Q rather needs kwargs than a tuple:
Q(toBuy='bread') | Q(name__contains='bread')
that's where the ** operator comes to the rescue. If you get data like this:
[{'toBuy': 'bread'}, {'name__contains': 'bread'}]
which may be accomplished by simply changing the conditions assignment you can then do
reduce(operator.or_, [Q(**condition) for condition in conditions])
which translates in the particular case to
Q(toBuy='bread') | Q(name__contains='bread')
which is exactly what we need.

Related

Getting all LDAP users with django

I'm using django-auth-ldap and I'm trying to get all users from LDAP server, I didn't find a way to do so, the authenticating is working in the backend, here is my code
#api_view(['GET'])
def users(request):
l = ldap.initialize(backend.AUTH_LDAP_SERVER_URI)
l.simple_bind_s(backend.AUTH_LDAP_BIND_DN, backend.AUTH_LDAP_BIND_PASSWORD)
users = LDAPBackend().populate_user('*') #this line is returning None
l.unbind_s()
print (users)
serializer = userSerializer(users, many=True)
return Response(serializer.data)
I know that line is incorrect LDAPBackend().populate_user('*')
but I really need to get all users with something like this : conn.search('ou=users, dc=example,dc=com', '(objectclass=person)', attributes=['uid', 'cn', 'givenName', 'sn', 'gidNumber'])
(this is how I did with another library called ldap3)
Thank you
You can do something like this below
def get_users():
conn = ldap.initialize(LDAP_URL)
results = conn.search_s(GROUP_DN, ldap.SCOPE_ONELEVEL, '(cn=*)')
# get all non-empty uniqueMember of all groups (list of list), flattern the list and get only unique value
users_dn = set(list(chain.from_iterable(filter(lambda x: x, [x[1].get('uniqueMember') for x in results]))))
users = [x.split(',')[0].split('=')[1] for x in users_dn]
return users

How to get multiple queryset from textarea in django

I have a text area in which user inputs multiple values in different line and i want to get object for every single line in text area and send it to template. How i should do it.?
if request.method == 'GET':
search = request.GET.get('search')
slist = []
for i in range(4):
slist.append(search.splitlines()[i])
sdata = Stock.objects.all().filter(slug=slist)
return render(request, 'stocks/searchbar.html', {'sdata':sdata})
I'm trying to do it in this way.
You need to do something like this:
sdata = Stock.objects.filter(slug__in=search.splitlines())
Since search.splitlines() returns a list and slug is, I assume, a CharField, you need the in clause in your query.

Objects.filter(" ı wanna add two contains field")

This is search field. But in the views ı cant search on two field. I tried all of this. its not working.
its only working in one fields like = Makale.objects.filter(baslik__contains=keyword)
makale = Makale.objects.filter(baslik__contains=keyword,icerik_contains=keyword)
makale = Makale.objects.filter(baslik_contains=keyword or icerik_contains=keyword)
def paylasimlar(request):
keyword = request.GET.get("keyword")
if keyword:
paylasimlar = Makale.objects.filter(icerik__contains=keyword)
return render(request, "feed.html", {"paylasimlar": paylasimlar})
paylasimlar = Makale.objects.all()
return render(request, "feed.html", {"paylasimlar":paylasimlar})
You can add an or operator between two constraints by using Q-objects [Django-doc] and the or (|) operator [Django-doc], like:
from django.db.models import Q
Makale.objects.filter(Q(baslik__contains=keyword) | Q(icerik__contains=keyword))

Django data saving and presenting

My Django project need to acquire one list after processing in one function of views.py.
def acquire(request):
import sys
n = []
for topic in Topic.objects.filter(owner=request.user).order_by("date_added"):
entries = topic.entries.all()
q = entries.text
n.append(q)
return render(request, "projects/topics.html", n)
The list "n" above need to be transferred to another function of views.py for the information in another "results.html" page.
def results(request):
data = XXXX
return render(request, "projects/results.html", {"datas": data})
How could I edit "XXX" in results function to transfer the "n" list?
You can write a utility function that can be used by both views and stores the data for the current session:
def acquire(request):
data = _get_data(request)
return render(request, "projects/topics.html", {'data': data})
def results(request):
data = _get_data(request)
return render(request, "projects/results.html", {'data': data})
# this is not a view, but a utility function
def _get_data(request)
# this will try to use the data generated in a previous request of
# the same session. So the data might be stale by now
if not 'user_entries' in request.session:
n = []
for topic in Topic.objects\
.filter(owner=request.user)\
.order_by('date_added')\
.prefetch_related('entries'): # prefetch avoids the nested queries
for entry in topic.entries.all():
n.append(entry.text)
request.session['user_entries'] = n
return request.session['user_entries']
You can declare the list n outside of the function so you can use it wherever you want, like:
n = []
def acquire(request):
import sys
for topic in Topic.objects.filter(owner=request.user).order_by("date_added"):
entries = topic.entries.all()
q = entries.text
n.append(q)
return render(request, "projects/topics.html", n)
def results(request):
data = n
return render(request, "projects/results.html", {"datas": data})
You have to remember that whatever variable you set, it only lives within the view/function as Django is stateless. That's why you have a database and cookies.
This is how you do it. Unless that list has thousands and thousands of entries, this will be fast.
def results(request):
data = []
for topic in Topic.objects.filter(owner=request.user).order_by("date_added"):
entries = topic.entries.all()
q = entries.text
data.append(q)
return render(request, "projects/results.html", {"datas": data})
If you want to be really fast, you could change the request and work on the database level and create a join. Something along the lines of this (I'm a bit rusty)
data = Entries.objects.filter(topic__owner=request.user).order_by("topic__date_added").values("text")

Returning multiple fetched users

I have a view which fetches multiple users from a database based on passed in skills. It works almost as desired except if it returns more than one user it only passes back the most recently fetched user. How do I aggregate fetched users to be passed back to the template. I've tried passing them back as a list but they didn't appear.
Here is my code:
form = FilterFreelancerForm(request.POST)
filtered_skills = set((request.POST.getlist('skills_select')))
match_fl = Freelancer.object.annotate(c=Count('skills')).filter(c=len(filtered_skills))
candidate_freelancers = None
for skill in filtered_skills:
candidate_freelancers = match_fl.filter(skills=skill)
freelancers = None
for freelancer in candidate_freelancers:
freelancers = User.objects.filter(freelancer=freelancer.id)
return render(request, 'freelancestudent/browsefreelancers.html', {'freelancers': freelancers,
'filter_form': form})
I previously had this:
freelancers = []
for freelancer in candidate_freelancers:
freelancers.append(User.objects.filter(freelancer=freelancer.id))
which returns nothing to the template.
Instead of:
for freelancer in candidate_freelancers:
freelancers = User.objects.filter(freelancer=freelancer.id)
try:
freelancers = User.objects.filter(freelancer__in=[freelancer.id for freelancer in candidate_freelancers])
out:
[<User: user1>, <User: user2>]

Categories