如何让我的序列化器从模型中的依赖字段返回数据?

问题描述 投票:-1回答:1

我使用Django 2和Python 3.7。 我设置了这些模型。 其中一个(Coop)使用Many-To-Many方式依赖于另一个(CoopType)。

class CoopTypeManager(models.Manager):

    def get_by_natural_key(self, name):
        return self.get_or_create(name=name)[0]


class CoopType(models.Model):
    name = models.CharField(max_length=200, null=False, unique=True)

    objects = CoopTypeManager()


class CoopManager(models.Manager):
    # Look up by coop type
    def get_by_type(self, type):
        qset = Coop.objects.filter(type__name=type,
                                   enabled=True)
        return qset

    # Look up coops by a partial name (case insensitive)
    def find_by_name(self, partial_name):
        queryset = Coop.objects.filter(name__icontains=partial_name, enabled=True)
        print(queryset.query)
        return queryset

    # Meant to look up coops case-insensitively by part of a type
    def contains_type(self, types_arr):
        filter = Q(
            *[('type__name__icontains', type) for type in types_arr],
            _connector=Q.OR
        )
        queryset = Coop.objects.filter(filter,
                                       enabled=True)
        return queryset


class Coop(models.Model):
    objects = CoopManager()
    name = models.CharField(max_length=250, null=False)
    types = models.ManyToManyField(CoopType)
    address = AddressField(on_delete=models.CASCADE)
    enabled = models.BooleanField(default=True, null=False)
    phone = PhoneNumberField(null=True)
    email = models.EmailField(null=True)
    web_site = models.TextField()

我设置了下面的序列化器,旨在以JSON形式返回数据......

class CoopTypeField(serializers.PrimaryKeyRelatedField):

    queryset = CoopType.objects

    def to_internal_value(self, data):
        if type(data) == dict:
            cooptype, created = CoopType.objects.get_or_create(**data)
            # Replace the dict with the ID of the newly obtained object
            data = cooptype.pk
        return super().to_internal_value(data)

...
class CoopTypeSerializer(serializers.ModelSerializer):
    class Meta:
        model = CoopType
        fields = ['id', 'name']

    def create(self, validated_data):
        """
        Create and return a new `CoopType` instance, given the validated data.
        """
        return CoopType.objects.create(**validated_data)

    def update(self, instance, validated_data):
        """
        Update and return an existing `CoopType` instance, given the validated data.
        """
        instance.name = validated_data.get('name', instance.name)
        instance.save()
        return instance


class CoopSerializer(serializers.ModelSerializer):
    types = CoopTypeSerializer(many=True)
    address = AddressTypeField()

    class Meta:
        model = Coop
        fields = ['id', 'name', 'types', 'address', 'phone', 'enabled', 'email', 'web_site']
        extra_kwargs = {
            'phone': {
                'required': False,
                'allow_blank': True
            }
        }

    def to_representation(self, instance):
        rep = super().to_representation(instance)
        rep['types'] = CoopTypeSerializer(instance.types).data
        rep['address'] = AddressSerializer(instance.address).data
        return rep

    def create(self, validated_data):
        #"""
        #Create and return a new `Snippet` instance, given the validated data.

        coop_types = validated_data.pop('types', {})
        instance = super().create(validated_data)
        for item in coop_types:
            coop_type, _ = CoopType.objects.get_or_create(name=item['name'])  #**item)
            instance.types.add(coop_type)

        return instance

然而,依赖的字段 "type "总是以 "null "的形式返回,尽管事实上我可以看到数据库中存在有效的数据。 以下是我运行curl请求时的情况

curl -v --header "Content-type: application/json" --request GET "http://127.0.0.1:8000/coops/?contains=resource"
[{"id":348,"name":"Garden Resources of Woodlawn (GRoW)","types":{"name":null}

我如何编辑我的序列化器,使其返回依赖类型的值?

django python-3.x django-models serialization django-serializer
1个回答
1
投票

尝试删除 rep['types'] = CoopTypeSerializer(instance.types).datato_representation(...) 方法。

def to_representation(self, instance):
    rep = super().to_representation(instance)
    rep['types'] = CoopTypeSerializer(instance.types).data
    rep['address'] = AddressSerializer(instance.address).data
    return rep

使用 instance.types.all() 而不是 instance.types因为,这里的 instance.types 是一个 经理人 方法,它不返回任何 QuerySet

def to_representation(self, instance):
    rep = super().to_representation(instance)
    rep['types'] = CoopTypeSerializer(instance.types.all(), many=True).data
    rep['address'] = AddressSerializer(instance.address).data
    return rep
© www.soinside.com 2019 - 2024. All rights reserved.