Как мне настроить мой Django сериализатор так, чтобы он принимал массив полей? - PullRequest
1 голос
/ 04 апреля 2020

Я использую Django 2.0 и Python 3.7. У меня есть следующие модели (CoopType - это поле «многие ко многим» Coop) ...

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)

    objects = CoopTypeManager()

    class Meta:
        unique_together = ("name",)


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)
    #type = models.ForeignKey(CoopType, on_delete=None)
    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()

Я не знаю, как правильно создать сериализатор для приема входных данных , У меня есть эти сериализаторы ...

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 CoopSerializer(serializers.ModelSerializer):
    type = CoopTypeField()
    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['type'] = CoopTypeSerializer(instance.type).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.
        """
        CoopSerializer.update_coords(validated_data)
        return Coop.objects.create(**validated_data)

Однако, это приводит к следующей ошибке

AssertionError: The field 'type' was declared on serializer CoopSerializer, but has not been included in the 'fields' option.

, когда я отправляю запрос (JSON ниже). Как лучше настроить мои сериализаторы?

{
        "name": "6899",
        "types": [
            {"name": "Coworking Space"},
            {"name": "Library"}
        ],
        "address": {
            "formatted": "222 W. Merchandise Mart Plaza, Suite 1212",
            "locality": {
                "name": "Chicago",
                "postal_code": "60654",
                "state": 19313
            }
        },
        "enabled": true,
        "phone": "312473",
        "email": "laredotornado@msn.com",
        "web_site": "http://www.1871.com/"
}
...