DjangoRestFramework - 如何使用模型序列化程序访问 OneToOneField 反向关系的其他字段?
DjangoRestFramework - How to access other fields of a OneToOneField reverse relationship using a model serializer?
我正在使用默认的 User 模型,并且还在使用 UserExtended 模型对其进行扩展:
class Country(models.Model):
countryName = models.CharField(max_length=50, unique=True)
countryCode = models.CharField(max_length=10, unique=True)
class UserExtended(models.Model):
user = models.OneToOneField(User, related_name="userextended")
country = models.ForeignKey(Country)
我正在尝试遵循此处记录的内容:http://www.django-rest-framework.org/api-guide/relations/#reverse-relations
这是我的 UserSerializer:
class UserSerializer(serializers.ModelSerializer):
def __init__(self, *args, **kwargs):
super(UserSerializer, self).__init__(*args, **kwargs) # call the super()
for field in self.fields: # iterate over the serializer fields
self.fields[field].error_messages['required'] = 'Enter a valid %s.'%field # set the custom error message
class Meta:
model = User
fields = ('username', 'password', 'email', 'userextended')
extra_kwargs = {
'password': {
'write_only': True,
}
}
def create(self, validated_data):
user = User.objects.create_user(
email = validated_data['email'],
username = validated_data['username'],
password = validated_data['password'],
)
return user
我的问题是,如果最终用户在提交之前没有填写表单的 "Country" 部分,Django 会向前端发送错误消息 "Enter a valid userextended"。 "userextended" 是反向关系的名称,每个用户对象都链接到一个用户扩展对象,反之亦然。 "userextended" 是强制性的,但最终用户在创建用户对象时不必指定 "userextended" 字段,因为这已经是给定的(最终用户创建用户对象时,用户对象将默认情况下与 UserExtended 对象具有反向关系)。
最终用户必须填写表格中的 "Country" 部分,因为国家/地区是最终用户所需要的。话虽如此,我如何让 Django 说 "Enter a valid Country" 而不是 "Enter a valid userextended"?
如果最终用户成功保存了一个用户对象,并在表单的"Country"部分提交了"Canada",DRF如何知道将"Canada"保存为国家?因为目前看来,DRF 认为表单中的 "Country" 部分指的是 "userextended" 反向关系字段。
我期望的是,在用户序列化程序的 "fields" 数组中,我使用点表示法?是这样的吗?:
fields = ('username', 'password', 'email', 'userextended.country')
编辑:我刚刚也创建了一个 UserExtended 序列化程序,如下所示:
class UserExtendedSerializer(serializers.ModelSerializer):
class Meta:
model = UserExtended
fields = ('country')
但我不知道如何 "merge" 使用原始 UserSerializer 这个序列化器。
你应该做下一步:
- 为 UserExtended 模型实例编写序列化程序。
- 使用此序列化程序序列化
userextended
字段。
像这样:
class UserExtendedSerializer(serializers.ModelSerializer):
# define serializer here...
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('username', 'password', 'email', 'userextended')
userextended = UserExtendedSerializer(read_only=True)
Igor 给出的解决方案仅在您想获取用户的详细信息时有效,因为 read_only 字段。 Serializer 默认不支持嵌套写入。要编写嵌套对象,您应该重写 UserSerializer 的创建方法。
class UserSerializer(serializers.ModelSerializer):
def __init__(self, *args, **kwargs):
super(UserSerializer, self).__init__(*args, **kwargs) # call the super()
for field in self.fields: # iterate over the serializer fields
self.fields[field].error_messages['required'] = 'Enter a valid %s.'%field # set the custom error message
country = serializers.RelatedField(source='userextended.country')
class Meta:
model = User
fields = ('username', 'password', 'email', 'country')
extra_kwargs = {
'password': {
'write_only': True,
}
}
def create(self, validated_data):
user = User.objects.create_user(
email = validated_data['email'],
username = validated_data['username'],
password = validated_data['password'],
)
country=Country.objects.get(pk=validated_data['country'])
UserExtended.objects.create(user=user, country=country)
return user
创建时要发送的数据:
{'username':'sachin', 'email': 'email@gmail.com', 'password': 'abc', 'country':2}
我正在使用默认的 User 模型,并且还在使用 UserExtended 模型对其进行扩展:
class Country(models.Model):
countryName = models.CharField(max_length=50, unique=True)
countryCode = models.CharField(max_length=10, unique=True)
class UserExtended(models.Model):
user = models.OneToOneField(User, related_name="userextended")
country = models.ForeignKey(Country)
我正在尝试遵循此处记录的内容:http://www.django-rest-framework.org/api-guide/relations/#reverse-relations
这是我的 UserSerializer:
class UserSerializer(serializers.ModelSerializer):
def __init__(self, *args, **kwargs):
super(UserSerializer, self).__init__(*args, **kwargs) # call the super()
for field in self.fields: # iterate over the serializer fields
self.fields[field].error_messages['required'] = 'Enter a valid %s.'%field # set the custom error message
class Meta:
model = User
fields = ('username', 'password', 'email', 'userextended')
extra_kwargs = {
'password': {
'write_only': True,
}
}
def create(self, validated_data):
user = User.objects.create_user(
email = validated_data['email'],
username = validated_data['username'],
password = validated_data['password'],
)
return user
我的问题是,如果最终用户在提交之前没有填写表单的 "Country" 部分,Django 会向前端发送错误消息 "Enter a valid userextended"。 "userextended" 是反向关系的名称,每个用户对象都链接到一个用户扩展对象,反之亦然。 "userextended" 是强制性的,但最终用户在创建用户对象时不必指定 "userextended" 字段,因为这已经是给定的(最终用户创建用户对象时,用户对象将默认情况下与 UserExtended 对象具有反向关系)。
最终用户必须填写表格中的 "Country" 部分,因为国家/地区是最终用户所需要的。话虽如此,我如何让 Django 说 "Enter a valid Country" 而不是 "Enter a valid userextended"?
如果最终用户成功保存了一个用户对象,并在表单的"Country"部分提交了"Canada",DRF如何知道将"Canada"保存为国家?因为目前看来,DRF 认为表单中的 "Country" 部分指的是 "userextended" 反向关系字段。
我期望的是,在用户序列化程序的 "fields" 数组中,我使用点表示法?是这样的吗?:
fields = ('username', 'password', 'email', 'userextended.country')
编辑:我刚刚也创建了一个 UserExtended 序列化程序,如下所示:
class UserExtendedSerializer(serializers.ModelSerializer):
class Meta:
model = UserExtended
fields = ('country')
但我不知道如何 "merge" 使用原始 UserSerializer 这个序列化器。
你应该做下一步:
- 为 UserExtended 模型实例编写序列化程序。
- 使用此序列化程序序列化
userextended
字段。
像这样:
class UserExtendedSerializer(serializers.ModelSerializer):
# define serializer here...
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('username', 'password', 'email', 'userextended')
userextended = UserExtendedSerializer(read_only=True)
Igor 给出的解决方案仅在您想获取用户的详细信息时有效,因为 read_only 字段。 Serializer 默认不支持嵌套写入。要编写嵌套对象,您应该重写 UserSerializer 的创建方法。
class UserSerializer(serializers.ModelSerializer):
def __init__(self, *args, **kwargs):
super(UserSerializer, self).__init__(*args, **kwargs) # call the super()
for field in self.fields: # iterate over the serializer fields
self.fields[field].error_messages['required'] = 'Enter a valid %s.'%field # set the custom error message
country = serializers.RelatedField(source='userextended.country')
class Meta:
model = User
fields = ('username', 'password', 'email', 'country')
extra_kwargs = {
'password': {
'write_only': True,
}
}
def create(self, validated_data):
user = User.objects.create_user(
email = validated_data['email'],
username = validated_data['username'],
password = validated_data['password'],
)
country=Country.objects.get(pk=validated_data['country'])
UserExtended.objects.create(user=user, country=country)
return user
创建时要发送的数据:
{'username':'sachin', 'email': 'email@gmail.com', 'password': 'abc', 'country':2}