I am working with Django Rest Framework Filter to access my data. I wrote a custom viewset for one of my models to handle logical 'or' operation on some specifics fields for request with url.
Here is my ViewSet Class (the printing are just for my debug)
class CustomViewSet(viewsets.ModelViewSet):
permission_classes = (IsAuthenticated,)
queryset = appart.MyModel.objects.order_by('pk')
serializer_class = MyModelSerializer
filter_class = MyModelFilter
def get_queryset(self):
# getting param
query = dict(self.request.query_params)
print(query)
ct_query = query['caracteristique_text__icontains'][0].split('|')
cl_query = query['caracteristique__libelle__in'][0].split(',')
# writting request syntax
ct = 'Q(caracteristique__libelle__in=' + str(cl_query) + ')&('
print(ct)
for value in ct_query:
ct += "Q(caracteristique_text__icontains='" + value + "')|"
ct = ct[0:len(ct) - 1]
ct += ')'
print(ct)
filtre_text = "global filtre; filtre = " + ct
# creating the request
exec(filtre_text)
#running the request
self.queryset = self.queryset.filter(filtre)
print(self.queryset)
return self.queryset # doesn't return what I see when running print(self.queryset)
And MyModelFilter Class :
class MyModelFilter(ModelFilterSet):
class Meta:
model = appart.MyModel
fields = ('id', 'libelle', 'locataire_appart', 'bien_appart',
'adresse', 'loyer_appart', 'caracteristique', 'caracteristique_text',
'date_creation', 'derniere_maj')
this code is working well and do what I want it to do. He takes the url parameters, create dynamically the request syntax and return the data i'm looking for.
The only problem is that the return at the end doesn't give the same result that what I printed in my code. He still trying to execute a GET request based on the given url and return nothing when the syntax is not following the django_filter rules.
Can anyone help me to prevent this behavior of my viewsets ?
You need to specify some filters with Django Filters. I think you just need BaseInFilter
: https://django-filter.readthedocs.io/en/master/ref/filters.html#baseinfilter
class MyModelFilter(ModelFilterSet):
caracteristique_text = BaseInFilter(field_name='caracteristique_text', lookup_exp='icontains')
libelle = BaseInFilter(field_name='libelle', lookup_exp='in')
class Meta:
model = appart.MyModel
fields = ('id', 'libelle', 'locataire_appart', 'bien_appart',
'adresse', 'loyer_appart', 'caracteristique', 'caracteristique_text',
'date_creation', 'derniere_maj')
Ok so I finally solved my problem, there were no mistake in the code. This was due to the filter_class = MyModelFilter
. I just commented on this line and everything started to work. I honestly don't know why but i would appreciate a comment to this answer if anyone know the reason.
I also took a look on the exec
that @schillingt was talking about and here is the result for those trying to do the same thing or having the same problem.
class CustomViewSet(viewsets.ModelViewSet):
permission_classes = (IsAuthenticated,)
queryset = models.MyModel.objects.order_by('pk')
serializer_class = MyModelSerializer
filter_class = MyModelFilter
def get_queryset(self):
query = dict(self.request.query_params)
ct = self.request.query_params.get('caracteristique_text__icontains', None)
cl = self.request.query_params.get('caracteristique__libelle__in', None)
if ct is not None and cl is not None:
self.filter_class = None
ct_query = query['caracteristique_text__icontains'][0].split(',')
cl_query = query['caracteristique__libelle__in'][0].split(',')
full_query = Q(caracteristique__libelle__in=cl_query)
ct = Q()
for value in ct_query:
ct_part = Q(caracteristique_text__icontains=value)
ct |= ct_part
full_query &= ct
self.queryset = self.queryset.filter(full_query)
return self.queryset
return models.MyModel.objects.order_by('pk')
This post can also be helpful Filter with or condition
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.