Разрешить дубликаты в отношении «многие ко многим» в SlugRelatedField - PullRequest
0 голосов
/ 05 сентября 2018

У меня SlugRelatedField настроено так:

items = serializers.SlugRelatedField(
    slug_field='name', many=True, queryset=Item.objects.all())

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

{
    items: [
        "item1",
        "item1",
        "item2",
    ]
}

Однако, если я запрашиваю тот же объект, я получаю следующее:

{
    items: [
        "item1",
        "item2",
    ]
}

Как мне сделать так, чтобы DRF вставлял именно то, что я посылаю, а не удалял дубликаты.

1 Ответ

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

Мне удалось решить эту проблему, сделав три изменения. Весь приведенный ниже код был изменен, чтобы избежать проблем с авторским правом в моей компании, поэтому извините, если я сделал опечатку. Во-первых, я создал собственную модель «многие ко многим», которая допускает дублирование записей:

class FooBar(models.Model):
    foo = models.ForeignKey(
        Foo, on_delete=models.SET_NULL, null=True)
    bar = models.ForeignKey(
        Bar, on_delete=models.SET_NULL, null=True)

Затем я добавил аргумент through в поле ManyToMany моего класса Foo, чтобы использовать новую модель:

class Foo(models.Model):
    items = models.ManyToManyField(Foo, through='FooBar')

Однако, просто выполнение этого вызывает AttributeError: Cannot set values on a ManyToManyField which specifies an intermediary model. Use my_package.FooBar's Manager instead. Это потому, что Django Rest Framework не может автоматически создавать пользовательские модели «многие ко многим». Поэтому нам нужно реализовать несколько пользовательских методов сериализатора, чтобы обойти это:

def create(self, validated_data):
    instance = Foo()
    instance.x = validated_data['x']
    instance.y = validated_data['y']
    instance.save()
    for bar in validated_data['bars']:
        relation = FooBar(foo=instance, bar=bar)
        relation.save()
    return instance

def update(self, instance, validated_data):
    instance.table = validated_data.get('x', instance.x)
    instance.status = validated_data.get('y', instance.y)
    instance.save()
    if 'bars' in validated_data:
        FooBar.objects.filter(foo=instance).delete()
        for bar in validated_data.get('bars', []):
            relation = FooBar(foo=instance, bar=bar)
            relation.save()
    return instance
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...