Getting all LDAP users with django - python

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

Related

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.

Getting 0 when using json.decode

I am a beginner in Django as well as Python.
I first generate 50 random numbers and store them in a list and then in a text field in model User.
def generate(request, user_id):
easy = [] * 55
cnt = 0
while cnt < 50:
random_id = random.randint(1, 200)
if random_id not in easy:
easy.append(random_id)
cnt += 1
current_user = User.objects.get(pk=user_id)
current_user.question_array = json.dumps(easy)
return render(request, 'comp/question.html', {'easy': easy[0], 'question_id': 1,'user_id':user_id})
But when I try to retrieve the value from field I get only 0.
When I try to use it as a list it shows an error of "int object cannot be subscript".
This is the code to retrieve it:
def next(request,user_id, question_id):
current_user = User.objects.get(pk=user_id)
jsonDec = json.decoder.JSONDecoder()
easy = jsonDec.decode(current_user.question_array)
return render(request, 'comp/question.html',
{'easy': easy, 'question_id': int(question_id) + 1,'user_id':user_id})
I have used the answer to this question given by mindthief to store a list in a table.
Edit:
My main problem is that the list is not getting stored in database. Any ideas why?
You need to add a .save() call to save the data to the db:
current_user = User.objects.get(pk=user_id)
current_user.question_array = json.dumps(easy)
current_user.save()
...
BTW, you can also use random.sample():
easy = random.sample(range(200), 50) # in python 2.x use xrange()
and json.loads():
easy = json.loads(current_user.question_array)
If you use PostgreSQL (highly recommended) you can even use a JsonField.
And finally, if the questions are stored in another model (Question), consider using a ManyToManyField instead.

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>]

Django Tastypie: filter results for a GET call by looping over model.objects.all()

I want to build an API using Tastypie that takes in a lat/long pair, and then searches my database for all entries whose locations are within a given distance of that lat/long. To do so, my model has a method which can take in a lat/long pair and return a distance from its own lat/long to the given lat/long.
In other words, I want to filter not by model fields, but by doing something along the lines of:
latitude = # somehow get from Tastypie request
longitude = # somehow get from Tastypie request
distance = 80
all_models = Example.objects.all()
within_range = []
for model in all_models:
distance_to_model = model.calculate_distance(latitude, longitude)
if distance_to_model <= 80:
within_range.append(model.name)
# somehow return within_range to Tastypie
I perused the docs and honestly am a bit overwhelmed -- this is the first API I'll have built, and it would seem that this functionality should be simple to find, but I'm struggling.
First of all you should rethink do you really want RESTful type API as Tastypie is. Because having this type of interface is super generic, easy and quick to expose your data to some front-end clients but requires you to stick to rules that doesn't fit your current problem.
If I understand you correctly you want to build only one API endpoint only for this calculation. And if yes this is not the case where you use RESTful type APIs.
I suggest you to build simple JSON view:
#csrf_exempt
def calculate_distance(request):
# Pass data in various ways
latitude = request.GET.get('latitude') or request.POST.get('latitude')
longitude = request.GET.get('longitude') or request.POST.get('longitude')
# Or pass data as JSON in request body
if request.method != 'POST':
return HttpResponseNotAllowed(permitted_methods=('POST',))
try:
data = json.loads(request.body)
except (AttributeError, ValueError):
return HttpResponseBadRequest(json.dumps({'message': 'json format incorrect'}),
content_type='application/json')
if data.get('latitude', None) and data.get('longitude', None):
within_range = []
for location in Location.objects.all():
distance_to_model = location.calculate_distance(data['latitude'], data['longitude'])
if distance_to_model <= 80:
within_range.append(location.name)
return HttpResponse(json.dumps({'success': True,
'within_range': within_range}),
content_type='application/json')
else:
return HttpResponseBadRequest(json.dumps({'message': 'offer_id is missing'}),
content_type='application/json')
You can upgrade this view with more validation, authorization, authentication etc.
EDITED:
However if you from some reasons will decide to stick to Tastypie use build_filters method inside your model resource class:
def build_filters(self, filters=None):
if filters is None:
filters = {}
orm_filters = super(OfferResource, self).build_filters(filters)
if 'pk__in' not in orm_filters:
orm_filters['pk__in'] = []
if 'latitude' in filters and 'longitude' in filters:
for entity in Example.objects.all():
distance_to_model = entity.calculate_distance(
filters['latitude'], filters['longitude'])
if distance_to_model <= 80:
orm_filters['pk__in'].append(entity.pk)
return orm_filters
Now can request your resource ?latitude=xxx&longitude=yyyy. Remember values passed by filters are always strings. Make sure calculate_distance can handle them.

search multiple fields django

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.

Categories