Django开发:如何在ORM管理视图中自动更新模型字段选择值
有两个表,一个是记录网站信息的站点表,结构如下:
CREATE TABLE `site` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(32) NOT NULL, `url` varchar(128) NOT NULL, `mtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `ctime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `name` (`name`), UNIQUE KEY `url` (`url`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='配置网站表'
另一个是用户表记录user信息,结构如下:
CREATE TABLE `user` ( `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, `site_id` bigint(20) unsigned NOT NULL COMMENT 'site.id', `user_id` varchar(32) NOT NULL, `name` varchar(128) NOT NULL, `description` text NOT NULL, `mtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `ctime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE KEY `user_id` (`user_id`), UNIQUE KEY `name` (`name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='配置用户表'
如上表结构所示,user表中site_id列(简写为user.site_id)的值实际上仅限于id字段的值(缩写为 site.id)在站点表中,实现此目的的错误一种方法是在 user.site_id 和 user.id 两列上指定外键约束。但是,如果由于某种原因无法指定外键约束,则可以跳过用户。 site_id 上的可选字段限制了用户values.site_id 的范围。模型中的代码如下:
# coding=utf-8 from __future__ import unicode_literals from django.db import models class Site(models.Model): id = models.PositiveIntegerField(primary_key=True, blank=True) name = models.CharField(max_length=32, verbose_name=u'网站名称') url = models.CharField(max_length=255, verbose_name=u'网址') mtime = models.DateTimeField(auto_now=True, verbose_name=u'修改时间') ctime = models.DateTimeField(auto_now=True, verbose_name=u'创建时间') class Meta: db_table = 'site' def get_site_choices(): rcs = Site.objects.all() choices = [(x.id, x.name) for x in rcs] return choices class User(models.Model): id = models.PositiveIntegerField(primary_key=True, blank=True, verbose_name=u'自增id(留空自动生成)') site_id = models.PositiveIntegerField(verbose_name=u'网站', choices=get_site_choices()) user_id = models.CharField(max_length=32, verbose_name=u'用户id') name = models.CharField(max_length=128, verbose_name=u'用户名') description = models.TextField(verbose_name=u'备注') mtime = models.DateTimeField(auto_now=True, verbose_name=u'修改时间') ctime = models.DateTimeField(auto_now=True, verbose_name=u'创建时间') class Meta: db_table = 'user'
在Django后端创建两个ORM管理视图。考虑站点表中已经录入了以下两条数据:
那么对用户表进行ADD USER操作时,site_id的可选值为豆瓣电影和豆瓣阅读
添加了豆瓣读书的用户账号后,用户表如下:
现在看起来一切正常,但是如果你在站点表中添加一个网站,比如豆瓣音乐,那么站点表就会更新为三个记录:豆瓣读书、豆瓣电影、豆瓣音乐。但是,如果你想在记录当前用户表中再添加一个,site_id下拉列表中仍然只有两个值:豆瓣读书和豆瓣电影:
这是因为site_id = models .PositiveIntegerField(verbose_name=u'website ', Choices=get_site_choices() in class User)) 该语句只会在服务启动时类初始化时执行一次。此时会执行get_site_choices函数,此时的site.id值会作为user.site_id选项被移除,并在site表中添加一个新的值。或者减少记录后,由于User类中的初始化语句将不再被执行,因此会出现两个值不一致的问题。在这种情况下,如果您想更新 user.site_id 值,只需重新启动服务即可。 。
但是,每次更新站点表都必须重新启动服务,这是绝对不能接受的。解决方案是每次在类的 __init__ 方法中重新查询 site 表中的正确值,然后重新从 user.site_id 字段中将值分配给可选字段。获取user.site_id字段是通过self.get_field函数实现的。代码如下:
class User(models.Model): id = models.PositiveIntegerField(primary_key=True, blank=True, verbose_name=u'自增id(留空自动生成)') site_id = models.PositiveIntegerField(verbose_name=u'网站', choices=get_site_choices()) user_id = models.CharField(max_length=32, verbose_name=u'用户id') name = models.CharField(max_length=128, verbose_name=u'用户名') description = models.TextField(verbose_name=u'备注') mtime = models.DateTimeField(auto_now=True, verbose_name=u'修改时间') ctime = models.DateTimeField(auto_now=True, verbose_name=u'创建时间') def __init__(self, *args, **kargs): super(User, self).__init__(*args, **kargs) self._meta.get_field('site_id').choices = get_site_choices() class Meta: db_table = 'user'
get_field函数的说明请参见Django文档(https://docs.djangoproject.com/en/2.0/ref/models/meta/#django.db.models.options) .Options. get_field):
Options.
get_field
(field_name)[源]列更改名称名称给定field_ name 可以是模型中的列名称、抽象模型或继承中的列,或引用该模型的其他模型中定义的字段。在最后一种情况下, Field_name
将是 Related_name
由用户定义或 django 它集写入的名称 ❀❀♽ 不下注带有名称的 Field 。
如果找不到给定名称的列,将引发 FieldDoesNotExist
异常。
这样,在启动每个用户实例时将检索最新的 site.id 字段值。 ,分配给 user.site_id 的可选属性。这样做的缺点是每次初始化都会调用 get_site_choice 。s 并重新分配 user.site_id.choices。如果页面加载的事件较多或者站点表记录较多,就会出现性能问题,所以只适合后台数据量较小的情况,自动更新ADD USER上的最新选择页面无需重新启动服务:
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。