Создать метод для отношений внешнего ключа с сериализаторами Django Rest Framework - PullRequest
0 голосов
/ 11 ноября 2018

Мои модели такие:

class FirewallPolicy(models.Model):
    name = models.CharField(max_length=100, unique=True)
    team = models.ForeignKey(Team)
    source_ip = models.ForeignKey(IP)
    destination_ip = models.ForeignKey(IP)

Теперь, для создания новой политики брандмауэра, уже должны быть существующая команда, source_ip и destination_ip. Моя полезная нагрузка для создания новой политики брандмауэра выглядит следующим образом:

{"name": "test-create-policy-911",
 "team": "avengers",
 "source_ip": "1.1.1.1",
 "destination_ip": "2.2.2.2",
}

Мой сериализатор для создания новой политики брандмауэра выглядит следующим образом:

class FirewallPolicyCreateSerializer(serializers.ModelSerializer):
    name = serializers.CharField(max_length=100)
    team = serializers.CharField(max_length=100)
    source_ip = serializers.CharField(max_length=100)
    destination_ip = serializers.CharField(max_length=100)

    class Meta:
        model = Policy
        fields = ['id', 'name', 'team', 'source_ip', 'destination_ip']

    def validate(self, data):
        try:
            Team.objects.get(name=data['team'])
            IP.objects.get(name=data['source_ip'])
            IP.objects.get(name=data['destination_ip'])
        except ObjectDoesNotExist:
            raise serializers.ValidationError("Entities must exist before you can associate it with a Firewall Policy")

    def create(self, validated_data):
        team = Team.objects.get(name=validated_data['team'])
        source_ip = IP.objects.get(name=validated_data['source_ip'])
        destination_ip = IP.objects.get(name=validated_data['destination_ip'])
        policy  = Policy.objects.create(name=validated_data['name'], 
                                        team_id=team.id, 
                                        source_ip_id = source_ip.id, 
                                        destination_ip_id = destination_ip.id )
        return policy 

Я не уверен, что это правильный способ добавления внешних ключей в модель, так как это кажется слишком большой работой. Что-то мне не хватает, когда сериализатор может автоматически все это проверить и добавить внешние ключи?

1 Ответ

0 голосов
/ 11 ноября 2018

Да, вы делаете гораздо больше работы, чем нужно.

Вы должны определить свои поля, используя SlugRelatedField , чтобы позволить DRF автоматически заполнять их из поля в связанной модели. Итак:

class FirewallPolicyCreateSerializer(serializers.ModelSerializer):
    team = serializers.SlugRelatedField(queryset=Team.objects.all(), slug_field='name')
    source_ip = serializers.SlugRelatedField(queryset=IP.objects.all(), slug_field='source_ip')
    destination_ip = serializers.SlugRelatedField(queryset=IP.objects.all(), slug_field='destination_ip')

    class Meta:
        model = Policy
        fields = ['id', 'name', 'team', 'source_ip', 'destination_ip']

Теперь вам вообще не нужно определять validate или create, поскольку DRF выполнит все соответствующие проверки и назначения.

(Обратите внимание, вам также не нужно было переопределять поле name, так как вы ничего не меняете из базового поля модели.)

...