I have these two models with their serializers:
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)
The problem is when i try to create a prescription serializer during a unit test (the test suppose to fail due to duration, it should not exceed 90) during a unit test:
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']))
I got an unexpected error: Field 'id' expected a number but got <Customer: Lary>.
Even i'm providing the customer id not the customer itself, What is weird though, it were all god, but suddenly it doesn't work anymore.
The Prescription serializer:
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')
CodePudding user response:
Your code should be something like this:
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']))
CodePudding user response:
I guess the root problem was in the validation function for ChronicPrescription model, that's why the code was working before it:
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.')
When we serialize the prescription the validation method got a customer instance as a parameter, that's why i got the error : expected a number but got Customer: Lary>. due to
customer = Customer.objects.get(pk=value)
So i refactor the validation method as follow:
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.')
And it worked fine.