Jak vytvářet 2 objekty z různých modelů s jedním serializer a také je získat z databáze s jedním serializátor v Django RF?

0

Otázka

Mám 3 modely: Výrobce, Produkt a MakerItem, že vytváří vztah mezi předměty a jejich tvůrci:

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)

položky mohou mít náhodné množství tvůrců.

Chci vytvořit obě Položky a MakerItem objektů současně s jediným souborem dat, například, pokud Výrobce s id = "abcd" již existuje, a já jít do /položky a odeslat POST požadavek s následujícími údaji:

{
    "name": "item1",
    "makers": [
        {
            "maker_id": "abcd"
        }
    ]
}

Chci serializátor na Položku vytvořit objekt a MakerItem objektu. Jsem dosáhl tohoto, s následující nastavení:

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

ale když Django se pokusí vrátit vytvořený objekt, je to vždy dává mi chybu:

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'.

Co dělám špatně?

Díky

EDIT: Pro upřesnění, objekty, které si vytvořili, a naplnění databáze správně, ale když browsable API, které DRF poskytuje pokusí zobrazit vytvořený objekt, to mi dává chybu výše.

1
0

Změnit:

class ItemSerializer(serializers.ModelSerializer):
    class MakerItemSerializer(serializers.ModelSerializer):
        class Meta:
            model = MakerItem
            exclude = ['id', 'item_id']

    makers = MakerItemSerializer(many=True)

K:

class ItemSerializer(serializers.ModelSerializer):
    class MakerItemSerializer(serializers.ModelSerializer):
        class Meta:
            model = MakerItem
            exclude = ['id', 'item_id']

    makers = MakerItemSerializer(many=True, source="makeritem_set")

Doufám, že to funguje!

Pro přehlednost se pokoušíte serialise reverzní vztah mezi MakerItem a Položky pro tento serialiser.

To znamená, že atribut objektu, je automaticky nastaven jako Django fieldname_set ale můžete přepsat toto chování nastavením related_name kwarg na pole a pak makemigrations a migrate to.

Ve vašem případě by bylo třeba udělat:

maker_id = models.ForeignKey(Maker, on_delete=models.CASCADE, related_name="maker_items")

A potom aktualizujte pole v Meta, aby odpovídaly novému názvu pole, tímto způsobem, nemusíte ručně zadat zdroj. Protože vlastně atribut "tvůrci" je zavádějící, vzhledem k tomu, jeho vlastně MakerItem, ne Výrobce sám.

Vidět https://docs.djangoproject.com/en/3.2/ref/models/relations/ pro další informace o tomto chování.

2021-11-24 14:14:06

Ahoj, mohl bys upřesnit to trochu? Já opravdu nerozumím, co tím myslíš
obvionaoe

Swift

@obvionaoe aktualizováno odpověď
Swift

Díky, nakonec jsem pomocí ManyToManyField! Existuje způsob, jak přepsat id pole pro ManyToManyField? Je to výchozí hodnota auto increment číslo ale já to potřebuju použít UUID
obvionaoe

Já bych to doporučit. Dalo by se jistě přidat UUID pole. Google, taková věc existuje, použil jsem to! :)
Swift

Proč ne? Bude to něco rozbít? Má problémy s výkonem? Používám PostgreSQL
obvionaoe

Ne, můžete znovu přiřadit, ale já opravdu nejsem jistý, proč byste zvolit, aby re-přiřadit auto increment ID s UUID. Snažíte se dělat něco konkrétně? Jako, je to volba designu? Pokud ano, tak proč?
Swift

všechny ostatní tabulky použít Uuid, to dává smysl použít jeden v to taky věřím
obvionaoe

V jiných jazycích

Tato stránka je v jiných jazycích

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................