Django FlatPage代理模型新增字段报错及无数据损失改造方案
报错原因
Django 代理模型(Proxy Model)的设计定位就是仅修改父模型的业务逻辑、不新增数据库字段,只要设置了proxy = True的模型就不能自定义新字段,你给代理模型MyFlatPage添加published字段的操作违反了这个规则,所以触发models.E017系统校验错误。
无数据丢失改造方案
下面两种方案都不会改动原有FlatPage表的存量数据,可以按需选择:
方案1:改用多表继承(改动最小)
删除代理标记改用多表继承后,Django会自动生成MyFlatPage和FlatPage的一对一关联,原有FlatPage的所有字段都可以直接在MyFlatPage上调用,扩展字段单独存在新表中:
- 修改
models.py的MyFlatPage定义:
from django.contrib.flatpages.models import FlatPage from django.db import models, Q from django.utils import timezone class FlatPageManager(models.Manager): def search(self, query=None): qs = self.get_queryset().filter(published__lte=timezone.now()) if query is not None: or_lookup = (Q(title__icontains=query) | Q(content__icontains=query) ) qs = qs.filter(or_lookup).distinct() return qs class MyFlatPage(FlatPage): class Meta: verbose_name = "自定义静态页面" # 删除proxy = True即可开启多表继承 published = models.DateTimeField(verbose_name="发布时间") objects = FlatPageManager()
- 执行
python manage.py makemigrations,当Django提示你为存量记录设置published默认值时,选择自动填充timezone.now或者自定义默认值即可。 - 执行
python manage.py migrate完成迁移,所有原有FlatPage的数据完全不受影响。
方案2:单独建扩展关联表(侵入性最低)
如果你不想改动原有代理模型的逻辑,也可以单独建一张扩展表和FlatPage一对一绑定:
class FlatPageExtend(models.Model): page = models.OneToOneField(FlatPage, on_delete=models.CASCADE, related_name="extend_info") published = models.DateTimeField(verbose_name="发布时间")
后续需要判断发布时间时,直接通过页面实例.extend_info.published访问对应字段即可,原有所有逻辑都不需要修改。
两种方案都可以在查询时加上
filter(published__lte=timezone.now())条件,直接实现仅展示到了发布时间的页面的需求。
内容的提问来源于stack exchange,提问作者HBMCS
相关产品推荐
相关产品推荐

