Django的Many-to-Many(多对多)模型

日期:2012-05-05 |  来源:未知 |  作者:redice |  人围观 |  1 人鼓掌了!

参考:《DjangoBook2.0》 数据模型高级进阶

经典的例子:一本书有多个作者,一个作者有多本书,典型的多对多关系。

设计模型如下:

  1. from django.db import models
  2. class Author(models.Model):
  3. first_name = models.CharField(max_length=30)
  4. last_name = models.CharField(max_length=40)
  5. email = models.EmailField()
  6. def __unicode__(self):
  7. return self.name
  8. class Meta:
  9. db_table = "author"
  10. class Book(models.Model):
  11. title = models.CharField(max_length=200)
  12. authors = models.ManyToManyField(Author)
  13. def __unicode__(self):
  14. return self.title
  15. class Meta:
  16. db_table = "book"

python manage.py sqlall books(App名) 看一下Django帮我们生成的数据库表结构:

  1. CREATE TABLE `author` (
  2. `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
  3. `first_name` varchar(30) NOT NULL,
  4. `last_name` varchar(40) NOT NULL,
  5. `email` varchar(75) NOT NULL
  6. )
  7. ;
  8. CREATE TABLE `book_authors` (
  9. `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
  10. `book_id` integer NOT NULL,
  11. `author_id` integer NOT NULL,
  12. UNIQUE (`book_id`, `author_id`)
  13. )
  14. ;
  15. ALTER TABLE `book_authors` ADD CONSTRAINT `author_id_refs_id_22051734` FOREIGN KEY (`author_id`) REFERENCES `author` (`id`);
  16. CREATE TABLE `book` (
  17. `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
  18. `title` varchar(200) NOT NULL
  19. )
  20. ;
  21. ALTER TABLE `book_authors` ADD CONSTRAINT `book_id_refs_id_77516490` FOREIGN KEY (`book_id`) REFERENCES `book` (`id`);

book表中并没有authors字段,其中的book_authors表就是用来存放书和作者多对多映射关系的。

访问多值:

一本书的所有作者:

b = Book.objects.get(id=50)

b.authors.all()

b.authors.filter(first_name='Adam')

反向也可以,一个作者的所有书:

a = Author.objects.get(id=1)

a.book_set.all()

给多对多字段添加值(添加多对多关系):

a = Author.objects.get(id=1)

b = Book.objects.get(id=50)

b.authors.add(a)

从多对多字段中删除值(删除多对多关系):

a = Author.objects.get(id=1)

b = Book.objects.get(id=50)

b.authors.remove(a) 或者 b.authors.filter(id=1).delete()

我想自定义关系表!!!

为什么?

可能的原因:

1)我想添加一些额外的字段;

2)与现有系统集成,关系表已经存在。

定义方法如下:

  1. # coding: utf-8
  2. from django.db import models
  3. class Author(models.Model):
  4. first_name = models.CharField(max_length=30)
  5. last_name = models.CharField(max_length=40)
  6. email = models.EmailField()
  7. def __unicode__(self):
  8. return self.name
  9. class Meta:
  10. db_table = "author"
  11. class Book(models.Model):
  12. title = models.CharField(max_length=200)
  13. authors = models.ManyToManyField(Author, through='BookAuthor') # 注意多了through参数
  14. def __unicode__(self):
  15. return self.title
  16. class Meta:
  17. db_table = "book"
  18. class BookAuthor(models.Model):
  19. book = models.ForeignKey(Book)
  20. author = models.ForeignKey(Author)
  21. created_at = models.DateTimeField(auto_now_add=True) # 我要添加额外的字段
  22. class Meta:
  23. db_table = "book_author_relationship" # 我需要用自定义的名称

再看一下此时的数据库表结构:

  1. BEGIN;
  2. CREATE TABLE `author` (
  3. `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
  4. `first_name` varchar(30) NOT NULL,
  5. `last_name` varchar(40) NOT NULL,
  6. `email` varchar(75) NOT NULL
  7. )
  8. ;
  9. CREATE TABLE `book` (
  10. `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
  11. `title` varchar(200) NOT NULL
  12. )
  13. ;
  14. CREATE TABLE `book_author_relationship` (
  15. `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
  16. `book_id` integer NOT NULL,
  17. `author_id` integer NOT NULL,
  18. `created_at` datetime NOT NULL
  19. )
  20. ;
  21. ALTER TABLE `book_author_relationship` ADD CONSTRAINT `author_id_refs_id_6b774382` FOREIGN KEY (`author_id`) REFERENCES `author` (`id`);
  22. ALTER TABLE `book_author_relationship` ADD CONSTRAINT `book_id_refs_id_7cf7763a` FOREIGN KEY (`book_id`) REFERENCES `book` (`id`);
  23. CREATE INDEX `book_author_relationship_752eb95b` ON `book_author_relationship` (`book_id`);
  24. CREATE INDEX `book_author_relationship_337b96ff` ON `book_author_relationship` (`author_id`);
  25. COMMIT;

爽!

但是这样做也是有不便的地方:多对多字段的add()和remove()方法就不能用了。这里有很好的解释:http://stackoverflow.com/questions/1755591/many-to-many-relationships-with-additional-data-on-the-relationship

https://docs.djangoproject.com/en/dev/topics/db/models/#extra-fields-on-many-to-many-relationships

那此时我们如何添加和删除映射关系呢?直接使用BookAuthor模型。

例如:

a = Author.objects.get(id=1)

b = Book.objects.get(id=50)

BookAuthor(book=b, author=a).save()

