我有这两个模型及其序列化程序:
class ChronicPrescription
chronic_prescription_id = models.AutoField(primary_key=True)
date = models.DateField(default=datetime.date.today, validators=[no_future_date, no_old_date])
# This field is for the prescription duration in days
duration = models.PositiveIntegerField(default=90, validators=[MaxValueValidator(90), MinValueValidator(30)])
customer = models.ForeignKey('customers.Customer', on_delete=models.CASCADE, related_name="chronic_prescription",
validators=[prescriptions_for_patient_only])
class Customer(models.Model):
id = models.BigAutoField(primary_key=True)
customer_name = models.CharField(max_length=100, null=False, blank=False, unique=True)
phones = ArrayField(models.CharField(max_length=10, validators=[validate_phone_number, prevent_replicated_phone]),
default=list, null=True, blank=True)
customer_type = models.CharField(max_length=10,default='patient', choices=CUSTOMER_TYPE)
问题是,当我试图在单元测试期间创建一个处方序列化程序时(由于持续时间的原因,测试假设失败,不应超过90(:
def test_upper_bound_duration(self):
customer = Customer.objects.create(customer_name="Lary")
prescr_serializer = ChronicPrescriptionSerializer(data={'duration': 1000, 'customer': customer.id})
if prescr_serializer.is_valid():
prescr_serializer.save()
self.assertFalse(prescr_serializer.is_valid())
self.assertEqual(set(prescr_serializer.errors), set(['duration']))
我遇到了一个意外错误:字段"id"应为数字,但得到<客户:拉里>。
即使我提供的是客户id,而不是客户本身,但奇怪的是,这一切都是上帝,但突然间就不起作用了。
处方序列化程序:
class ChronicPrescriptionSerializer(serializers.ModelSerializer):
drugs = PrescriptionItemSerializer(many=True, read_only=True)
notification_status = serializers.BooleanField(default=True)
left_days = serializers.SerializerMethodField()
def get_left_days(self, obj):
return obj.count_left_days()
class Meta:
model = ChronicPrescription
fields = ('chronic_prescription_id', 'date', 'duration', 'notification_status', 'left_days', 'drugs', 'customer')
您的代码应该是这样的:
def test_upper_bound_duration(self):
customer = Customer.objects.create(customer_name="Lary")
customer.save()
prescr_serializer = ChronicPrescriptionSerializer(data={'duration': 1000, 'customer': customer.id})
if prescr_serializer.is_valid():
prescr_serializer.save()
self.assertFalse(prescr_serializer.is_valid())
self.assertEqual(set(prescr_serializer.errors), set(['duration']))
我想根本问题出在ChronicPrescription模型的验证函数中,这就是代码在它之前工作的原因:
def prescriptions_for_patient_only(value):
customer = Customer.objects.get(pk=value)
if customer.customer_type != 'patient':
raise ValidationError('Only patient customer can have prescriptions.')
当我们序列化处方时,验证方法得到了一个客户实例作为参数,这就是为什么我得到了错误:应该是一个数字,但得到了customer:Lary>。由于
customer = Customer.objects.get(pk=value)
因此,我重构验证方法如下:
def prescriptions_for_patient_only(value):
if isinstance(value, int):
customer = Customer.objects.get(pk=value)
else:
customer = value
if customer.customer_type != 'patient':
raise ValidationError('Only patient customer can have prescriptions.')
而且效果很好。