Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The serializer field might be named incorrectly and not match any attribute or key on the `GenericRelatedObjectManager` instance

I can't figure out why I'm getting this error "The serializer field might be named incorrectly and not match any attribute or key on the GenericRelatedObjectManager instance. Original exception text was: 'GenericRelatedObjectManager' object has no attribute 'country'.". I been working on this for days, Can someone help me please? What is wrong with my code? Thanks in advance.

I want to create a nested serializer that has a CRUD functionality. Planning to use this in my DRF.

I have 3 interrelated models namely Company, Address, and Country.

  • Company model have a field called "address" and it's a GenericForeignKey.
  • Address model have a field called "country" and it's ForeignKey.
  • Country model is a CountryField(). I'm using django_countries plugin.

Model Structure

Company
 |__Address (GenericForeignKey)
    |___Country (ForeignKey)

Company Model

from django_countries.fields import CountryField

class SalesClientCompany(models.Model):
            address = GenericRelation(
                Address,
                null=True,
                blank=True,
            )

Address Model

class Address(models.Model):

    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE,)

    object_id = models.UUIDField(
        primary_key=False,
        unique=False,
        default=uuid.uuid4,
        blank=True,
        null=True,
    )

    content_object = GenericForeignKey()

    country = models.ForeignKey(
        Country,
        verbose_name=_("Country"),
        to_field='country',
        blank=False,
        on_delete=models.CASCADE,
    )

Country Model

from django_countries.fields import CountryField

class Country(SmardtAbstractHistory):

    country = CountryField(
        unique=True,
    )

    name = SmardtTranslateField(
        models.CharField(
            max_length=50,
            null=True,
        )
    )

Serializers

from rest_framework import serializers
from django.contrib.contenttypes.models import ContentType, ContentTypeManager


from models.client_companies import SalesClientCompany
from country.models.countries import Country
from models.addresses import Address


class CountrySerializer(serializers.ModelSerializer):

    class Meta:
        model = Country
        fields = ('country',)


class ClientCompanyAddressSerializer(serializers.ModelSerializer):
    country = CountrySerializer()
    # country = serializers.SlugRelatedField(queryset=Country.objects.all(), slug_field='country') 
    class Meta:
        model = Address
        fields = ('line_first', 'line_second', 'province', 'country',  'postal_code',)



class ClientCompanySerializer(serializers.ModelSerializer):

    address = ClientCompanyAddressSerializer()

    class Meta:
        model = SalesClientCompany
        fields = ['id', 'name', 'address',  'email', 'phone', 'type', 'company_directory']

    def create(self, validated_data):

        company = SalesClientCompany(
            name=validated_data['name'],
            email=validated_data['email'],
            .....
        )
        company.save()

        content_type = ContentType.objects.get_for_model(SalesClientCompany)

        company_address = Address(
            content_type=content_type,
            object_id=company.pk,
            content_object=company,
            country=validated_data['address']['country'],
            .....

        )

        company_address.save()

        return company

Inspect Serializer

ClientCompanyAddressSerializer():
    line_first = CharField(allow_blank=True, label='Address Line 1', max_length=255, required=False)
    line_second = CharField(allow_blank=True, label='Address Line 2', max_length=255, required=False)
    province = CharField(allow_blank=True, label='State/Province/Region', max_length=255, required=False)
    country = SlugRelatedField(queryset=Country.objects.all(), slug_field='country')    
    postal_code = CharField(allow_blank=True, label='Zip/Postal Code', max_length=255, required=False)

View

class ClientCompanyCreate( generics.ListCreateAPIView ):
    queryset = SalesClientCompany.objects.all()
    serializer_class = ClientCompanySerializer
like image 724
Wreeecks Avatar asked Jan 01 '23 07:01

Wreeecks


1 Answers

Even though your serializers are aware of each other, the serializers don't know how to link the models together. You need to specify the source parameter when initialising the nested serializer, and provide the value of the related_name of the foreign key in the model.

For example:

class ClientCompanyAddressSerializer(serializers.ModelSerializer):
    country = CountrySerializer(source='country_set')
    
    class Meta:
        model = Address
        fields = ('line_first', 'line_second', 'province', 'country',  'postal_code',)

In your code, you did not provide an explicit related_name when defining your ForeignKey field, so Django automatically generated related name country_set (model name + '_set').

See also this answer ("Django Rest Framework Nested Serializers") and this answer ("Include intermediary (through model) in responses in Django Rest Framework").

like image 145
phantom-99w Avatar answered Jan 15 '23 05:01

phantom-99w