Dica 52 - DRF: django-filter
Github: https://github.com/rg3915/drf-example
Doc: https://www.django-rest-framework.org/api-guide/filtering/#djangofilterbackend
Doc: https://django-filter.readthedocs.io/en/stable/guide/rest_framework.html#integration-with-drf
Filtrando a queryset
Editar blog/models.py
# blog/models.py
from django.contrib.auth.models import User
from django.db import models
class Author(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30, null=True)
class Meta:
verbose_name_plural = "Authors"
@property
def full_name(self):
return f'{self.first_name} {self.last_name or ""}'.strip()
def __str__(self):
return self.full_name
class Post(models.Model):
title = models.CharField(max_length=30)
body = models.TextField()
author = models.ForeignKey(Author, on_delete=models.CASCADE, null=True)
created_by = models.ForeignKey(
User,
on_delete=models.CASCADE,
verbose_name='criado por',
null=True
)
created = models.DateTimeField(auto_now_add=True)
class Meta:
verbose_name_plural = "Posts"
def __str__(self):
return self.title
Editar blog/admin.py
# blog/admin.py
from django.contrib import admin
from blog.models import Author, Post
@admin.register(Author)
class AuthorAdmin(admin.ModelAdmin):
list_display = ('__str__',)
@admin.register(Post)
class PostAdmin(admin.ModelAdmin):
list_display = ('title', 'author', 'created_by')
Editar blog/views.py
# blog/views.py
from rest_framework.permissions import AllowAny, IsAuthenticated
class PostViewSet(viewsets.ModelViewSet):
# queryset = Post.objects.all()
queryset = Post.objects.filter(created_by__username='regis')
serializer_class = PostSerializer
# permission_classes = (AllowAny,)
permission_classes = (IsAuthenticated,)
# pagination_class = CustomBlogResultsSetPagination
Filtrando pelo usuário logado
Editar blog/views.py
# blog/views.py
class PostViewSet(viewsets.ModelViewSet):
# queryset = Post.objects.all()
# queryset = Post.objects.filter(created_by__username='regis')
serializer_class = PostSerializer
# permission_classes = (AllowAny,)
permission_classes = (IsAuthenticated,)
# pagination_class = CustomBlogResultsSetPagination
def get_queryset(self):
user = self.request.user
return Post.objects.filter(created_by=user)
Erro:
AssertionError: `basename` argument not specified, and could not automatically determine the name from the viewset, as it does not have a `.queryset` attribute.
Editar blog/urls.py
# blog/urls.py
...
router.register(r'authors', AuthorViewSet, basename='Author')
router.register(r'posts', PostViewSet, basename='Post')
Filtrando a partir de query parameters
Editar settings.py
# settings.py
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
# 'rest_framework_simplejwt.authentication.JWTAuthentication',
'rest_framework.authentication.BasicAuthentication',
'rest_framework.authentication.TokenAuthentication',
),
Editar blog/views.py
# blog/views.py
class PostViewSet(viewsets.ModelViewSet):
serializer_class = PostSerializer
permission_classes = (IsAuthenticated,)
def get_queryset(self):
queryset = Post.objects.all()
username = self.request.query_params.get('username')
if username is not None:
queryset = queryset.filter(created_by__username=username)
title = self.request.query_params.get('title')
if title is not None:
queryset = queryset.filter(title__icontains=title)
return queryset
Filtro Genérico django-filter
https://django-filter.readthedocs.io/en/stable/guide/rest_framework.html#integration-with-drf
pip install django-filter
pip freeze | grep django-filter >> requirements.txt
Editar settings.py
# settings.py
INSTALLED_APPS = [
...
# 3rd apps
'django_filters',
...
]
REST_FRAMEWORK = {
...
'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend']
}
Editar blog/views.py
# blog/views.py
class PostViewSet(viewsets.ModelViewSet):
queryset = Post.objects.all()
serializer_class = PostSerializer
permission_classes = (IsAuthenticated,)
filterset_fields = ('title', 'body')
# comentar def get_queryset(self)
Filtra pelo texto completo.
Adicionando filtro específico com filterset_class
Editar blog/filters.py
# blog/filters.py
from django_filters import rest_framework as filters
from blog.models import Post
class PostFilter(filters.FilterSet):
title = filters.CharFilter(field_name="title", lookup_expr='icontains')
body = filters.CharFilter(field_name="body", lookup_expr='icontains')
class Meta:
model = Post
fields = ('title', 'body')
Editar blog/views.py
# blog/views.py
from blog.filters import PostFilter
class PostViewSet(viewsets.ModelViewSet):
queryset = Post.objects.all()
serializer_class = PostSerializer
permission_classes = (IsAuthenticated,)
# filterset_fields = ('title', 'body')
filterset_class = PostFilter
Campo de busca
Editar blog/views.py
# blog/views.py
from rest_framework.filters import SearchFilter
class AuthorViewSet(viewsets.ModelViewSet):
...
filter_backends = (SearchFilter,)
search_fields = ('first_name', 'last_name')
Last updated
Was this helpful?