我将这个表存储在 Postgres 数据库中
用户
| id | email | password | gender |
| 01 | user1@email.com | pass1 | male |
| 02 | user2@email.com | pass3 | female |
| 03 | user3@email.com | pass2 | male |
标记
| id | school_mark | subject | user_id | status |
| 01 | 9 | history | 01 | True |
| 02 | 8 | english | 02 | True |
| 03 | 7 | math | 01 | True |
| 02 | 7 | english | 01 | False |
| 03 | 6 | math | 03 | False |
...
- user_id 是将 marks 元素链接到每个用户的外键
- id(在两个表中)都是主键
# api/models.py
from django.db import models
class User(models.Model):
email = models.EmailField()
password = models.CharField(max_length=100)
gender = models.CharField(max_length=100)
class Mark(models.Model):
school_mark = models.IntegerField()
subject = models.CharField(max_length=100)
user_id = models.ForeignKey(User, on_delete=models.CASCADE)
status = models.BooleanField(default=False)
我希望我的最终结果是这样的/api/marks/male
[
{"id" : 01,
"marks": [
{"id": 01,
"subject": "history",
"school_mark": 9},
{"id": 03,
"subject": "history",
"school_mark": 7}]}
{"id" : 03,
"marks": []}
]
首先仅选择“男性”形式的用户,然后搜索所选用户的标记,但在响应中仅返回状态为 TRUE 的标记
我开始认为 serializers.py 是这样的:
# api/serializers.py
from rest_framework import serializers
from .models import User, Mark
class MarkSerializer(serializers.ModelSerializer):
class Meta:
model = Mark
exclude = ('status', 'user_id')
class UserSerializer(serializers.ModelSerializer):
marks = MarkSerializer(many=True, read_only=True)
class Meta:
model = User
fields = ('id', 'marks')
但后来我卡在了 views.py 上
# api/views.py
from rest_framework import generics
from .models import User, Mark
from .serializers import UserSerializer
class MarkList(generics.ListAPIView):
serializer_class = UserSerializer
def get_queryset(self):
# "/api/marks/<str:gender>/"
gender = kwargs['gender']
???
知道如何继续吗?
请您参考如下方法:
您是否设置了 url/response 结构?我知道这并不完全是您所要求的,但为了给出我能提供的请您参考如下方法:,我可能会更改您的设置的一些结构性内容:
通常对于 RESTful API,/api/marks/ 会返回一个序列化的
Mark对象列表,而不是您所显示的,这是一个Users列表,其中每个用户都有一个序列化Marks列表。由于您只需要用户 ID,因此 DRF 提供了一种简单的非嵌套机制来以相反的方式对此进行序列化(使用PrimaryKeyRelatedField)。接下来,我可能会使用查询参数 (/api/marks?gender=male) 而不是 /api/marks/male。这有点个人偏好,但在 REST 最佳实践中有一定的基础(请参阅 this SO answer for a nice description)
最后,
Mark上的ForeignKey字段应命名为user,而不是user_id。 Django 在存储外键字段时自动将_id附加到数据库列名,因此您编写的模型将产生一个名为user_id_id的数据库列。
通过这些修改,以下代码将为您提供所需的过滤(尽管序列化响应与上述初始请求略有不同):
# api/serializers.py
from rest_framework import serializers
from .models import Mark
class MarkSerializer(serializers.ModelSerializer):
user = serializers.PrimaryKeyRelatedField(read_only=True)
class Meta:
model = Mark
exclude = ('status')
# api/views.py
from rest_framework import generics
from .models import Mark
from .serializers import MarkSerializer
class MarkList(generics.ListAPIView):
serializer_class = MarkSerializer
def get_queryset(self):
queryset = Mark.objects.filter(status=True)
gender = self.request.query_params.get('gender')
if gender is not None:
queryset = queryset.filter(user__gender=gender)
return queryset
我还没有对此进行测试,但是除非有任何拼写错误,从上面的示例中请求 /api/marks?gender=male 应该返回如下内容:
[
{
"id" : 01,
"subject": "history",
"school_mark": 9,
"user": 01
},
{
"id" : 03,
"subject": "math",
"school_mark": 7,
"user": 01
}
]
