我有一个用例,我希望在Django应用程序中捕获用户的各种类型的提醒(由业务逻辑自动生成)。在所有提醒中,属性都相同(即owner
,creator
,creation_time
,status
,completion_time
)并且它们具有相同的界面(即{ {1}},render_message()
)。但是,有许多类型的提醒,每个提醒都应该有这些常用功能的实现细节。
由于模型属性永远不会改变,似乎只有单个Django模型才有意义,但后来我质疑从模型实例到is_valid()
等函数的特定实现的最佳方法。
我目前正考虑在名为render_message()
的{{1}}模型上设置ChoiceField
,该模型将映射到各种提醒类型类,然后在{{1}内设置辅助函数将基于Reminder
实例化相应的提醒类型类,并将其调用为type
等功能。
我错过了更好的方法吗?不确定这个模式是考虑什么,或者在哪里寻找具有与同一接口的各种实现相关联的单个Django模型的类似示例。
答案 0 :(得分:2)
如果您想使用模型存储提醒,Django proxy models可以很好地满足您的要求。
在高层次上,Django有三种继承:
未创建基类表,并且所有继承的模型都获取基类的所有字段
Django支持的第二种模型继承是每种类型 层次结构中的模型本身就是一个模型。每个型号 对应于自己的数据库表,可以查询和创建 个别。继承关系引入了之间的联系 儿童模型及其每个父母(通过自动创建 OneToOneField)。
使用多表继承时,会创建一个新的数据库表 对于模型的每个子类。这通常是理想的行为, 因为子类需要一个地方来存储任何其他数据字段 基类上没有的。但是,有时你只是 想要改变模型的Python行为 - 也许是为了改变 默认管理器,或添加新方法。
这就是代理模型继承的用途:为。创建代理 原始模型。您可以创建,删除和更新实例 代理模型和所有数据将被保存,就像您使用的一样 原始(非代理)模型。不同之处在于你可以改变 诸如默认模型排序或默认管理器之类的东西 代理,无需改变原件。
示例:
from django.db import models
class Person(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
class MyPerson(Person):
class Meta:
proxy = True
def do_something(self):
# ...
pass
class AlienPerson(Person):
class Meta:
proxy = True
def do_something(self):
pass
很酷的是,它可以帮助您创建不同的管理界面,即使对象存储在同一个表中:) reference
答案 1 :(得分:0)
您可以将逻辑的自定义部分存储到数据库中。
class Reminder:
message_template = forms.TextField()
def render_message(self):
render_message_dict = self.get_render_message_dict()
return self.message_template.format(**render_message_dict)
def get_render_message_dict(self):
return {
'project_name': self.project_name,
'due_for_days': (date.today() - self.due_date).days,
'updated_for_days': (date.today() - self.last_updated.date()).days,
}
所以你设置:
reminder_a.message_template = '{project_name} is over due by {due_for_days} days'
reminder_b.message_template = '{project_name} hasn't been updated in {updated_for_days} days'
如果您有一组给定的消息模板,您也可以使用选择字段:
class Reminder:
MESSAGE_TEMPLATE_CHOICES = [
(1, _("{project_name} is over due by {due_for_days} days")),
(2, _("{project_name} hasn't been updated in {updated_for_days} days")),
]
message_template = forms.PositiveSmallIntegerField(
choices=MESSAGE_TEMPLATE_CHOICES)
def render_message(self):
render_message_dict = self.get_render_message_dict()
return self.message_template.format(**render_message_dict)
def get_render_message_dict(self):
return {
'project_name': self.project_name,
'due_for_days': (date.today() - self.due_date).days,
'updated_for_days': (date.today() - self.last_updated.date()).days,
}
这也可以将消息模板标记为可翻译。