对于一些项目,我们使用EAV的非常简单的变体。我们不需要过滤和查询数据集。我们查看了django-eav和eav-django,它们不适合我们的项目,主要是因为我们不想使用GenericForeignKey。
我们现在看到的基本设置是这个(此问题不需要的字段可以专注于手头的问题):
# In the EAV app
class Attribute(models.Model):
name = models.CharField(max-Length=100, unique=True)
class BaseValue(models.Model):
value = models.TextField(null=False, blank=True)
attribute = models.ForeignKey(Attribute)
class Meta:
abstract = True
在使用属性的应用中,我们可以这样做:
# Locations with attributes
class Location(models.Model):
name = models.CharField(max_length=100, unique=True)
class LocationValue(BaseValue):
object = models.ForeignKey(Location)
这很好地实现了目的,但如果我们能够生成LocationValue类,那就太好了。所以我们想做什么,但无法开始工作是这样的:
选项1,装饰者
# Locations with attributes
@has_attrs
class Location(models.Model):
name = models.CharField(max-Length=100, unique=True)
# The `has_attrs` decorator should generate the LocationValue class
选项2,发电机/工厂
# Locations with attributes
class Location(models.Model):
name = models.CharField(max-Length=100, unique=True)
LocationValue = value_class_for(Location)
# The function `value_class_for` should generate the LocationValue class
重要的是,LocationValue类是与Location相同的应用程序的一部分。这样做的原因是我们希望数据库模型即使对于那些直接查看它的人来说也是可以理解的(不是通过Django抽象层)。
此外,将有多个应用程序使用此功能,因此最终我们可能会有一个位置应用程序(Location,LocationValue),一个Monument应用程序(Monument,MonumentValue)等等。
我的问题:
谢谢你分享你的知识!
答案 0 :(得分:1)
实现此目的的pythonic方法是使用metaclass,这是在第一次创建类时调用的。因此,您可以控制类创建并创建其他类(将其视为某种类型的"工厂"用于类)。 Django也充分利用了这个"魔术"在设置模型类时。您可能希望查看创建Model
类的Django's ModelBase
metaclass(此外,您可能需要将其子类化以集成所需的功能)。