Django Rest - ManyToManyField с данными SlugRelatedField не создается - PullRequest
1 голос
/ 18 января 2020

В моей базе данных есть следующая структура:

{
        "name": "sum",
        "formula": "a+b",
        "date": "2020-01-17T19:02:24.143000Z",
        "tags": [
            "sum",
            "test"
        ],
        "latex": "a+b"
    }

«tags» - это поле в Table Calculator с отношением ManyToManyField. Я использовал промежуточную модель ( TagLink ), которая указывает внешние ключи к калькулятору и модели тегов, которые связаны с отношением ManyToMany.

Модели:

class Tag(models.Model):
    name = models.CharField(max_length=25, primary_key=True, db_column='sTag')

    class Meta:
        db_table = 'tTag'

class Calculator(models.Model):
    name = models.CharField(max_length=100, primary_key=True, db_column='sName')
    formula = models.CharField(max_length=200, db_column='sFormula')
    date = models.DateTimeField(auto_now=True, db_column='dtModifiedDate')
    tags = models.ManyToManyField(Tag, through='TagLink', through_fields=('calculator', 'tag'), related_name='calculator', symmetrical=False)

    class Meta:
        db_table = 'tCalculator'

class TagLink(models.Model):
    calculator = models.ForeignKey(Calculator, on_delete=models.CASCADE, db_column='sCalculator')
    tag = models.ForeignKey(Tag, on_delete=models.CASCADE, db_column='sTag')

    class Meta:
        db_table = 'tTagLink'
        auto_created = True
        unique_together = [['calculator', 'tag']]

Вот Сериализатор :

class TagSerializer(serializers.ModelSerializer):
    class Meta:
        model = Tag
        fields = ['name']

class CalculatorSerializer(serializers.ModelSerializer):
    tags = serializers.SlugRelatedField(
        many=True, queryset=Tag.objects.all(), slug_field='name')

    class Meta:
        model = Calculator
        fields = ['name', 'formula', 'date', 'tags']

    def create(self, validated_data):
        tags = validated_data.pop('tags')
        calculadora = self.Meta.model.objects.create(**validated_data)

        for tag in tags:
        obj, _ = Tag.objects.get_or_create(name=tag)
        calculadora.tags.add(obj)

         calculadora.save()
         return calculadora

-> У меня проблемы с созданием нового «тега» в create () method;

(1) Условие успеха: тег создан успешно, если он уже существует в базе данных (таблица TagLink):

(Pdb) calc_serializer.data
{'name': 't4', 'formula': 'r', 'date': '2020-01-17T18:54:18.448332Z', 'tags': ['erika'], 'inputs': [OrderedDict([('name', 'r'), ('calculatorName', 't4'), ('isCalculator', False), ('isArray', False), ('isMatrix', False)])]}

(2) Условие сбоя: если тег не существует в базе данных, тег не создается, и я получаю следующую ошибку «CalculatorNotFound»:

return CalculatorNotFoundException(logger, request_json['name']).response

Ps .: calc_serializer .data возвращается правильно. Но происходит то, что calc_serializer не проверяет.

Может ли кто-нибудь помочь мне обойти эту ошибку? Я целыми днями пытаюсь это выяснить! : /

Спасибо большое !!!

Ответы [ 2 ]

1 голос
/ 31 января 2020

Я нашел ошибку! \ o /

Я исправил условие сбоя (если тег не существует в базе данных). Я сделал следующее: Перед сохранением калькулятора я сначала сохраняю теги в базе данных. Таким образом, я могу обновить теги !!!!

for tag_name in request_json['tags']:
            tag_object = Tag.objects.get_or_create(name=tag_name)
            tag_serializer = TagSerializer(data={'name': tag_name}) # -> I save first to the database

        calc_serializer = CalculatorSerializer(data=request_json)

        if calc_serializer.is_valid():
            calc_serializer.save()

            response = JsonResponse(
                calc_serializer.data, status=status.HTTP_201_CREATED)

            return response

Я особенно благодарен @DaviWesley за помощь! :)

0 голосов
/ 18 января 2020

Ваш код говорит, что если у меня есть существующий тег для связи с Калькулятором, вам не нужно проверять, существует ли Tag, вы можете просто использовать get_or_create метод , чтобы получить существующий Tag или создайте новое, вы также пытаетесь добавить отношение модели string в Calculator, помните, что в вашем случае validated_data.pop('tags') представляет собой list из strings, как это ['erika']

def create(self, validated_data):
        tags = validated_data.pop('tags')
        calculadora = self.Meta.model.objects.create(**validated_data)

        for tag in tags:
            # return the Tag object model
            obj, _ = Tag.objects.get_or_create(name=tag)
            calculadora.tags.add(obj)

        calculadora.save()
        return calculadora

Полезный обучающий персонал:

...