python - Django Rest Framework 如何从多个模型创建序列化程序
问题描述
我需要扩展 User 模型以添加诸如地址、分数、更多 user_types 等内容。有两种可能的方法来实现这一点,扩展 User 模型或创建一个将与目标 User 连接的新模型OneToOneField
。我决定使用新模型,因为它看起来更容易,并且在这个堆栈溢出问题中推荐。但是现在我无法在没有嵌套配置文件字段的情况下创建序列化程序,而且没有记录,因为默认的 rest_framwork 文档生成器无法为嵌套序列化程序生成文档。
我的UserSerializer
样子是这样的:
class UserSerializer(serializers.ModelSerializer):
# This creates a nested profile field
profile = ProfileSerializer(required=True)
def create(self, validated_data):
profile_data = validated_data.pop('profile')
user = User.objects.create_user(**validate_data)
profile, created = Profile.objects.upodate_or_creeate(user=user, defaults=profile_data)
return user
class Meta:
model = User
fields = ('id', 'username', 'email', 'password', 'buckelists', 'profile')
read_only_fields = ('id',)
extra_kwargs = {'password':{'write_only': True}}
此序列化程序采用以下 JSON 格式:
{
'name': ...,
'email': ...,
'password': ...,
'profile': {
'address': ...,
'score': ...,
'user_type': ...,
'achievements': ...,
'country': ...,
'trusted': ...,
}
这看起来很奇怪,并且生成的文档rest_framework.documentation.include_docs_urls
显示如下:
{
'username': ...,
'email': ...,
'password': ...,
'field': ...,
}
所以不清楚应该在配置文件字段中包含什么。我想创建可以接受以下格式的序列化程序:
{
'name': ...,
'email': ...,
'password': ...,
'address': ...,
'score': ...,
'user_type': ...,
'achievements': ...,
'country': ...,
'trusted': ...,
}
是否可以不从头开始创建自定义序列化程序?或者至少可以为嵌套序列化程序生成文档。
PS:我使用python3.6和Django 2.1
编辑:这是我的models.py的相关部分:
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
trusted = models.BooleanField(default=False)
address = models.CharField(max_length=100, default="")
COUNTRIES = (
('CZ', 'Czech Republic'),
('EN', 'England'),
)
country = models.CharField(max_length=2, choices=COUNTRIES, default="CZ")
score = models.BigIntegerField(default=0)
achievements = models.ManyToManyField(Achievement, blank=True)
USER_TYPES = (
('N', 'Normal'),
('C', 'Contributor'),
('A', 'Admin'),
)
user_type = models.CharField(max_length=1, choices=USER_TYPES, default='N')
@receiver(post_save, sender=settings.AUTH_USER_MODEL)
def create_auth_token(sender, instance=None, created=False, **kwargs):
if created:
Token.objects.create(user=instance)
@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created=False, **kwargs):
if created:
profile, created = Profile.objects.get_or_create(user=instance)
profile.save()
编辑:
Mohammad Ali 的答案为 GET 解决了这个问题,但我也想使用 POST、UPDATE 和 PATCH 方法。我发现我必须使用source
参数,但这与序列化程序有关,我不知道如何在没有配置文件字段的情况下引用配置文件。
解决方案
放轻松,您可以在 create 函数中创建 Profile obj。
class UserSerializer(serializers.ModelSerializer):
trusted = serializers.BooleanField()
address = serializers.CharField()
class Meta:
model = User
fields = ('username', 'email', 'password', 'trusted', 'address',)
def create(self, validated_data):
user = User.objects.create(username=validated_data['username'], email=validated_data['email'])
user.set_password(validated_data['password'])
user.save()
profile = Profile(user=user, trusted=validated_data['trusted'], address=validated_data['address']
profile.save()
return validated_data
这只是您的场景的简要实现。你可以填满故事。
推荐阅读
- excel - 行集群值的条件下拉列表
- javascript - 如何使用 React Router 覆盖 Express API 路由
- typescript - Angular 9没有设置动态输入字段值
- swift - 如何将 '(Data?, URLResponse, Error?) 转换为预期的参数类型 '(Data?, URLResponse?, Error?) -> Void'
- lua - 获取“IntValue”的值总是得到默认值
- amazon-web-services - AWS Systems Manager Parameter Store 和 AWS Secrets Manager 之间的区别?
- mysql - MySQL - 聚合和 GROUP BY 与子查询
- android - 如何在 android TWA(受信任的网络活动)中创建动画启动画面
- python-3.x - 使用 interpolate.splrep 输入数据错误
- c# - 如何在运行时确定属性所针对的类的名称和引用?