You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

DRF+PostgreSQL下无外键关联Django模型实现分类字段表单可编辑

方案1:保留外键关联,仅调整序列化器实现分类名读写

该方案不需要修改数据库表结构,保持原有的关联关系,仅调整序列化器逻辑即可实现接口返回分类名称、同时支持前端直接传入分类名称完成新增/编辑:

  1. 首先给Category模型的category_name字段添加唯一约束,避免分类名重复导致匹配失败:
class Category(models.Model):
   category_name = models.CharField(max_length=255, choices=CATEGORIES, unique=True)
  1. 修改BookSerializer,使用SlugRelatedField指定用category_name作为关联字段的读写值:
class BookSerializer(serializers.ModelSerializer):
    category = serializers.SlugRelatedField(
        slug_field='category_name',
        queryset=Category.objects.all(),
        error_messages={"does_not_exist": "输入的分类名称不存在"}
    )
    class Meta:
        model = Book
        fields = '__all__'

调整后接口返回的category字段会直接返回Fiction/Non-Fiction这类字符串值,前端提交新增/编辑请求时也直接传分类名称字符串即可,DRF会自动匹配对应的分类关联。

方案2:移除外键,直接在Book模型存储分类值(更适合固定分类场景)

如果你的分类枚举是固定的,不需要动态管理分类,完全可以移除Category模型和外键关联,直接在Book表存储分类值,实现起来更简单:

  1. 修改模型代码如下:
CATEGORIES = [
    ('Fiction', 'Fiction'),
    ('Non-Fiction', 'Non-Fiction')
]

class Book(models.Model):
   title = models.CharField(max_length=255)
   author = models.CharField(max_length=255)
   pages = models.IntegerField() # 修正原拼写错误:原IntergerField为笔误,且IntegerField不需要max_length参数
   category = models.CharField(max_length=255, choices=CATEGORIES)
  1. 序列化器不需要做任何修改,默认就会返回分类字符串值,前端直接传入分类名称即可完成读写,完全不需要处理ID。

额外代码修正建议

你现有代码里存在2处不符合规范的问题可以同步调整:

  • EditBookAPI视图中,更新成功的状态码应该用HTTP_200_OK而不是HTTP_201_CREATED(201是新增资源专用状态码)
  • EditBookAPI视图中,校验失败的返回状态码应该用HTTP_400_BAD_REQUEST而不是HTTP_304_NOT_MODIFIED(304是缓存未修改专用状态码)

内容的提问来源于stack exchange,提问作者CoderS

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 19:27:05