如何处理外键字段
问题:CreateView 中包含 ForeignKey,想要传递一个外键例如 author_id,结果报错
代码模拟
models.py
from django.contrib.auth.models import User
from django.db import models
class Article(models.Model):
    title = models.CharField(verbose_name="标题", max_length=100)
    author = models.ForeignKey(User, verbose_name="作者", on_delete=models.CASCADE)
    class Meta:
        verbose_name = '文章'
        verbose_name_plural = verbose_name
from ninja import ModelSchema
class ArticleIn(ModelSchema):
    class Meta:
        model = Article
        fields = ['title', 'author_id']
class ArticleOut(ModelSchema):
    class Meta:
        model = Article
        fields = '__all__'
from ninja_crud import views, viewsets
from ninja import Router
from .schema import ArticleIn, ArticleOut
route = Router()
class ArticleViewSet(viewsets.APIViewSet):
    router = route
    model = Article
    default_request_body = ArticleIn
    default_response_body = ArticleOut
    create_view = views.CreateView()
    read_view = views.ReadView()
    update_view = views.UpdateView()
    delete_view = views.DeleteView()
发出网络请求
Request body
{
  "title": "string",
  "author_id": 12
}
Responses
Traceback (most recent call last):
  File "/Users/yiqun/Venv/repgpt_be/lib/python3.10/site-packages/ninja/operation.py", line 107, in run
    result = self.view_func(request, **values)
  File "/Users/yiqun/Venv/repgpt_be/lib/python3.10/site-packages/ninja_crud/views/api_view.py", line 284, in wrapped_view_function
    return self.view_function(
  File "/Users/yiqun/Venv/repgpt_be/lib/python3.10/site-packages/ninja_crud/views/create_view.py", line 198, in default_view_function
    setattr(instance, field, value)
  File "/Users/yiqun/Venv/repgpt_be/lib/python3.10/site-packages/django/db/models/fields/related_descriptors.py", line 215, in __set__
    raise ValueError(
ValueError: Cannot assign "12": "Article.author" must be a "User" instance.
问题分析
通过 Model 分析,"Article.author" 必须为一个 "User" 实例,而前端只传了一个 int 的数值。
并且前端是不太可能直接给你传递这个值的,因此, 我们需要自定义 CreateView 的 request_body, 使它允许整数的传入。
schema.py
class NewArticleIn(Schema):
    author_id: int
    title: str
from ninja_crud import views, viewsets
from ninja import Router
from .schema import ArticleIn, ArticleOut
route = Router()
class ArticleViewSet(viewsets.APIViewSet):
    router = route
    model = Article
    default_request_body = ArticleIn
    default_response_body = ArticleOut
    create_view = views.CreateView(request_body=NewArticleIn)
    read_view = views.ReadView()
    update_view = views.UpdateView()
    delete_view = views.DeleteView()
问题完。
如有疑问,请留言,或者页面右上角加群讨论。
评论
本文总阅读量次
