Django 多对多字段

Posted

技术标签:

【中文标题】Django 多对多字段【英文标题】:Django ManyToMany Field 【发布时间】:2013-04-27 22:24:13 【问题描述】:

我需要制作一个智能菜单,为此我需要一个多对多关系。

我的模型是:

from django.db import models

    class Health_plan(models.Model):
        a = models.IntegerField ()
        b = models.IntegerField ()

   class Doctors_list(models.Model):

        name = models.CharField(max_length=30)
        hp_id = models.ManyToManyField(Health_plan)

        def __unicode__(self):
            return self.name

如何在数据库中建立这种关系?我正在考虑将health_plans (a,b) 作为列,将医生作为行,用 0 和 1 来标识他们所涵盖的健康计划。

有人告诉我这是滥用ManyToManyField,我不知道该怎么做。

帮助赞赏

【问题讨论】:

【参考方案1】:

Django 为您创建表格。在您的项目文件夹中运行:

python manage.py syncdb

Health_plan 和 Doctors_list 都是表。 “a”和“b”是 Health_plan 中的列。 'Name' 和 'hp_id' 是 Doctors_list 中的列。 Django 将在每个表中为 id 创建一个列。 Django 还会创建一个表“Doctor_list_Health_plan”来存储关系信息。

Django 模型是 Python 类,因此适用 Python 命名约定。使用 HealthPlan 和 Doctor(CapitalizeWord 单数)。

您的字段名称有点抽象。我建议您使用更具描述性的名称。例如:

class HealthPlan(models.Model):
    name = models.CharField()
    extra_care = models.BooleanField()

【讨论】:

【参考方案2】:

Django 的 ORM 已经处理了中间表,因此您不必“在数据库中建立这个关系(船)”,但鉴于您的问题,您显然需要了解正确的关系模型规范化 - 如果您不这样做'不了解关系模型,使用 Django 的 ORM 和任何其他 sql 东西 FWIW 都将一事无成。

为了记录,在关系模型中,多对多关系被建模为在其他两个表上都有外键的关系(SQL 中的“表”),即:

health_plan(#health_plan_id, name, ...)
doctor(#doctor_id, firstname, lastname, ...)
doctors_health_plans(#health_plan_id, #doctor_id)

所以你的 django 模型应该是:

class HealthPlan(models.Model):
    # no need to define an 'id' field,
    # the ORM provides one by default
    name = models.CharField(....)

class Doctor(models.Model):
    firstname = models.CharField(....)
    lastname = models.CharField(....)
    health_plans = models.ManyToManyField(HealthPlan, related_name="doctors")

然后您就可以获得医生的所有健康计划:

  doc = Doctor.objects.get(pk=xxxx)
  doc.health_plans.all()

和健康计划的所有医生:

  plan = HealthPlan.objects.get(pk=xxxx)
  plan.doctors.all()

FineManual(tm) 像往常一样是你的朋友...

【讨论】:

【参考方案3】:

health_plans 列为列的方法不一定是错误的,但这意味着您拥有固定数量的健康计划,并且您永远不会添加新计划。

关系数据库中多对多关系的传统方法是在中间引入一个表。此表将仅包含医生和健康计划之间的关联。

如果您有一个 Doctor 表,其中包含:

id    name
1     foo
2     bar

还有一个HealthPlan 表:

id    model
1     a
2     b

然后添加一个表格Doctor_HealthPlan,如下所示:

doctor_id    healthplan_id
1            2
2            1
2            2

django 中的ManyToMany 字段类型会自动为您创建此表。您的代码是正确的,但您可能应该将 hp_id 重命名为 health_plans,因为它是一个代理,可让您访问与医生相关的健康计划列表。

【讨论】:

所以在我的健康计划表上我只做:class Health_plan(models.Model): name = models.Charfield (max_lenght=10) ----> 并且在一个医生 ID 的连接表上我放了多个健康计划 ID? 连接表由django管理。您的Health_Plan 应包含一个姓名,您的医生应包含一个绑定到Health_PlanManyToMany 字段。【参考方案4】:

您只需先保存两个模型,然后将 healthplan 实例添加到医生列表中。 Django 将为您处理剩下的事情。

例如:

doctor_list = Doctors_list(name="Bwire")
health_plan.save()
doctor_list.save()

#Then add the plan to the doctors list.
doctor_list.hp_id.add(health_plan)

【讨论】:

以上是关于Django 多对多字段的主要内容,如果未能解决你的问题,请参考以下文章

多对多字段返回无 django

Django如何过滤多对多字段中的对象,而不是原始查询集

Django:按多对多字段订购模型

完全加入多对多字段 Django

Django:Syncdb 错误地警告多对多字段已过时

在Django中按关系字段过滤多对多关系