处理与Django的REST框架的外键关系?

z4bn682m  于 2023-10-21  发布在  Go
关注(0)|答案(1)|浏览(116)

**说明:**我是第一次创建Django应用,使用的是rest框架。我的目标是使用REST框架来测试一个创建新“Artwork”并将其添加到数据库中的post请求。艺术品包含标题、宽度、高度等列。它还包含一个名为“artist_id”的外键列。这个外键链接到我的“Artist”表的主键。在我的artist表中,我有一个artist_name列。
我在Models.py中的“Artwork”和“Artist”表:

class Artwork(models.Model):
    idartwork = models.AutoField(
        db_column="idArtwork", primary_key=True
    )  # Field name made lowercase.
    title = models.CharField(max_length=50, blank=True, null=True)
    date_created_month = models.IntegerField(blank=True, null=True)
    date_created_year = models.TextField(
        blank=True, null=True
    )  # This field type is a guess.
    comments = models.CharField(max_length=255, blank=True, null=True)
    width = models.DecimalField(max_digits=10, decimal_places=3, blank=True, null=True)
    height = models.DecimalField(max_digits=10, decimal_places=3, blank=True, null=True)
    artist = models.ForeignKey(Artist, models.DO_NOTHING, blank=True, null=True)

    class Meta:
        managed = False
        db_table = "artwork"

class Artist(models.Model):
    idartist = models.AutoField(
        db_column="idArtist", primary_key=True
    )  # Field name made lowercase.
    artist_name = models.CharField(
        max_length=40, db_collation="utf8_general_ci", blank=True, null=True
    )

    class Meta:
        managed = False
        db_table = "artist"

**我的问题:**为了测试我的描述中描述的帖子请求,我的直觉如下。首先创建一个视图,该视图将使用输入的名称更新artist表。然后,传递主键'idArtist'并将其存储在输入的艺术品列(标题,宽度等)旁边。不过,我不确定如何将这两个合并结合在一起。目前,我将视图和序列化器分开:

创建插图视图(views.py):

class CreateArtworkView(APIView):
    serializer_class = ArtworkSerializer

    def post(self, request, format=None):
        serializer = self.serializer_class(data=request.data)

        if serializer.is_valid():
            title = serializer.data.get("title")
            date_created_month = serializer.data.get("date_created_month")
            date_created_year = serializer.data.get("date_created_year")
            comments = serializer.data.get("comments")
            width = serializer.data.get("width")
            height = serializer.data.get("height")

            artwork = Artwork(
                title=title,
                date_created_month=date_created_month,
                date_created_year=date_created_year,
                comments=comments,
                width=width,
                height=height,
            )

            artwork.save()

            return Response(
                ArtworkSerializer(artwork).data, status=status.HTTP_201_CREATED
            )

创建艺术家视图(views.py):

class CreateArtistView(APIView):
    serializer_class = ArtistSerializer

    def post(self, request, format=None):
        serializer = self.serializer_class(data=request.data)

        if serializer.is_valid():
            artist_name = serializer.data.get("artist_name")

            artist = Artist(artist_name=artist_name)

            artist.save()

            return Response(
                ArtworkSerializer(artist).data, status=status.HTTP_201_CREATED
            )

Serializers.py:

class ArtistSerializer(serializers.ModelSerializer):
    class Meta:
        model = Artist
        fields = ["artist_name"]

class ArtworkSerializer(serializers.ModelSerializer):
    class Meta:
        model = Artwork
        fields = (
            "title",
            "date_created_month",
            "date_created_year",
            "comments",
            "width",
            "height",
            "artist",
        )

现在在rest框架中看起来是什么样子:

插图(注:艺术家下拉列表中的所有当前的artist_id的数据库中。我希望能够输入一个艺术家的名字有一个新的artist_id创建的艺术品):

艺术家:

**问题重申:**如何将这两个视图合并组合在一起,以便在一个post请求中完成,并根据插入到Artist表中的内容更新fk artist_id?

我尝试了代码(提供的代码片段),分别做他们。它目前将更新数据库,但它们不同步。通过'同步'我的意思是,我需要能够收到一次所有的数据后请求(在提供的图片HTML形式),并更新数据库。

bvhaajcl

bvhaajcl1#

要实现在一个POST请求中创建一个新的“Artwork”并将其与一个“Artist”关联的目标,您可以在视图中进行一些调整,以覆盖视图集的create方法。以下是你可以做的事情来实现这一点:

步骤1:为您的“艺术品”模型创建视图集

您需要为“Artwork”模型创建一个视图集。此视图集将处理与“Artwork”相关的操作,例如创建、更新和删除。您可以使用Django REST框架模块中的ModelViewSet来实现此目的:

class ArtworkViewSet(viewsets.ModelViewSet):
    queryset = Artwork.objects.all()
    serializer_class = ArtworkSerializer

第2步:修改序列化程序以直接接受'artist_name'

修改序列化程序以直接接受'artist_name'。此调整将允许您在单个POST请求中包含艺术家的姓名沿着以及其他艺术品详细信息。你可以这样做:
类ArtworkSerializer(serializers.ModelSerializer):artist_name = serializers.CharField(write_only=True)#添加此字段

class Meta:
    model = Artwork
    fields = (
        "title",
        "date_created_month",
        "date_created_year",
        "comments",
        "width",
        "height",
        "artist_name",  # Include artist_name
    )

def create(self, validated_data):
    # Extract the 'artist_name' from the validated data, removing it from the dictionary.
    artist_name = validated_data.pop("artist_name")
    
    # Use the 'get_or_create' method on the Artist model to retrieve an existing artist
    # with the provided name or create a new one if it doesn't exist.
    # 'created' is a boolean flag that indicates whether the artist was created or not.
    artist, created = Artist.objects.get_or_create(artist_name=artist_name)
    
    # Create a new instance of the Artwork model, associating it with the 'artist' object
    # and passing the remaining 'validated_data' as keyword arguments.
    artwork = Artwork.objects.create(artist=artist, **validated_data)
    
    # Return the newly created artwork instance.
    return artwork

通过以下步骤,您将能够发送一个POST请求,同时创建一个新的艺术品,并将其与相应的艺术家相关联。如果有问题请告诉我。

相关问题