DRF+PostgreSQL下无外键关联Django模型实现分类字段表单可编辑
方案1:保留外键关联,仅调整序列化器实现分类名读写
该方案不需要修改数据库表结构,保持原有的关联关系,仅调整序列化器逻辑即可实现接口返回分类名称、同时支持前端直接传入分类名称完成新增/编辑:
- 首先给
Category模型的category_name字段添加唯一约束,避免分类名重复导致匹配失败:
class Category(models.Model): category_name = models.CharField(max_length=255, choices=CATEGORIES, unique=True)
- 修改
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表存储分类值,实现起来更简单:
- 修改模型代码如下:
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)
- 序列化器不需要做任何修改,默认就会返回分类字符串值,前端直接传入分类名称即可完成读写,完全不需要处理ID。
额外代码修正建议
你现有代码里存在2处不符合规范的问题可以同步调整:
EditBookAPI视图中,更新成功的状态码应该用HTTP_200_OK而不是HTTP_201_CREATED(201是新增资源专用状态码)EditBookAPI视图中,校验失败的返回状态码应该用HTTP_400_BAD_REQUEST而不是HTTP_304_NOT_MODIFIED(304是缓存未修改专用状态码)
内容的提问来源于stack exchange,提问作者CoderS
相关产品推荐
相关产品推荐

