# articles/views.pyfromrest_frameworkimportgenericsfromsrc.articles.modelsimportArticlefromsrc.articles.serializerimportArticleSerializerclassArticleListView(generics.ListCreateAPIView):queryset=Article.objects.all()serializer_class=ArticleSerializerregion_separator=","defget_queryset(self):"""
Optionally restricts the returned articles to given regions,
by filtering against a `regions` query parameter in the URL.
"""regions=self.request.query_params.get("regions",None)ifregions:qs=Article.objects.prefetch_related("regions")forregioninregions.split(self.region_separator):qs=qs.filter(regions__code=region)returnqs# return default Article.objects.all()returnsuper().get_queryset()
Improvement II
Writing business logic or query decisions in Views is usually considered
anti-pattern for Django. Query methods should be in models or better in
models.Manager;
# articles/models.pyfromdjango.dbimportmodelsfromsrc.articles.modelsimportArticlefromsrc.articles.serializerimportArticleSerializerclassArticleManager(models.Manager):defby_regions(self,regions,region_separator=","):"""
Restricts the returned articles to given regions
"""ifregions:qs=self.prefetch_related("regions")forregioninregions.split(region_separator):qs=qs.filter(regions__code=region)returnqsreturnself.all()classArticle(models.Model):title=models.CharField(max_length=255)content=models.TextField(blank=True)regions=models.ManyToManyField("Region",related_name="articles",blank=True)objects=ArticleManager()def__str__(self):returnself.title...
Now our get_queryset simply looks like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# articles/views.pyfromrest_frameworkimportgenericsfromsrc.articles.modelsimportArticlefromsrc.articles.serializerimportArticleSerializerclassArticleListView(generics.ListCreateAPIView):serializer_class=ArticleSerializerdefget_queryset(self):"""
Optionally restricts the returned articles to given regions,
by filtering against a `regions` query parameter in the URL.
"""regions=self.request.query_params.get("regions",None)returnArticle.objects.by_regions(regions=regions)
This is definitely cleaner and better.
If you have more complex queries, then you can consider using third party packages.