Почему поле внешнего ключа в сериализаторе django rest-frame работает только для чтения? - PullRequest
0 голосов
/ 06 октября 2018

У меня есть две модели, как показано ниже

class Cluster(models.Model):

    _id = models.UUIDField(unique=True, null=False, default=uuid.uuid1)
    name = models.CharField(max_length=200, unique=True, null=False)

class Node(models.Model):
    _id = models.UUIDField(unique=True, null=False, default=uuid.uuid1)
    ip = models.GenericIPAddressField(null=False, unique=True)
    cluster = models.ForeignKey(Cluster, on_delete=models.PROTECT, to_field='_id')

Как вы можете видеть выше.Узел будет иметь ссылку на внешний ключ для кластера, что означает, что узел принадлежит одному кластеру. Я использую уникальный ключ, поданный _id, в качестве внешнего ключа вместо первичного ключа.

Затем я создаю сериализатор

class NodeSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Node
        fields = ('_id', 'ip', 'cluster_id')

Сериализатор работает нормально при полученииданные из базы данных.Но есть проблема при создании

>>> print(NodeSerializer())
NodeSerializer():
    _id = UUIDField(required=False, validators=[<UniqueValidator(queryset=Node.objects.all())>])
    ip = IPAddressField(validators=[<UniqueValidator(queryset=Node.objects.all())>])
    cluster_id = ReadOnlyField()

Так как cluster_id является ТОЛЬКО ДЛЯ ЧТЕНИЯ, поэтому serializer.validated_data всегда будет пропускать поле cluster_id.

Итак, как я могу создать узел с этим сериализатором?

1 Ответ

0 голосов
/ 06 октября 2018

cluster_id - дополнительный атрибут, сгенерированный ForeignKey.Вы должны использовать cluster, чтобы сделать поле доступным для записи:

class NodeSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Node
        fields = ('_id', 'ip', 'cluster')

Или использовать PrimaryKeyRelatedField с аргументом источника, чтобы переименовать поле на уровне сериализатора:

class NodeSerializer(serializers.ModelSerializer):
    cluster_id = serializers.PrimaryKeyRelatedField(source='cluster', queryset=Cluster.objects.all())

    class Meta:
        model = models.Node
        fields = ('_id', 'ip', 'cluster_id')
...