python-3.x - Django:用于管理 db_table 的抽象基类
问题描述
我正在尝试构建我的第二个 django(和 python,我的第一个项目是 django 教程:))项目。因为这应该是真实的,所以在我进入项目的实质之前,我想彻底并建立一个良好的代码结构。
我有几个像这样的简单模型
class Task(models.Model):
name = models.CharField(max_length=50, null=False)
description = models.CharField(max_length=255, null=True)
dueDate = models.DateTimeField()
我正在使用 PostgreSQL,并通过像这样定义每个模型的元类来设置我的模型以使用应用程序标签作为数据库模式
class Meta:
managed = True
db_table = 'app_name\".\"modelname'
这很好用。但我必须为每个模型都这样做。
不过我想保持干燥。所以我现在要做的是拥有一个自动执行此操作的抽象基类,因此我尝试了以下操作:
class SchemaModel(models.Model):
class Meta():
abstract = True
managed = True
db_table = AppConfig.label+'\".\"'+self.__class__.lower()+'s'
(然后当然继承了基类,我将嵌套Meta
类从普通模型中取出)
这不起作用,因为self
在Meta
在查阅文档后,我尝试了这个:
class SchemaModel(models.Model):
class Meta():
abstract = True
managed = True
db_table = '%(app_label)\".\"%(class)s'
这导致db_table
每个模型的属性是"%(app_label)\".\"%(class)s"
>>> t = Task()
>>> t._meta.db_table
'%(app_label)"."%(class)s'
>>>
我在互联网上没有找到类似的东西。我是在尝试做一些不可能或“禁止”的事情吗?
解决方案
解决方案如 elyas answer 所示db_table
,models.py
通过遍历所有__subclasses__()
for model in SchemaModel.__subclasses__():
db_table = '{}s'.format(model._meta.label_lower.replace('.','\".\"'))
model._meta.original_attrs['db_table'] = db_table
model._meta.db_table = db_table
解决方案
我不会说这是禁止的。但我想不出任何方式来声明式地做到这一点。然而,有一种方法可以做到这一点。
首先,根据您现有的尝试:
访问“自我”
db_table = AppConfig.label+'\".\"'+self.__class__.lower()+'s'
加载模型时,永远不会从类中创建实例对象Meta
,因此无需self
引用。但是即使创建了一个实例对象,db_table
也是类对象的一个属性,所以在创建类对象的时候进行求值,是在创建任何实例对象之前,所以这样self
定义类属性时是不能访问的。
编辑:正如你所提到的, app_label 不能通过AppConfig.label
.
字符串格式
db_table = '%(app_label)\".\"%(class)s'
这些占位符仅用于在抽象基类中定义or字段的和属性时非常特殊的情况。related_name
related_query_name
ForeignKey
OneToOneField
一个解法
正如我所说,我想不出任何声明性的方式来实现这一点。例如,尝试使用__qualname__
是行不通的,因为你SchemaModel.Meta
每次都会结束。
但是你可以在你的 models.py 的底部放一个 for 循环,如下所示:
for model in SchemaModel.__subclasses__():
# Name your db_table here
db_table = model._meta.app_label + '\".\"' + model._meta.model_name.lower() + 's'
# Set db_table here
model._meta.original_attrs['db_table'] = db_table
model._meta.db_table = db_table
SchemaModel
可以使用内置方法找到所有的孩子__subclasses__()
。- 该
db_table
属性需要在两个地方更新。首先_meta
,它(部分)是通过从Meta
类中复制属性创建的,其次是存储_meta.original_attrs
原始Meta
属性并在迁移期间由 Django 读取的位置。
替代解决方案
我个人会手动定义db_table
名称,并简单地进行单元测试,检查所有模型是否符合我提出的任何命名约定。我更喜欢这个,所以如果另一个开发人员关注他们从未见过的模型,他们可以根据模型(和抽象基类)中的声明获得完整的图片,并且不要对在其他地方修改它们的操作感到困惑。
推荐阅读
- python - Pygame 强制窗口最小化
- docker - 如何在 Docker Compose 多容器应用程序中使用 GoCQL 连接到 bitnami/cassandra?
- opencv - 如何获得具有自适应阈值的实体形状
- ios - 如何在没有调用者 UUID 的情况下从自定义 UI 结束 CallKit 调用?
- go - 在 VS Code 开发过程中调试 Go 包
- javascript - Firebase 消息 (FCM) - 没有通知权限的应用内消息
- node.js - 使用 Firebase Cloud Functions 创建 Node.js REST API,而不使用 Express?
- django - Django Permission 类被调用两次
- java - Spring boot 2中配置Sql server 2019数据库时出错
- sql - Oracle Sql 在插入语句时向 to_date 添加小时和分钟