Search code examples
djangodjango-modelsdjango-rest-frameworkdjango-viewsdjango-serializer

Trying to relate tables in Django


trying to POST request and create new location. now the filed country_id cues many troubles. those are the classes

class Country(models.Model):
id = UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
country_name = CharField(max_length=255)
federal_rate = FloatField()
social_security = FloatField()
comment = CharField(max_length=255)

class Location(models.Model):
participant_id = ForeignKey('Participant', on_delete=CASCADE, related_name="locations")
country_id = ForeignKey('Country', on_delete=CASCADE, related_name="country")
start_date = DateField()
end_date = DateField()
region = CharField(max_length=255)
tax_policy = CharField(max_length=255, null=True)

Serializer

class CountrySerializer(serializers.ModelSerializer):

class Meta:
    model = Country
    fields = "__all__"

class LoactionSerializer(serializers.ModelSerializer):
country_id = CountrySerializer(many=False)

class Meta:
    model = Location
    fields = "__all__"

now the only why that I mange to join the tables are adding the country_id line in the seirializer, and whem im trying to create new location, an error occur this is the way I'm trying to add new location

{
"start_date": "2021-10-10",
"end_date": "2021-11-18",
"region": "markian-land",
"tax_policy": "N/A",
"participant_id": "c5c1a00c-4263-418a-9f3a-3ce40a1ea334",
"country_id": "9067e71f-c6b9-4ecc-ad6b-461843063aee"
}

the Error - {"country_id": {"non_field_errors": ["Invalid data. Expected a dictionary, but got str."]}}

when i mange to send as dict, but i have another error that asking for all Country fields, so i get the specific country from data base, and when im sending it i got json error


Solution

  • You can have more details in this answer

    Django Rest Framework doesn't provide this functionality, you need to create a serializer field first.

    from rest_framework import serializers
    
    
    class RelatedFieldAlternative(serializers.PrimaryKeyRelatedField):
        def __init__(self, **kwargs):
            self.serializer = kwargs.pop('serializer', None)
            if self.serializer is not None and not issubclass(self.serializer, serializers.Serializer):
                raise TypeError('"serializer" is not a valid serializer class')
    
            super().__init__(**kwargs)
    
        def use_pk_only_optimization(self):
            return False if self.serializer else True
    
        def to_representation(self, instance):
            if self.serializer:
                return self.serializer(instance, context=self.context).data
            return super().to_representation(instance)
    

    Then use this new serializer field in Location serializer as,

    class LoactionSerializer(serializers.ModelSerializer):
        country_id = RelatedFieldAlternative(queryset = Country.objects.all(),
                         serializer=CountrySerializer)
    
        class Meta:
            model = Location
            fields = "__all__"
    

    Please note: You have a typo in LoactionSerializer.