简体   繁体   中英

django multiple filter options on queryset

We have 2 approach ideas that we are trying to consider here for the Django REST api.

At the moment, we have implemented 1 filter option:

class APINewsViewSet(viewsets.ModelViewSet):
    serializer_class = APINewsSerialiser

    def get_queryset(self):
        queryset = NewsBackup.objects.all()
        source = self.request.query_params.get('source', None)
        if source is not None:
            queryset = queryset.filter(news_source = source)
        return queryset

This achieves: 127.0.0.1/news?source=xxx

Something additional that we would like to do is have other filter options that the user can type in such as 127.0.0.1/news?source=xxx&sourcename=xxx which would then return them the JSON object with only data that has a source_id of xx and source_name of xx.

Is this possible with the Django REST framework? We have tried to add other options within the method:

query_params.get()

You can place the filters in a dictionary and then use the dictionary as the filter. Even better you can create a valid filters that safeguards invalid filters. Something like below:

# {'queryparam': 'db_field'}
valid_filters = {
    'source': 'news_source',
    'source_name': 'source_name',
}

filters = {valid_filters[key]: value for key, value in self.request.query_params.items() if key in valid_filters.keys()}

# So if the query_params is like this: source=xxx&source_name=xxx
# filters value will look something like below:
{
    'news_source': 'xxx',
    'source_name': 'xxx',
}
# **filters transforms the filters to: (news_source='xxx', source_name='xxx')
queryset = queryset.filter(**filters)

Or if you don't want to customize it heavily, you can use third party packages like Django Filter

UPDATE If you want to get the multiple values for example: id=1&id=2 , you can use getlist

ids = self.request.query_params.getlist('id')
# ids will have the list of id
# ids = [1, 2]
# you can then query the id
queryset = queryset.filter(id__in=ids)

UPDATE 2 If you want to support multiple filters, you can create a dictionary again:

keys = [
    'id',
    'source_name',
]
filters = {}
for key in keys:
    filter = query_params.getlist(key)
    if filter:
        filters['{}__in'.format(key)] = filter

queryset = queryset.filter(**filters)

You can add the validation if you want.

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM