将模型与“通用"一起使用建模继承的字段 [英] Using a Model with "general purpose" fields to model inheritance

查看:53
本文介绍了将模型与“通用"一起使用建模继承的字段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前在开玩笑地讲如何使用Django建模.基本情况是,我有一个对象,应作为机箱并提供一些 socket .然后,有许多不同的 modules 负载放置在机箱 socket 上.我想将这些不同的 modules 建模为Django中的不同类,但在数据库层上使用一个通用类,可能涉及一些通用字段.

I am currently kidding around on how to model something using Django. The basic situation is that I have an object that should serve as a chassis and provide some sockets. Then there are loads of different modules that are placed on the sockets of a chassis. I would like to model these different modules as distinct classes in Django, but use a common class on the database layer, possibly involving some generic fields.

所以数据库模型可能看起来像这样:

So the database model might look something like this:

class Module(models.model):
    name = models.CharField(max_length=128)
    # Or is there a better way to annotate a type?
    type = models.CharField(max_length=128) 
    string1 = models.CharField(max_length=128)
    string2 = models.CharField(max_length=128)
    ...
    int1 = models.IntegerField()

# Some kind of engine class that derives from Module
# but does nothing else then "mapping" the generic
# fields to something sensible

class Socket(models.Model):
    is_on = models.ForeignKey(Chassis)
    name = models.CharField(max_length=128)
    type = models.CharField(max_length=128)

class Connection(models.Model):
    chassis = models.ForeignKey(Chassis)
    module = models.ForeignKey(Module)
    via = models.ForeignKey(Socket)

class Chassis(models.Model):
    name = models.CharField(max_length=128)
    modules= models.ManyToManyField(Module, through='Connection')

class Group(models.Model):
    name = models.CharField(max_length=128)

当然,我不想因这种非规范化而破坏我的逻辑.这就是为什么我暗示某种类型的 engine 类应使用Module表,但提供逻辑"获取器和设置器,以将诸如"Horsepower"之类的数据有效地映射到"int1"的原因.

Of course I wouldn't want to spoil my logic with this denormalization. Thats why I hinted for some kind of engine class that should use the Module table, but provide "logical" getters and setters, effectively mapping data like "Horsepower" to "int1".

所以我的问题基本上是:

So my questions are basicly:

  • 我对Django所做的事情合理吗?还是有更好的(可能是内置的)方式来处理此问题?
  • 是否有可能构造正确的类型,该类型自动为<规范> Module.type 字段提供非规范化模型的包装方法?
  • Is what I am doing reasonable with Django? Or is there a better (possibly built in) way to deal with this?
  • Would it be possible to construct the correct type, the one providing the wrapper methods for the denormalized model, depending on the Module.type field automatically?

推荐答案

我对Django所做的事情合理吗?

Is what I am doing reasonable with Django?

一般的想法是可以的,但是非规范化可能会使您的查询不理想.标准解决方案是为每种类型的模块子类 Module .这将创建一个 module 表,以及每个模块类型的表,其中包含特定于类型的内容.当然,这是假设您不会在运行时创建或删除模块类型.

The general idea is okay, but the denormalization may make your queries less than optimal. The standard solution would be to subclass Module for each type of module; this would create a module table plus a table per module type with the type-specific stuff. This, of course, assumes you won't be creating or deleting module types at runtime.

也就是说,您的模型存在一些问题:

That said, there are some issues with your models:

class Module(models.model):
    name = models.CharField(max_length=128)
    # Or is there a better way to annotate a type?
    type = models.CharField(max_length=128) 
    string1 = models.CharField(max_length=128)
    string2 = models.CharField(max_length=128)
    ...
    int1 = models.IntegerField()

通常, type 将被规范化以节省空间:

Normally, type would get normalized to save space:

class ModuleType(models.model):
    name = models.CharField(max_length=128)
    # Any other type-specific parameters.

class Module(models.model):
    name = models.CharField(max_length=128)
    type = models.ForeignKey(ModuleType, related_name="modules")
    string1 = models.CharField(max_length=128)
    string2 = models.CharField(max_length=128)
    ...
    int1 = models.IntegerField()


class Socket(models.Model):
    is_on = models.ForeignKey(Chassis)
    name = models.CharField(max_length=128)
    type = models.CharField(max_length=128)

class Connection(models.Model):
    chassis = models.ForeignKey(Chassis)
    module = models.ForeignKey(Module)
    via = models.ForeignKey(Socket)

class Chassis(models.Model):
    name = models.CharField(max_length=128)
    sockets = m
    modules= models.ManyToManyField(Model, through='Socket')

机箱是一团糟.您没有定义 socket ,而是在可能需要 module 的地方写了 Model ,而 through 应该指的是 Connection (一个 through 模型必须在链接的两端都有 ForeignKey ).但是从您的描述中,我得到的结果要简单得多:

Chassis is a mess. You didn't define sockets, wrote Model where you probably want module, and through should probably refer to Connection (a through model has to have ForeignKeys to both ends of the link). But from your description, I get the far simpler:

class Socket(models.Model):
    chassis = models.ForeignKey(Chassis, related_name="sockets")
    name = models.CharField(max_length=128)
    # Is `type` a ModuleType? If so, use a ForeignKey.
    # If not, create a SocketType model.
    type = models.___
    module = models.ForeignKey(Module, related_name="sockets")

class Chassis(models.Model):
    name = models.CharField(max_length=128)
    sockets = models.IntegerField()
    modules = models.ManyToManyField(Socket)

通过更好地描述您要建模的内容,可以对此进行进一步完善.例如,我不确定您想要的是ManyToMany.您可能需要从机箱的实例中分离机箱的设计(即,给定类型的机箱的所有实例(包括其插槽)通用的东西).将引用该设计,并具有另一个将套接字映射到模块的表.

With a better description of what you're modeling, this can be refined further. For example, I'm not sure a ManyToMany is what you want. You may need to split the design of a chassis (i.e. things common to all instances of a given kind of chassis, including its sockets) from the instances of that chassis (which would reference the design, and have another table mapping sockets to modules).

是否可以根据Module.type字段自动构造正确的类型?

Would it be possible to construct the correct type depending on the Module.type field automatically?

这是Factory设计模式.在Python中,您可以将其实现为构造函数的字典:

That's the Factory design pattern. In Python, you'd implement it as a dictionary of constructors:

class Module(models.model):
    # ...
    CONSTRUCTORS = {}

    @staticmethod
    def register_constructor(type_name, constructor):
        Module.CONSTRUCTORS[type_name] = constructor

    def construct(self):
        return Module.CONSTRUCTORS[self.type.name](self)

我认为您不需要特定的引擎类别;各种模块类就足够了.

I don't think you need a specific engine class; the various module classes will suffice.

这篇关于将模型与“通用"一起使用建模继承的字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