Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Django中模型继承的多对多关系_Django_Inheritance - Fatal编程技术网

Django中模型继承的多对多关系

Django中模型继承的多对多关系,django,inheritance,Django,Inheritance,我有一个抽象对象叫做parameter。参数可以是几种不同的类型。例如-数值参数、常数参数、多值参数等。 每个参数可以与许多不同类型的参数相关,反之亦然 在检查了Django的文档之后,我决定我需要的是一个简单的。基类中的多对多关系示例可在后面的文档中找到 class ParameterBase(models.Model): id = models.AutoField(primary_key=True) description = models.CharField(max

我有一个抽象对象叫做parameter。参数可以是几种不同的类型。例如-数值参数、常数参数、多值参数等。 每个参数可以与许多不同类型的参数相关,反之亦然

在检查了Django的文档之后,我决定我需要的是一个简单的。基类中的多对多关系示例可在后面的文档中找到

class ParameterBase(models.Model):
    id = models.AutoField(primary_key=True)    
    description = models.CharField(max_length=200)
    sort_order = models.DecimalField(null=False, max_digits=6, decimal_places=4)

    m2m = models.ManyToManyField('self',related_name='dependent_on')

    class Meta:
        abstract = True

class ParameterConstant(ParameterBase):
    value = models.DecimalField(null=False, blank=False, max_digits=20 , decimal_places=4)

class ParameterNumeric(ParameterBase):
    minimum = models.DecimalField(null=True, blank=True, max_digits=20 , decimal_places=4)    
    maximum = models.DecimalField(null=True, blank=True, max_digits=20 , decimal_places=4)
所以同步后我可以看到django创建了4个表-

CREATE TABLE "calc_parameterconstant_m2m" (
    "id" serial NOT NULL PRIMARY KEY,
    "from_parameterconstant_id" integer NOT NULL,
    "to_parameterconstant_id" integer NOT NULL,
    UNIQUE ("from_parameterconstant_id", "to_parameterconstant_id")
)
;
CREATE TABLE "calc_parameterconstant" (
    "id" serial NOT NULL PRIMARY KEY,
    "description" varchar(200) NOT NULL,
    "sort_order" numeric(6, 4) NOT NULL,
    "value" numeric(20, 4) NOT NULL
)
;
ALTER TABLE "calc_parameterconstant_m2m" ADD CONSTRAINT "from_parameterconstant_id_refs_id_f893bb67" FOREIGN KEY ("from_parameterconstant_id") REFERENCES "calc_parameterconstant" ("id") DEFERRABLE INITIALLY DEFERRED;
ALTER TABLE "calc_parameterconstant_m2m" ADD CONSTRAINT "to_parameterconstant_id_refs_id_f893bb67" FOREIGN KEY ("to_parameterconstant_id") REFERENCES "calc_parameterconstant" ("id") DEFERRABLE INITIALLY DEFERRED;

CREATE TABLE "calc_parameternumeric_m2m" (
    "id" serial NOT NULL PRIMARY KEY,
    "from_parameternumeric_id" integer NOT NULL,
    "to_parameternumeric_id" integer NOT NULL,
    UNIQUE ("from_parameternumeric_id", "to_parameternumeric_id")
)
;
CREATE TABLE "calc_parameternumeric" (
    "id" serial NOT NULL PRIMARY KEY,
    "description" varchar(200) NOT NULL,
    "sort_order" numeric(6, 4) NOT NULL,
    "minimum" numeric(20, 4),
    "maximum" numeric(20, 4)
)
现在,这显然不是我的意图——我希望能够将每种类型的参数连接到其他类型的参数。使用Django ORM和模型继承有没有办法实现这个目标

如果基本参数模型本身是一个表,与它自身有多对多关系,并且子表通过一对一的非绑定关系连接,这可能是一个很好的解决方案

我想这会解决你的问题。要使用它,只需从
ParameterBase.Meta
子类中删除
abstract=True
(或完全删除该子类)

在使用多表继承时,为了访问特定子类的属性,Django必须知道您正在处理该子类

例如,这将失败:

p = ParameterBase.objects.get(...)  # get a ParameterBase that is a ParameterConstant
print p.value
相反,您必须这样做:

p = ParameterConstant.objects.get(...)
print p.value
或者这个:

p = ParameterBase.objects.get(...)  # get a ParameterBase that is a ParameterConstant
print p.paramaterconstant.value

解决这一问题的一种方法是更换

m2m = models.ManyToManyField('self',related_name='dependent_on')

但Django不允许您创建指向尚未安装的模型或抽象模型的m2m字段。此时,
ParameterBase
是这两个参数

我会这样做

class Parameter(models.Model):
    id = models.AutoField(primary_key=True)    
    description = models.CharField(max_length=200)
    sort_order = models.DecimalField(null=False, max_digits=6, decimal_places=4)

class ParameterType(models.Model):
    parameter = models.ForeignKey(Parameter)
    related_parameters = models.ManyToManyField(Parameter,related_name='dependent_on')

    class Meta:
        abstract = True

class ParameterConstant(ParameterType):
    value = models.DecimalField(null=False, blank=False, max_digits=20 , decimal_places=4)

class ParameterNumeric(ParameterType):
    minimum = models.DecimalField(null=True, blank=True, max_digits=20 , decimal_places=4)    
    maximum = models.DecimalField(null=True, blank=True, max_digits=20 , decimal_places=4)

如果在抽象父类中使用多个字段,则应提供唯一的相关\u名称。。。在您的情况下,这应该很好:


m2m=models.ManyToManyField('self',related_name='%(app_label)s_wu%(class)s_m2m')

在单独的模型中使用多表模型继承而不是普通的一对一字段有什么附加值?子类仍然可以访问父类的属性和方法。在本例中,如果p是ParameterConstant的实例,那么p.description将执行您所期望的操作。另外,像
isinstance(p,ParameterBase)
这样的东西也可以正常工作,因为它使用普通的python继承。如果使用OneToOneField,则必须显式导航到“父”类。使用OneToOneField不是继承。我能想到的另一个区别是,请求继承参数可能会导致对两个表进行查询,而使用一对一允许延迟加载其他参数。这取决于
p=ParameterBase.objects.get(…)
将只获取ParameterBase表中定义的字段,而不获取联接。使用
p.parameterconstant
会触发对parameterconstant表的查询
p=ParameterConstant.objects.get(…)
使用内部联接对两个表执行单个查询。如果我有一个ParameterBase并且我想要子模型,我必须知道我的类型。所以在初始化子类时,我需要在父类中设置一个类型模型。。。类似于
super(ParameterBase,self.\uuuuu class.\uuuu name.\uuuu)
这实际上是一个非常有趣的想法。子模型与基础模型之间是否缺少一对一的链接?您可以从m2m获得关联,但还需要当前子类的基本参数。
class Parameter(models.Model):
    id = models.AutoField(primary_key=True)    
    description = models.CharField(max_length=200)
    sort_order = models.DecimalField(null=False, max_digits=6, decimal_places=4)

class ParameterType(models.Model):
    parameter = models.ForeignKey(Parameter)
    related_parameters = models.ManyToManyField(Parameter,related_name='dependent_on')

    class Meta:
        abstract = True

class ParameterConstant(ParameterType):
    value = models.DecimalField(null=False, blank=False, max_digits=20 , decimal_places=4)

class ParameterNumeric(ParameterType):
    minimum = models.DecimalField(null=True, blank=True, max_digits=20 , decimal_places=4)    
    maximum = models.DecimalField(null=True, blank=True, max_digits=20 , decimal_places=4)