django -- 多对多关系的实现

在django中表和表之间的多对多关系有两种实现方案:

  方案一:直接使用django自动实现的多对多关系。

  方案二:自己写连接表、然而告诉django在实现多对多关系时要使用的连接表。

 

一、方案一:

  model的定义

from django.db import models

class Person(models.Model):
    name= models.CharField(max_length=16)
    birthday=models.DateField()
class Group(models.Model):
    name= models.CharField(max_length=16)
    members = models.ManyToManyField(Person)

  对应的SQL代码

BEGIN;
--
-- Create model Group
--
CREATE TABLE "polls_group" (
    "id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, 
    "name" varchar(16) NOT NULL);
--
-- Create model Person
--
CREATE TABLE "polls_person" (
    "id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, 
    "name" varchar(16) NOT NULL, 
    "birthday" date NOT NULL);
--
-- Add field members to group
--
CREATE TABLE "polls_group_members" (
    "id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, 
    "group_id" integer NOT NULL REFERENCES "polls_group" ("id"), 
    "person_id" integer NOT NULL REFERENCES "polls_person" ("id"));

CREATE UNIQUE INDEX "polls_group_members_group_id_person_id_ce176f60_uniq" 
    ON "polls_group_members" ("group_id", "person_id");

CREATE INDEX "polls_group_members_group_id_f4695d83" 
    ON "polls_group_members" ("group_id");

CREATE INDEX "polls_group_members_person_id_fb30aa04" 
    ON "polls_group_members" ("person_id");

COMMIT;




-- ----------------------------
delimiter //
create procedure sp_a(a int)
BEGIN
    insert into t1(x,a) values(100,a);
end //
delimiter ;

 

 

 

二、方案二:

  model的定义

from django.db import models

class Person(models.Model):
    name= models.CharField(max_length=16)
    birthday=models.DateField()

    def __str__(self):
        return self.name

class Group(models.Model):
    name= models.CharField(max_length=16)
    members = models.ManyToManyField(Person,through=MemberShip)

class MemberShip(models.Model):
    person = models.ForeignKey(Person)
    group  = models.ForeignKey(Group)

    date_join=models.DateTimeField()
    invite_reason=models.CharField(max_length=100)

  对应的SQL代码:

BEGIN;
--
-- Create model Group
--
CREATE TABLE "polls_group" (
    "id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, 
    "name" varchar(16) NOT NULL);
--
-- Create model MemberShip
--
CREATE TABLE "polls_membership" (
    "id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, 
    "date_join" datetime NOT NULL, 
    "invite_reason" varchar(100) NOT NULL, 
    "group_id" integer NOT NULL REFERENCES "polls_group" ("id"));
--
-- Create model Person
--
CREATE TABLE "polls_person" (
    "id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, 
    "name" varchar(16) NOT NULL, 
    "birthday" date NOT NULL);
--
-- Add field person to membership
--
ALTER TABLE "polls_membership" RENAME TO "polls_membership__old";
CREATE TABLE "polls_membership" (
    "id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, 
    "date_join" datetime NOT NULL, 
    "invite_reason" varchar(100) NOT NULL, 
    "group_id" integer NOT NULL REFERENCES "polls_group" ("id"), 
    "person_id" integer NOT NULL REFERENCES "polls_person" ("id"));

INSERT INTO "polls_membership" ("id", "date_join", "invite_reason", "group_id", "person_id") SELECT "id", "date_join", "invite_reason", "group_id", NULL FROM "polls_membership__old";
DROP TABLE "polls_membership__old";
CREATE INDEX "polls_membership_group_id_19f13d47" ON "polls_membership" ("group_id");
CREATE INDEX "polls_membership_person_id_fa058fab" ON "polls_membership" ("person_id");
--
-- Add field members to group
--
CREATE TABLE "polls_group_members" (
    "id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, 
    "group_id" integer NOT NULL REFERENCES "polls_group" ("id"), 
    "person_id" integer NOT NULL REFERENCES "polls_person" ("id"));
    
CREATE UNIQUE INDEX "polls_group_members_group_id_person_id_ce176f60_uniq" ON "polls_group_members" ("group_id", "person_id");
CREATE INDEX "polls_group_members_group_id_f4695d83" ON "polls_group_members" ("group_id");
CREATE INDEX "polls_group_members_person_id_fb30aa04" ON "polls_group_members" ("person_id");
COMMIT;

 

 

三、由上面的SQL可以看出django来只是定义了memberShip模式对应的表、它自己也并没有放弃自己的那一套:

   model 的定义:

from django.db import models

class Person(models.Model):
    name= models.CharField(max_length=16)
    birthday=models.DateField()

    class Meta():
        db_table="person"

class Group(models.Model):
    name= models.CharField(max_length=16)
    members = models.ManyToManyField(Person,through='MemberShip')

    class Meta():
        db_table="group"

class MemberShip(models.Model):
    person = models.ForeignKey(Person)
    group  = models.ForeignKey(Group)

    date_join=models.DateTimeField()
    invite_reason=models.CharField(max_length=100)

    class Meta():
        db_table="membership"

  对应的SQL代码:

BEGIN;
--
-- Create model Group
--
CREATE TABLE "group" (
    "id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, 
    "name" varchar(16) NOT NULL);
--
-- Create model MemberShip
--
CREATE TABLE "membership" (
    "id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, 
    "date_join" datetime NOT NULL, 
    "invite_reason" varchar(100) NOT NULL, 
    "group_id" integer NOT NULL REFERENCES "group" ("id"));
--
-- Create model Person
--
CREATE TABLE "person" (
    "id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, 
    "name" varchar(16) NOT NULL, 
    "birthday" date NOT NULL);
--
-- Add field person to membership
--
ALTER TABLE "membership" RENAME TO "membership__old";
CREATE TABLE "membership" (
    "id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, 
    "date_join" datetime NOT NULL, 
    "invite_reason" varchar(100) NOT NULL, 
    "group_id" integer NOT NULL REFERENCES "group" ("id"), 
    "person_id" integer NOT NULL REFERENCES "person" ("id"));

INSERT INTO "membership" ("id", "date_join", "invite_reason", "group_id", "person_id") 
    SELECT "id", "date_join", "invite_reason", "group_id", NULL FROM "membership__old";

DROP TABLE "membership__old";

CREATE INDEX "membership_group_id_786fce67" ON "membership" ("group_id");
CREATE INDEX "membership_person_id_8ed25d16" ON "membership" ("person_id");
--
-- Add field members to group
--
ALTER TABLE "group" RENAME TO "group__old";
CREATE TABLE "group" (
    "id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, 
    "name" varchar(16) NOT NULL);

INSERT INTO "group" ("id", "name") 
    SELECT "id", "name" FROM "group__old";
    
DROP TABLE "group__old";
COMMIT;

 

 

总结:

  1、在定义模式时指定数据库中的表名是一个好的习惯、这样django就不会建立一些不需要的表了。

  2、对于多对多关系还是自己实现多对多关系比较好、一来可以保存一些额外的有用信息、表名也更加统一。

 

----

posted on 2017-11-29 16:16  蒋乐兴的技术随笔  阅读(2494)  评论(0编辑  收藏  举报

导航