Home > Enterprise >  Django serializer does not recognize relation attribute
Django serializer does not recognize relation attribute

Time:05-02

what im trying to do

I'm creating a django API and currently i'm trying to request(GET) all the farmers(model) from my database, but every time I try to do so I ended up receiving a response saying that a property from my model isnt declared even though it's clearly declared. I've been struggling with this for a couple of days, your wisdom and knowledge on this situation is greatly appreciated.

Error:

Exception Type: AttributeError
Exception Value:    
'Farmer' object has no attribute 'property'

models.py:

  class Farmer(AbstractUser):

    active = models.BooleanField(default=True)
    age = models.PositiveSmallIntegerField(blank=True, default=18)
    cpf = models.CharField(max_length=11, unique=True, default='')
    phone = models.CharField(blank=True, max_length=11, unique=True, default='')
    sex = models.CharField(blank=True, max_length=11, unique=False, default='')

    class Meta:
        ordering = ['id']
        verbose_name = 'farmer'
        verbose_name_plural = 'farmers'

    def __str__(self):
        return self.username

    @receiver(post_save, sender=settings.AUTH_USER_MODEL)
    def create_auth_token(sender, instance=None, created=False, **kwargs):
        if created:
            Token.objects.create(user=instance)


class Property(models.Model):

    name = models.CharField(blank=False, max_length=255)
    size = models.DecimalField(blank=False, max_digits=100, decimal_places=1)
    phone = models.CharField(blank=False, max_length=11, unique=True)
    longitude = models.DecimalField(blank=False,decimal_places=16,max_digits=1000)
    latitude = models.DecimalField(blank=False,decimal_places=16,max_digits=1000)
    
    farmer = models.ForeignKey(
        Farmer,
        related_name='property_farmer',
        on_delete=models.DO_NOTHING
    )

    class Meta:
        ordering = ['id']
        verbose_name = 'property'
        verbose_name_plural = 'properties'
        unique_together = ['id', 'farmer']

    def __str__(self):
        return f'the {self.name} property is owned by {self.farmer.username}'

serializers.py:

class FarmerSerializer(serializers.ModelSerializer):

    property = serializers.HyperlinkedRelatedField(
        many=True,
        view_name='property-detail',
        read_only=True
    )

    class Meta:
        model = Farmer
        fields = [
            'id', 'username', 'cpf', 
            'email', 'age', 'phone', 
            'sex', 'active', 'password', 'property'
        ]
        extra_kargs = {
            'cpf': {'write_only': True},
            'active': {'read_only': True}
        }

views.py:

@api_view(['GET', 'POST'])
def farmer_CR(request, format=None):

    if request.method == 'GET':
        serializer = FarmerSerializer(Farmer.objects.all(), many=True)
        return Response(serializer.data, status=status.HTTP_200_OK)
    
    elif request.method == 'POST':
        serializer = FarmerSerializer(data=request.data)
        if serializer.is_valid():
            _saveFarmer(serializer)
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        else: return Response(status=status.HTTP_400_BAD_REQUEST)

    else: 
        return Response(status=status.HTTP_400_BAD_REQUEST)

CodePudding user response:

you can use SerializerMethodField: https://www.django-rest-framework.org/api-guide/fields/#serializermethodfield

class FarmerSerializer(serializers.ModelSerializer):

    class Meta:
        model = Farmer
        fields = [
            'id', 'username', 'cpf', 
            'email', 'age', 'phone', 
            'sex', 'active', 'password', 'property'
        ]
        extra_kargs = {
            'cpf': {'write_only': True},
            'active': {'read_only': True}
        }
        property = serializers.SerializerMethodField()


        def get_farmers_property(self, farmer_obj):
            all_farmers_property = Property.ojbects.filter(farmer = farmer_obj)
            return all_farmers_property

CodePudding user response:

'Farmer' object has no attribute 'property', because it has 'property_farmer' :)

in your property model you should:

 farmer = models.ForeignKey(
        Farmer,
        related_name='property',
        on_delete=models.DO_NOTHING
    )

Change related_name to 'property' so you can access property as farmer.property and not farmer.property_farmer.

  • Related