Home > Net >  Field 'customer_id' expected a number but got <Customer: Lary>
Field 'customer_id' expected a number but got <Customer: Lary>

Time:09-10

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.

  • Related