Django的Many-to-Many(多对多)模型的更多相关文章

  1. django一对多、多对多模型、自关联的建立

    # 原创,转载请留言联系 一对多模型 一对多的关系,例如员工跟部门.一个部门有多个员工.那么在django怎么建立这种表关系呢? 其实就是利用外键,在多的一方,字段指定外键即可.例如员工和部门,员工是 ...

  2. Django学习笔记之数据库-数据库与模型

    MySQL数据库 在网站开发中,数据库是网站的重要组成部分.只有提供数据库,数据才能够动态的展示,而不是在网页中显示一个静态的页面.数据库有很多,比如有SQL Server.Oracle.Postgr ...

  3. legend3---lavarel多对多模型操作实例

    legend3---lavarel多对多模型操作实例 一.总结 一句话总结: 在多对多模型中,增加关系表的数据 需要 弄一个和关系表一对多的模型关系 1.在lavarel关系模型中,课程和标签表是多对 ...

  4. Python Django框架笔记(五):模型

    #前言部分来自Django Book (一)    前言 大多数web应用本质上: 1. 每个页面都是将数据库的数据以HTML格式进行展现. 2. 向用户提供修改数据库数据的方法.(例如:注册.发表评 ...

  5. Django ORM 一对一,一对多,多对多, 添加,批量插入和查询

    模型类 class Book(models.Model): nid = models.AutoField(primary_key=True) title = models.CharField(max_ ...

  6. Django——7 常用的查询 常用的模型字段类型 Field的常用参数 表关系的实现

    Django 常用的查询 常用的查询方法 常用的查询条件 常用字段映射关系 Field常用参数 表关系的实现 查用的查询方法 这是需要用到的数据 from django.http import Htt ...

  7. django ajax MTV与MVC 多对多创建方式

    MTV与MVC MTV模型(django): M:模型层(models.py) T:templates V:views MVC模型: M:模型层(models.py) V:视图层(views.py) ...

  8. django 中models表的多对一,多对多的理解

    django 表的理解 好处:设计的好,会清晰,易于理解和维护,后期开发事半功倍,一目了然. 1. 一对一的表,两表的属性实际上完全可以合并成一个表,共用一个主键即可: 2. 一对多的表,可以设中间关 ...

  9. Django教程:[33]从数据库生成模型

    在使用django做网站的时候,有时候我们的数据库来自一个已有的数据库,如何整合这个数据库呢? django提供了方便的方法来整合已有数据库,下面我们看看具体的方法: 1.先来设置数据库:在网站文件夹 ...

  10. django “如何”系列8:如何为模型提供初始化数据

    当你第一次配置一个app的时候,有时候使用硬编码的数据去预填充你的数据库是非常有用的.这里有几个你可以让django自动创建这些数据的方法:你可以提供固定格式的初始化数据或者提供通过SQL初始化数据. ...

随机推荐

  1. Win7旗舰版中的IIS配置asp.net的运行环境

    Win7旗舰版中的IIS配置asp.net的运行环境   以前弄过好多次,都没有成功,昨天晚上不知怎么地就成功了,借用我同学的一句话,这叫“灵光一闪”,废话不多说了,这个成功是有图有视频有真相地哈! ...

  2. servlet、genericservlet、httpservlet之间的区别(转)

    当编写一个servlet时,必须直接或间接实现servlet接口,最可能实现的方法就是扩展javax.servlet.genericservlet或javax.servlet.http.httpser ...

  3. SVN上传文件注意事项-------------------养成良好的项目文件上传习惯

    项目组的学弟经常把一些.obj文件和debug目录上传到svn,这个习惯很不好,我说了很多次他总改不了,还是写个文档说清楚吧,以后查起来也方便.     svn是一种版本控制工具,主要目的是用来管理代 ...

  4. 7、XML加强/Web开发/Tomcat

    1 XML加强 XML加强 1)Dom4j修改XML文档 写出xml文档: XMLWriter writer = new XMLWriter() writer.wrtite(doc); 增加: Doc ...

  5. UINavigationController侧滑滑动返回 卡死问题

    UINavigationController滑动返回,有需要的朋友可以参考下. 最近做了UINavigationController的滑动返回(IOS7及以后系统默认支持的), 主要分成以下几步以及碰 ...

  6. quick lua 3.3常用方法和学习技巧之functions.lua目录

    1.functions.lua (framework->functions.lua) 提供一组常用函数,以及对 Lua 标准库的扩展 1.printf 2.checknumber checkin ...

  7. 第十一章 Android 内核驱动——Alarm

    11.1  基本原理 Alarm 闹钟是 android 系统中在标准 RTC 驱动上开发的一个新的驱动,提供了一个定时器 用于把设备从睡眠状态唤醒,当然因为它是依赖 RTC 驱动的,所以它同时还可以 ...

  8. syntactically incorrect() 404

    遇到这个错误就来记录一下吧. 这个错误是springMVC报出的错误.大致的意思就是form传值的类型和controller中的参数不符. 有可能是名字错误,有可能是类型不对.比如前面你传来的是  p ...

  9. windows上安装apache python mod_python

    综述:   windows上安装apache python mod_python的例子.教程甚至图解都不少:但作为新手还是会出错,而且一时无法快速排解. 在此笔者将根据自己的实践经验,给出几个需要注意 ...

  10. 使用Window Live Writer写博客

    1.打开“日志账户”—>“日志选项”. 2.点击“更新账户信息”. 3.输入博客地址,用户名和密码,点击“下一步”. 4.耐心等待片刻... 5.设置“日志昵称”,点击“完成”. 这样就大功告成 ...