10

OVERVIEW


A url with query parameters looks like.

http://example.api.com/search/?name=jhon&age=26 

and on view if i am using django-filter all parameters are automatically extracted from request and it will return a filtered query-set .

views.py

class SearchView(TemplateView): template_name = "search.html" def get_queryset(self): return SearchFilter(request.GET, queryset=Model.objects.all()).qs def get_context_data(self, **kwargs): context = super(SearchView, self).get_context_data(**kwargs) return context 

If i want to extract it manually from request.GET i can do.

def get_queryset(self): # extracting query parameter q = self.request.GET.get('name') 

PROBLEM STATEMENT


My search url looks like

 http://example.api.com/search/jhon-26 

I am doing this because i don't want to reveal keys like 'name' and 'age' to public, this is for security abstraction these are the column of my db table .

I am getting jhon-26 in **kwargs, I want to split it and set as query parameter to request.GET so that my filter class will work fine

QUESTION


Is there anything to set attribute to request.GET?

# may be any set function available for this self.request.GET.set('name', 'jhon') 

How can i achieve this.

4
  • why dont you put it in session?? and access in the filter view? Commented Jul 19, 2017 at 11:12
  • How can i access request session in my filter class? Commented Jul 19, 2017 at 11:15
  • as you normally access session in views, just import the request in that file Commented Jul 19, 2017 at 11:19
  • @Exprator can you demonstrate how django-filter work with session? Commented Jul 19, 2017 at 11:58

3 Answers 3

29

I found solution to set query parameters to request.GET here

As request.GET QueryDict instance is immutable so we can not modify it directly so for that we need to set its _mutable property to True

if not request.GET._mutable: request.GET._mutable = True # now you can edit it request.GET['name'] = 'jhon' request.GET['age'] = 26 
Sign up to request clarification or add additional context in comments.

1 Comment

This is definitely not the recommended approach. using request.GET = request.GET.copy() then adding properties to this request.GET['name'] = 'jhon' is a much safer solution. As the highest rated answer in your linked solution states "This has been purposefully designed so that none of the application components are allowed to edit the source request data"
2

Well, you can do what django-filter does for you by simply saying:

 result = Model.objects.filter(**dict) 

However, for request.GET, you'd have to format it to make a valid dictionary since it's values are usually list. You can simply do:

 formatted = {key: dictionary.get(key)[0] for key in dict(request.GET).keys()} 

And then you can add the remaining variables into it:

 formatted['age'] = 26 //As extracted from **kwargs. etc. 

And then do:

 result = Model.objects.filter(**formatted) 

If you do not necessarily need to use request.GET (Since there's a way around what django-filter does), then you can simply form your dictionary and use it in the model's filter method.

By the way, why are you using request.GET if you do not want the public to see your data? How did you form your url? You may want to Ignore all of that as far as your code is working fine anyway!

3 Comments

django-filters configurations allow us to make filtering easy and remove overheads which we face if we write manual query to filter object, also it make a filter feature modular which is a good practise to be followed. Also i want to show my data to public but i just want to abstract keys which are directly a column in db table, So if i manage to do what i am asking is much efficient way i guess.
It is achievable without django-filter as you explained. But how it will work with django-filter? is there any possible way?
You may want to add your values to request.GET then. request.GET is a dict so you can simply do request.GET['new_key'] = value. However, it's immutable by default so you'd have to remove the immutability with request.GET._mutable = True This is not recommended though
1

Build your filter dynamically like so;

 query_data={} name = request.query_params.get('name') age = request.query_params.get('age') if name is not None: query_data['name'] = name if age is not None: query_data['age'] = age return Model.objects.filter(**query_data) 

1 Comment

The request.query_params is immutable.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.