Как отфильтровать несколько полей с помощью Django-filter?
Я хочу получить данные, отфильтрованные по пользователю и категории.
Я использую Django Rest Framework.
models.py
class Practice(models.Model):
practice_id = models.BigAutoField(primary_key=True)
user = models.ForeignKey('User', models.DO_NOTHING, default=None)
subcategory = models.ForeignKey('Subcategory', models.DO_NOTHING, default=None)
score = models.SmallIntegerField(null=True)
def __str__(self):
return str(self.practice_id)
class User(models.Model):
user_id = models.BigAutoField(primary_key=True)
fullname = models.CharField(max_length=50)
def __str__(self):
return self.fullname
class Subcategory(models.Model):
subcategory_id = models.BigAutoField(primary_key=True)
category = models.CharField(max_length=30)
def __str__(self):
return f"{ self.category }"
serializers.py
class PracticeSerializer(serializers.ModelSerializer):
subcategory = SubcategorySerializer()
class Meta:
model = Practice
fields = ('practice_id',
'user',
'subcategory',
'score',
)
views.py
@api_view(['GET'])
def practiceFilter_User(request):
if request.method == 'GET':
exercises = Practice.objects.all()
user = request.GET.get('user', None)
if user is not None:
practice_filtered = exercises.filter(user__user_id__icontains=user)
exercises_serializer = PracticeSerializer(practice_filtered, many=True)
return JsonResponse(exercises_serializer.data, safe=False)
urls.py
urlpatterns = [
url(r'^api/practice-filter-user$', views.practiceFilter_User),
]
В моей базе данных есть данные по 3 практикам, как показано ниже :
[
{
practice_id: 1,
user: 1,
subcategory: {
subcategory_id: 1,
category: "Math",
},
score: 7,
},
{
practice_id: 2,
user: 1,
subcategory: {
subcategory_id: 1,
category: "Math",
},
score: 8,
},
{
practice_id: 3,
user: 1,
subcategory: {
subcategory_id: 2,
category: "History",
},
score: 9,
}
]
Если вышеприведенный код выполняется для получения данных о практике по идентификатору пользователя = 1, результат будет следующим :
api/practice-filter-user?user=1
[
{
practice_id: 1,
user: 1,
subcategory: {
subcategory_id: 1,
category: "Math",
},
score: 7,
},
{
practice_id: 2,
user: 1,
subcategory: {
subcategory_id: 1,
category: "Math",
},
score: 8,
},
{
practice_id: 3,
user: 1,
subcategory: {
subcategory_id: 2,
category: "History",
},
score: 9,
}
]
Я хочу получить данные, отфильтрованные по всем user
с идентификатором 1 и всем Math category
, как показано ниже :
api/practice-filter-subcategory-user?user=1&category=Math
[
{
practice_id: 1,
user: 1,
subcategory: {
subcategory_id: 1,
category: "Math",
},
score: 7,
},
{
practice_id: 2,
user: 1,
subcategory: {
subcategory_id: 1,
category: "Math",
},
score: 8,
}
]
Результаты, приведенные выше, - это то, что я хочу получить при извлечении данных о практике, отфильтрованных по пользователю и категории.
Я пробовал использовать django-filter на этой ссылке, но появляется ошибка.
Я добавил класс в views.py
class practiceFilter_Subcategory_User(generics.ListAPIView):
queryset = Practice.objects.all()
serializer_class = PracticeSerializer
filter_fields = ('user', 'category')
Я добавил url в urls.py
urlpatterns = [
url(r'^api/practice-filter-subcategory-user$', views.practiceFilter_Subcategory_User),
]
И я пытаюсь получить данные, отфильтрованные по всем user
с id 1 и всем Math category
, как показано ниже :
api/practice-filter-subcategory-user?user=1&category=Math
Но я потерпел неудачу и получил ошибку, как указано выше.
Можно ли отфильтровать все user
по id 1 и все Math category
?
Да, это возможно, фильтровать с большим количеством параметров. Django Rest Framework предоставляет нам множество вариантов для достижения этой цели. Я покажу вам одну из них: Filtering against query parameters
.
Вы можете переопределить .get_queryset()
вашего представления на основе класса, чтобы работать с URL, такими как api/practice-filter-subcategory-user?user=1&category=Math
class practiceFilter_Subcategory_User(generics.ListAPIView):
serializer_class = PracticeSerializer
def get_queryset(self):
# If they are no parameters return all objects
queryset = Practice.objects.all()
# Retrieve the query parameters in the url
user_id = self.request.query_params.get('user_id')
category = self.request.query_params.get('category')
# If they are present
if user_id is not None and category is not None:
practice_filtered = exercises.filter(user__user_id=user_id)
# Filter by category, you can chain filter of course
practice_filtered = practice_filtered.filter(subcategory__category=category)
queryset = practice_filtered
return queryset
Вот документация DRF
ОЧЕНЬ ВАЖНО : Вам нужно вызвать .as_view()
на ваших url
представлениях вот так :
from django.conf.urls import url
from yasn import views
urlpatterns = [
url(r'^api/practice-filter-user$', views.practiceFilter_User.as_view()),
url(r'^api/practice-filter-subcategory-user$', views.practiceFilter_Subcategory_User.as_view()),
]