跳转到主要内容

一个可重用的Django应用程序,实现了实体-属性-值数据模型。

项目描述

EAV-Django是一个可重用的Django应用程序,提供了实体-属性-值数据模型的实现。

实体-属性-值模型(EAV),也称为对象-属性-值模型和开放模式,用于描述一个事物(一个“实体”或“对象”)时,可能可以使用的属性(属性、参数)数量非常大,但实际上应用到特定实体上的属性数量相对较少的情况。

(有关更多详细信息,请参阅维基百科文章。)

EAV-Django与传统的RDBMS(在SQLite和MySQL上进行了测试)兼容良好。

优先级

该应用程序源于一个在线商店项目,因此它非常实用,而不仅仅是一个学术练习。主要优先事项包括

  1. 数据灵活性,

  2. 查询效率,以及

  3. 最大可维护性,无需编辑代码。

当然,这涉及到权衡,目标是在一般情况下找到最无害的组合。

功能

所有提供的模型都是抽象的,即EAV-Django不会在其自己的表中存储任何信息。相反,它为您自己的模型提供了一个基础,这些模型将具有开箱即用的EAV支持。

EAV API包括

  • 创建/更新/访问:模型实例为“真实”字段和EAV属性提供了标准的API。然而,这种抽象不会妨碍您,它提供了处理底层内容的手段。

  • 查询:BaseEntityManager在filter()exclude()中包含了查询“真实”和EAV属性的统一方法。

  • 可自定义的属性架构

  • 管理界面:所有动态属性都可以在Django管理界面中轻松表示和修改(使用eav.admin.BaseEntityAdmin)。架构可以单独编辑,就像普通的Django模型对象一样。

  • 分面搜索:分面搜索是在线商店、目录等的重要功能。基本上,您需要一个表单来表示模型属性的某个子集,具有适当的控件和选项,以便用户可以选择某些属性的期望值,提交表单并获取匹配项的列表。在一般情况下,django-filter会做到这一点,但不会与EAV一起工作,因此EAV-Django为此提供了一套完整的工具。

示例

让我们定义一个EAV友好的模型,创建一个EAV属性,看看它的行为。我所说的“EAV属性”是指那些作为独立对象存储在数据库中,但以类似于实体表中的列的方式访问和搜索的属性。

from django.db import models
from eav.models import BaseEntity, BaseSchema, BaseAttribute

class Fruit(BaseEntity):
    title = models.CharField(max_length=50)

class Schema(BaseSchema):
    pass

class Attr(BaseAttribute):
    schema = models.ForeignKey(Schema, related_name='attrs')

# in Python shell:

# define attribute named "colour"
>>> colour = Schema.objects.create(
...     title = 'Colour',
...     name = 'colour',               # omit to populate/slugify from title
...     datatype = Schema.TYPE_TEXT
... )

# create an entity
>>> e = Fruit.objects.create(title='Apple', colour='green')

# define "real" and EAV attributes the same way
>>> e.title
'Apple'
>>> e.colour
'green'

>>> e.save()    # deals with EAV attributes automatically

# list EAV attributes as Attr instances
>>> e.attrs.all()
[<Attr: Apple: Colour "green">]

# search by an EAV attribute as if it was an ordinary field
>>> Fruit.objects.filter(colour='yellow')
[<Fruit: Apple>]

# all compound lookups are supported
>>> Fruit.objects.filter(colour__contains='yell')
[<Fruit: Apple>]

请注意,我们可以像访问、修改和查询真实实体字段一样访问、修改和查询颜色,但与此同时,其名称、类型甚至存在都是由架构实例完全定义的。架构对象可以理解为类,与之相关的Attr对象是其实例。换句话说,架构对象就像CharField、IntegerField等,只是在数据级别定义,而不是在Python中硬编码。并且它们可以为任何实体“实例化”(除非您放置了自定义约束,这些约束超出了EAV-Django的责任范围)。

