python - RelatedField 序列化器 Django Rest 框架
问题描述
我有这个表存储在 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是将标记元素链接到每个用户的外键
- 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": []}
]
首先仅选择“男性”表单用户,然后搜索选定用户的标记,但在响应中仅返回具有 status=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 最佳实践中有一些基础(请参阅这个 SO 答案以获得很好的描述)
最后,
ForeignKey
字段 onMark
应该命名为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
}
]
推荐阅读
- kubernetes - 客户端应用程序的 Kubernetes 扩展
- flutter - 未找到未定义的名称和吸气剂
- f# - 避免在程序集的两个部分中出现模块和类型定义的错误
- python - Python - 如何在 for 循环中打印 json 的内部键?
- c# - ServiceStack.OrmLite 使用错误的列定义创建表
- scala - 如何实现 CustomKeySerializer
- python - 当尝试在弹性搜索中进行批量更新时。我收到 403 错误?
- python - 如何让 docker 容器在主机内而不是容器内搜索文件?
- telethon - Telethon 无法再获取聊天实体
- python - 使用 genfromtxt 获取数据时遇到问题