[英]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.