属性的名称是在相关的架构中定义的。这可能会引起担心,一旦名称更改,代码就会中断。实际上并非如此,因为名称仅直接用于手动查找。在其他所有情况下,查找都是不使用硬编码的名称构建的,EAV对象是通过主键相互关联的,而不是通过名称。名称存在于表单中,但表单是依赖于当前元数据状态生成的,因此您可以安全地重命名架构。您可以从管理界面中破坏的是类型。如果您更改架构的数据类型,所有属性都将保持不变,但将使用另一个列来存储它们的值。当您恢复数据类型时,先前存储的值再次可见。

您可以在源代码中找到更多示例:请参阅“example/”目录和测试。

数据类型

由元数据驱动的结构扩展了灵活性,但同时也涉及一些权衡。其中之一是JOIN数量的增加(因此查询速度变慢)。另一个是数据类型较少。从理论上讲,我们可以支持存储中所有可用的数据类型,但在实践中,这意味着为每个属性创建许多列,而只有少数列被使用——这正是我们通过使用EAV试图避免的。这就是为什么EAV-Django仅支持一些基本类型(尽管如果需要,您可以扩展此列表)。

  • Schema.TYPE_TEXT,一个TextField;

  • Schema.TYPE_FLOAT,一个FloatField;

  • Schema.TYPE_DATE,一个DateField;

  • Schema.TYPE_BOOL,一个NullBooleanField;

  • Schema.TYPE_MANY用于多个选择(即值的列表)。

所有EAV属性都存储在一个表中,表中包含实体和模式的唯一引用组合。实体通过contenttypes框架引用,模式通过外键引用。换句话说,只有一个属性可以与特定的实体和模式相关联。模式是属性的定义。模式定义了名称、标题、数据类型以及其他适用于该模式任何属性的属性。当我们访问或搜索EAV属性时,EAV机制总是使用模式作为属性元数据。为什么?因为属性名称存储在相关的模式中,而值存储在属性表的某一列中。除非我们查看元数据,否则我们不知道它是哪一列。

在上面的示例中,我们只玩了一个文本属性。除了TYPE_MANY外,所有其他类型的行为完全相同。多对多是一个特殊情况,因为它涉及一个额外的选择模型。EAV-Django提供了一个抽象模型,但需要您定义一个具体的模型(例如Choice),并从属性模型中指向它(即在属性模型中放置名为“choice”的外键)。选择模型也将指向模式。请检查测试以获取示例。

文档

目前没有教程。尽管如此,代码本身相当有文档,整个逻辑相当简单。

请参见

  • 测试,它们包含模型定义和查询的好例子;

  • 捆绑的示例(“杂货店”,包含固定数据);

  • 讨论组

依赖项

理论上,支持Python 2.5到2.7;然而,该库仅针对Python 2.6和2.7进行了测试。

您还需要Django 1.1或更高版本以及一些小库:django_autoslug和django_view_shortcuts。这通常由安装程序自动处理。

替代品,分支

django-eav

这是eav-django的一个分支,变成了一个新的应用程序。看起来没有活跃开发,但在某些方面可能更好。eav-django的原始作者鼓励用户也尝试这个应用程序。

作者

此应用程序最初由Andrey Mikhaylenko创建。有关完整的贡献者列表,请参阅AUTHORS文件。

请随时提交问题或补丁。

许可

EAV-Django是免费软件;您可以在自由软件基金会的GNU较小通用公共许可证的条款下重新分配它和/或修改它;许可证的第3版,或(根据您的选择)任何较新版本。

EAV-Django的发布是为了希望它将是有用的,但没有任何保证;甚至没有关于其适销性或适用于特定目的的暗示保证。有关详细信息,请参阅GNU较小通用公共许可证。

您应已收到GNU较小通用公共许可证的副本;请参阅COPYING.LESSER文件。如果没有,请参阅GNU许可证

项目详细信息


下载文件

下载适用于您平台的文件。如果您不确定要选择哪个,请了解更多关于安装包的信息。

源分布

eav-django-1.4.7.tar.gz (27.9 kB 查看哈希值)

上传时间 源代码

支持者