Как создать 2 объекта из отдельных моделей с помощью одного сериализатора, а также получить их из базы данных с помощью одного сериализатора в Django RF?
У меня есть 3 модели: Maker, Item и MakerItem, которые создают связь между предметами и их создателями:
class Maker(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4)
name = models.CharField(max_length=100)
class Item(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4)
name = models.CharField(max_length=100)
class MakerItem(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4)
item_id = models.ForeignKey(Item, on_delete=models.CASCADE)
maker_id = models.ForeignKey(Maker, on_delete=models.CASCADE)
предметы могут иметь случайное количество производителей.
Я хочу создать одновременно объекты Item и MakerItem с одним набором данных, например, если Maker с id = "abcd" уже существует, и я иду в /item и отправляю POST запрос со следующими данными:
{
"name": "item1",
"makers": [
{
"maker_id": "abcd"
}
]
}
Я хочу, чтобы сериализатор создавал объект Item и объект MakerItem. Я достиг этого со следующей установкой:
views.py
class ItemListCreate(ListCreateAPIView):
queryset = Item.objects.all()
serializer_class = ItemSerializer
serializers.py
class ItemSerializer(serializers.ModelSerializer):
class MakerItemSerializer(serializers.ModelSerializer):
class Meta:
model = MakerItem
exclude = ['id', 'item_id']
makers = MakerItemSerializer(many=True)
class Meta:
model = Item
fields = ['id', 'name', 'makers']
def create(self, validated_data):
maker_item_data = validated_data.pop('makers')
item_instance = Item.objects.create(**validated_data)
for each in maker_item_data:
MakerItem.objects.create(
item_id=check_instance,
maker_id=each['maker_id']
)
return item_instance
но когда Django пытается вернуть созданный объект, он всегда выдает мне ошибку:
AttributeError at /item/
Got AttributeError when attempting to get a value for field `makers` on serializer `ItemSerializer`.
The serializer field might be named incorrectly and not match any attribute or key on the `Item` instance.
Original exception text was: 'Item' object has no attribute 'makers'.
Что я делаю не так?
Спасибо
Изменение:
makers = MakerItemSerializer(many=True)
To:
makers = MakerItemSerializer(many=True, source="makeritem_set")
Надеюсь, это сработает!
Для ясности, вы пытаетесь сериализовать обратное отношение между MakerItem и Item для этого сериализатора.
Это означает, что атрибут на вашем объекте автоматически устанавливается Django как fieldname_set
, но вы можете переопределить это поведение, установив related_name
kwarg на поле, а затем makemigrations
и migrate
его.
В вашем случае вам нужно сделать следующее:
maker_id = models.ForeignKey(Maker, on_delete=models.CASCADE, related_name="maker_items")
А затем обновите поле в Meta, чтобы оно соответствовало новому имени поля, таким образом, вам не придется вручную указывать источник. Потому что на самом деле атрибут "makers" вводит в заблуждение, поскольку на самом деле это MakerItem, а не сам Maker.