两个相互引用的模型字段 - django rest
Two model fields referring to each other - django rest
我想更改 Django 模型中的一个现有字段名称。但是,为了向后兼容,我们不想用新字段覆盖现有字段,暂时保留它们。有没有办法让多个字段引用同一个数据库对象?即
现在的代码:
class NetworkPackage:
name = models.CharField(unique=True, blank=False, null=False)
inbound = models.CharField(unique=True, blank=False, null=False)
...
我要实施:
class NetworkPackage:
name = models.CharField(max_length=32, unique=True, blank=False, null=False)
inbound = models.CharField(max_length=128, unique=True, blank=True)
mobile = models.CharField(max_length=128, unique=True, blank=True)
...
基本上,'inbound' 和 'mobile' 应该引用相同的字段,并且可以使用 'inbound' 字段或 'mobile'.
发送请求
不知道你为什么要重复字段,但我有一些建议给你。
1.自定义 属性
class NetworkPackage:
name = models.CharField(unique=True, blank=False, null=False)
inbound = models.CharField(unique=True, blank=False, null=False)
@poperty
def mobile(self):
return self.inbound
2。序列化器
class NetworkPackageSerializer(serializers.Serializer):
mobile = serializers.CharField(source='inbound')
class Meta:
model = NetworkPackage
fields = (
'id',
'inbound',
'mobile',
'name',
...
)
在同一个模型中拥有两个包含相同信息的字段是个坏主意,尤其是当您需要强制执行唯一性时,因为
- 您需要保持两个字段的奇偶校验,这意味着如果请求设置
inbound
,那么您还必须设置 mobile
。
- 由于唯一性,数据库现在必须索引
inbound
和 mobile
。
您可以利用 python 属性,因为属性是您拥有遗留属性的完美解决方案:
class NetworkPackage(models.Model):
name = models.CharField(unique=True, blank=False, null=False)
inbound = models.CharField(unique=True, blank=False, null=False)
...
@property
def mobile(self):
return self.inbound
@mobile.setter
def mobile(self, value):
self.inbound = value
然后在你的序列化器中,你需要:
- 将
mobile
作为附加字段来源添加到 inbound
。
- 覆盖两个字段上的
required
和 allow_blank
参数,因为序列化程序可以允许任一字段...
- 但是,您随后需要编写一个自定义验证方法,以确保 2 个字段中至少有 1 个填充了值。
- 如果两个字段都已填充,则
inbound
值也优先于 mobile
值。
class NetworkPackageSerializer(serializers.ModelSerializer):
inbound = serializers.CharField(required=False, allow_blank=True)
mobile = serializers.CharField(source="inbound", required=False, allow_blank=True)
class Meta:
model = NetworkPackage
fields = ("inbound", "mobile", ...)
def validate(self, data):
"""Validate `inbound` and/or `mobile`."""
if not data["inbound"] and not data["mobile"]:
raise serializers.ValidationError("missing value on inbound or mobile")
if data["inbound"]:
del data["mobile"]
else:
del data["inbound"]
return data
我想更改 Django 模型中的一个现有字段名称。但是,为了向后兼容,我们不想用新字段覆盖现有字段,暂时保留它们。有没有办法让多个字段引用同一个数据库对象?即
现在的代码:
class NetworkPackage:
name = models.CharField(unique=True, blank=False, null=False)
inbound = models.CharField(unique=True, blank=False, null=False)
...
我要实施:
class NetworkPackage:
name = models.CharField(max_length=32, unique=True, blank=False, null=False)
inbound = models.CharField(max_length=128, unique=True, blank=True)
mobile = models.CharField(max_length=128, unique=True, blank=True)
...
基本上,'inbound' 和 'mobile' 应该引用相同的字段,并且可以使用 'inbound' 字段或 'mobile'.
发送请求不知道你为什么要重复字段,但我有一些建议给你。
1.自定义 属性
class NetworkPackage:
name = models.CharField(unique=True, blank=False, null=False)
inbound = models.CharField(unique=True, blank=False, null=False)
@poperty
def mobile(self):
return self.inbound
2。序列化器
class NetworkPackageSerializer(serializers.Serializer):
mobile = serializers.CharField(source='inbound')
class Meta:
model = NetworkPackage
fields = (
'id',
'inbound',
'mobile',
'name',
...
)
在同一个模型中拥有两个包含相同信息的字段是个坏主意,尤其是当您需要强制执行唯一性时,因为
- 您需要保持两个字段的奇偶校验,这意味着如果请求设置
inbound
,那么您还必须设置mobile
。 - 由于唯一性,数据库现在必须索引
inbound
和mobile
。
您可以利用 python 属性,因为属性是您拥有遗留属性的完美解决方案:
class NetworkPackage(models.Model):
name = models.CharField(unique=True, blank=False, null=False)
inbound = models.CharField(unique=True, blank=False, null=False)
...
@property
def mobile(self):
return self.inbound
@mobile.setter
def mobile(self, value):
self.inbound = value
然后在你的序列化器中,你需要:
- 将
mobile
作为附加字段来源添加到inbound
。 - 覆盖两个字段上的
required
和allow_blank
参数,因为序列化程序可以允许任一字段... - 但是,您随后需要编写一个自定义验证方法,以确保 2 个字段中至少有 1 个填充了值。
- 如果两个字段都已填充,则
inbound
值也优先于mobile
值。
class NetworkPackageSerializer(serializers.ModelSerializer):
inbound = serializers.CharField(required=False, allow_blank=True)
mobile = serializers.CharField(source="inbound", required=False, allow_blank=True)
class Meta:
model = NetworkPackage
fields = ("inbound", "mobile", ...)
def validate(self, data):
"""Validate `inbound` and/or `mobile`."""
if not data["inbound"] and not data["mobile"]:
raise serializers.ValidationError("missing value on inbound or mobile")
if data["inbound"]:
del data["mobile"]
else:
del data["inbound"]
return data