簡體   English   中英

如何用react創建和處理django中的相關字段?

[英]How to create and handle a related field in django with react?

我創建了 2 個模型 - 標簽和初創公司。 Startups 有一個 tags 字段,與 Tag 是多對多關系。

模型.py 文件 -

從 django.db 導入模型 從 django_extensions.db.fields 導入 AutoSlugField 從 django.db.models 導入 CharField、TextField、DateField、EmailField、ManyToManyField

class Tag(models.Model):

    name = CharField(max_length=31, unique=True, default="tag-django")
    slug = AutoSlugField(max_length=31, unique=True, populate_from=["name"])

    def __str__(self):
        return self.name


class Startup(models.Model):

    name = CharField(max_length=31, db_index=True)
    slug = AutoSlugField(max_length=31, unique=True, populate_from=["name"])
    description = TextField()
    date_founded = DateField(auto_now_add=True)
    contact = EmailField()
    tags = ManyToManyField(Tag, related_name="tags")

    class Meta:
        get_latest_by = ["date_founded"]

    def __str__(self):
        return self.name

我的 serializers.py 文件 -

from rest_framework.serializers import HyperlinkedModelSerializer, PrimaryKeyRelatedField, ModelSerializer
from .models import Startup, Tag


class TagSerializer(HyperlinkedModelSerializer):
    class Meta:
        model = Tag
        fields = "__all__"
        extra_kwargs = {
            "url": {
                "lookup_field": "slug",
                "view_name": "tag-api-detail"
            }
        }


class StartupSerializer(HyperlinkedModelSerializer):
    tags = TagSerializer(many=True, read_only=True)

    class Meta:
        model = Startup
        fields = "__all__"
        extra_kwargs = {
            "url": {
                "lookup_field": "slug",
                "view_name": "startup-api-detail"
            }
        }

我的 viewsets.py 文件 -

from rest_framework.response import Response
from rest_framework.viewsets import ModelViewSet
from .serializers import TagSerializer, StartupSerializer
from .models import Tag, Startup
from rest_framework.decorators import action
from rest_framework.status import HTTP_400_BAD_REQUEST, HTTP_200_OK, HTTP_204_NO_CONTENT
from django.shortcuts import get_object_or_404


class TagViewSet(ModelViewSet):

    queryset = Tag.objects.all()
    serializer_class = TagSerializer
    lookup_field = "slug"


class StartupViewSet(ModelViewSet):

    serializer_class = StartupSerializer
    queryset = Startup.objects.all()
    lookup_field = "slug"


    @action(detail=True, methods=["HEAD", "GET", "POST"], url_path="tags")
    def tags(self, request, slug=None):
        
        startup = self.get_object()
        print(startup)
        if request.method in ("HEAD", "GET"):
            s_tag = TagSerializer(
                startup.tags,
                many=True,
                context={"request": request}
            )
            return Response(s_tag.data)

        tag_slug = request.data.get("slug")
        if not tag_slug:
            return Response(
                "Slug of Tag must be specified",
                status=HTTP_400_BAD_REQUEST
            )
        tag = get_object_or_404(Tag, slug__iexact=tag_slug)
        startup.tags.add(tag)
        return Response(HTTP_204_NO_CONTENT)

我可以通過我的 django 管理員創建初創公司並關聯標簽。 我的 django 管理員中有一個包含所有已創建標簽的下拉列表,我可以從中將標簽與初創公司相關聯。

我不明白在反應中創建啟動時如何將標簽與啟動相關聯。 我嘗試以這種形式發布數據 -

{
    "name": "Test Startup 1",
    "description": "First Desc",
    "contact": "first@gmail.com",
    "tags": [
        {
            "url": "http://127.0.0.1:8000/api/v1/tag/first-tag/",
            "name": "First Tag",
            "slug": "first-tag"
        }
    ]
}

我無法獲得與啟動相關的標簽。

如何處理相關字段?

你有多種選擇。

如果你想執行關聯(意味着標簽和啟動在發出請求之前已經存在,有點像 django-admin 發生的事情),你可以創建一個新的序列化器,它有一個不同的標簽字段,接受 ids 而不是嵌套序列化器。

如果你想有嵌套的創建/版本,你可以從這里簽出 WritableNestedSerializer 。 因為文檔說它不處理此類用例,因為根據您的業務邏輯,它們可能有多種執行此操作的方法,但請在此處提供自己執行此操作的方法

另一種方法是使用嵌套資源(例如嵌套路由器)的路由,因此當您在 /startup/1/tags/ 中發布標簽時,您會自動創建並關聯您的標簽,就像您所做的那樣。

現在,關於您的端點,您需要獲取請求的數據並將其傳遞給標簽序列化程序。 然后,此序列化程序將驗證您的數據,如果有效,您可以執行標簽創建。

為此,您可以執行以下操作:

tag_data = request.data
tag_serializer = TagSerializer(data=request.data)
tag_serializer.is_valid()
tag = tag_serializer.save()
tag.startup_set.add(startup)

添加關系必須分兩步完成。 您應該使用事務來確保它被正確創建。 此外,不要在您的視圖中添加此邏輯,您應該覆蓋 TagSerializer/StartupSerializer create方法來執行此操作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM