前言
我正在实现一个基于 Django 框架(目前稳定的 1.4.3)的“收藏管理系统” 。
我正在设计 ORM 的良好关系性质来强制一些讨厌的“OO 方面”,我试图提取一个最小的例子。(免责声明:完整的功能描述将是另一个冗长而无聊的阅读,所以我不会制作它,除非它被证明是设计讨论)。
提取的例子
假设我们使用 Django 模型松散地模拟 OO。我们有发布模型(=一个类),它可以由不同的属性(=类的数据成员)组成。然后可以为相同的Release实例化不同的实例(= 对象) 。每个Instance可以为其相关Release中存在的所有/部分/无属性存储一个值。
这将为我们提供以下模型:
#An attribute is a name, that can be given a value at instance level.
class Attribute(models.Model):
name = models.CharField(max_length=60)
#A release can be compared to a class in OO :
# it's a data structure description (the attributes' list).
class Release(models.Model):
name = models.CharField(max_length=60)
#A release is caracterized by a list of attributes
# the same attribute can be present in several releases
attributes = models.ManyToManyField(Attribute, blank=True, null=True)
#An instance entry can be compared to an object in OO :
# it instantiates a release
# it can hold its own value for each of the attributes in this release.
#Nb : Attributes are all optional.
class Instance(models.Model):
#the instantiated release
release = models.ForeignKey(Release)
#Store the actual attribute-value pairs for the different instances.
class InstanceAttribute(models.Model):
instance = models.ForeignKey(Instance)
attribute = models.ForeignKey(Attribute)
value = models.CharField(max_length=60)
问题
用这种方法使用强大的 Django 管理员会很棒。
一切都是开箱即用的,可以添加Releases并使用Attributes组合它们。
实例添加视图变得越来越复杂。(相关的Release id 可以通过 GET 形式的 url 转发:instance/add/?release=x)。当这个视图被加载时,我们需要提出一个InstanceAttribute的 InlineFormset :
- 与组成相关版本的属性数量匹配的表单数量
- 对于这些表单中的每一个,应将Attribute字段初始化为 Release 的Attribute,并且它的查询集被限制为仅显示此Attribute。
我们可以通过覆盖ModelAdmin.get_formsets()
返回一个inlineformset_factory
并将额外参数设置为所需数字的方法来解决#1。
仔细查看add_view 源代码,我找不到实现#2 的好方法...