我正在设计一个API,它将由不同的合作伙伴使用。以下是API虚拟有效负载:-
{
key1: value1,
key2: value2,
key3: value3,
key4: value4,
key5: value5,
partner: partner_code
}
现在,我有一个模型,其中需要保存以上字段。
class Table(models.Model):
key1 = models.IntegerField()
key2 = models.IntegerField(blank=True, null=True)
key3 = models.IntegerField()
key4 = models.IntegerField(blank=True, null=True)
key5 = models.CharField(max_length=255)
partner = models.ForeignKey(Partner)
另外,我有一个序列化器:-
class TableSerializer(models.Model):
class Meta:
model = Table
fields = '__all__'
现在,每当发布数据时,我都会序列化(并验证)数据,然后将其保存。这是我的方法。
serializer = TableSerializer(data=payload)
if serializer.is_valid():
serializer.save()
这是正常的DRF流程。现在,出现的问题是我需要对每个合作伙伴应用自定义验证。例如:-
`key2` and `key4` are mandatory for PartnerA. Similarly, for PartnerB, max value of `key1` is 100 and many more.
根据当前的DRF流,我需要在序列化器中添加if-else
条件。
class TableSerializer(models.Model):
def validate(self, data):
if partner == `partnerA`:
# checkfor key1 max value.
# check the mandatory fields.
elif partner == `partnerB`:
# some custom validations
# and so on
class Meta:
model = Table
fields = '__all__'
这个if-else
可能会继续增长,这是一个糟糕的设计。如何引入另一个名为 Validation Engine
的组件,它可以首先验证数据,然后将经过验证的数据传递给DRF序列化器?
答案 0 :(得分:0)
您可以使用partner == partnerB
或类似的方法编写更多的序列化器(该序列化器仅用于验证),并执行以下工作:
def validate(self, data):
data_is_valid = False
for serializer_class in selializers_for_validate:
serializer = serializer_class(data=data)
is_valid = serializer.is_valid()
if is_valid:
break
if not is_valid:
raise serializers.ValidationError(<here your custom error>)
return data
我认为这个决定不是很好,但是您可以尝试, 或者您可以编写自定义验证器并在validate中使用
答案 1 :(得分:0)
我建议仅通过基本验证以及合作伙伴id / name / type / etc与特定序列化器之间的映射来制作基本序列化器:
from django.db import models
from rest_framework import serializers
from rest_framework.viewsets import ModelViewSet
# models.py
class Table(models.Model):
key1 = models.IntegerField()
key2 = models.IntegerField(blank=True, null=True)
key3 = models.IntegerField()
key4 = models.IntegerField(blank=True, null=True)
key5 = models.CharField(max_length=255)
partner = models.ForeignKey(Partner)
# serializers.py
class TableSerializer(serializers.ModelSerializer):
partner_serializers = {}
class Meta:
model = Table
fields = '__all__'
def validate(self, data):
self.partner_serializers[data['partner']['partner_id']](
instance=self.instance,
data=data
).is_valid(raise_exception=True)
return super().validate(data)
@classmethod
def register_partner_validator(cls, partner_id):
def wrapped(serializer):
cls.partner_serializers[partner_id] = serializer
return serializer
return wrapped
@TableSerializer.register_partner_validator('thePartner1')
class Partner1TableSerializer(TableSerializer):
class Meta:
extra_kwargs = {
'key3': {'max_value': 3}
}
def validate(self, data):
if data['key1'] + data['key2'] > 5:
raise serializers.ValidationError('Wrong!')
@TableSerializer.register_partner_validator('thePartner2')
class Partner2TableSerializer(TableSerializer):
def validate(self, data):
if data['key1'] + data['key5'] < 5:
raise serializers.ValidationError('Wrong!')
# views.py
class TableViewSet(ModelViewSet):
queryset = Table.objects.all()
serializer_class = TableSerializer