Django 中 ManyToMany 的关联方法
来源:互联网 发布:mac电脑的终端命令 编辑:程序博客网 时间:2024/05/02 09:16
什么是 ManyToMany?
举个简单的例子,一本书可以有一个或多个作者,而一个作者可以写多本书,那么对于书和作者来说,他们的关系就不是一一对应的,而是多对多(也就是 ManyToMany)。在 Django 的 model 中,有个 ManyToManyField 专门来处理这种关系。
我写了个小应用来的管理 blog 的文章,因此我设计了这样的 model:
class Tag(models.Model): name = models.CharField(max_length=30)class Entry(models.Model): title = models.CharField(max_length=100) pub_date = models.DateField(blank=True, null=True) content = models.TextField() tags = models.ManyToManyField(Tag)
Entry 和 Tag 分别代表了 blog 的两大组件——文章和分类。Tag 很简单,只用一个 name 字段来存放 tag 的名字。而 Entry 则用了 title, pub_date, content 这 3 个字段来存放文章的标题、发布时间和文章内容。那么 tags = models.ManyToManyField(Tag)
是干什么的?
和之前的例子一样,一篇文章会有好几个 tag,而 tag 也下辖很多篇文章。从 Entry 的角度看,它有很多 tag(s),于是通过 ManyToManyField 与 Tag 关联起来。打开数据库,你可以看到 Django 专门生成了名为 entry_tags 的表来保存文章与 tag 的对应关系。
model 是搞定了,但实际中如何使用 model 往数据库里添加文章和 tag? 可以用 Model 的 save 方法或者 Manager 提供的 create 方法向数据库写入数据,因此可以这样添加 tag:
t = Tag()t.name = '测试't.save()# 或者Tag.objects.create(name='测试')
文章也是一样:
e = Entry()e.title = '测试'e.pub_date = '2010-03-11'e.content = 'test'e.save()
但这样只能分别添加 tag 和文章,而且文章与 tag 的对应关系没有添加进去。要想在添加文章的时候顺便把 tag 和对应关系也一并存放,我们需要重载 save 方法:
class Entry(models.Model): title = models.CharField(max_length=100) pub_date = models.DateField(blank=True, null=True) content = models.TextField() tags = models.ManyToManyField(Tag) taglist = [] def save(self, *args, **kwargs): super(Entry, self).save() for i in self.taglist: p, created = Tag.objects.get_or_create(name=i) self.tags.add(p)
在 Entry 的属性里多了个 taglist,它用来储存文章的 tag。之后使用 save 的时候,会先调用 Entry 父类的 save 方法将 title, pub_date, content 写入 entry 表,然后取出 taglist 中的每一个 tag,调用 Tag.objects.get_or_create 方法获得 Tag 对象,再用 ManyToMany 的 add 方法添加 Tag 对象,最后二次调用 save 方法把数据真正存入数据库。
Manager 的 get_or_create 方法接受给定参数作为查询条件,如果找到结果就返回找到的对象,如果没找到就先创建对象再返回它,这样一来我们就不用担心会出现重复添加 tag 的问题了。
能否在添加的文章的时候也使用 get_or_create 方法来防止重复添加呢,答案是当然可以。自定义一个 Manager 重载 get_or_create 即可。
class EntryManager(models.Manager): def get_or_create(self, **kwargs): defaults = kwargs.pop('defaults', {}) taglist = defaults.pop('taglist', {}) Entry.taglist = taglist kwargs.update(defaults) super(EntryManager, self).get_or_create(**kwargs)class Entry(models.Model): title = models.CharField(max_length=100) pub_date = models.DateField(blank=True, null=True) content = models.TextField() tags = models.ManyToManyField(Tag) taglist = [] objects = EntryManager() def save(self, *args, **kwargs): super(Entry, self).save() for i in self.taglist: p, created = Tag.objects.get_or_create(name=i) self.tags.add(p) self.taglist = []
因为 get_or_create 实际上还是会最终调用 model (Entry) 的 save 方法,所以才会用Entry.taglist = taglist
在真正执行 get_or_create 之前先把 tag 放进去。
最后就可以这样储存文章:
title = '测试'data = {'taglist': tags, 'pub_date': date, 'content': output, }Entry.objects.get_or_create(title=title, defaults=data)
以上代码均来自 Antidote(https://github.com/Vayn/Antidote),这是一个为方便用 jekyll 写 blog 的人管理文章的应用,欢迎 clone。
转自:http://www.zijin5.com/2011/04/django-manytomany/- Django 中 ManyToMany 的关联方法
- django manytomany field修改关联数据库问题
- django ManyToMany 使用的注意事项
- Django 关于manytomany add的问题
- @OneToMany @ManyToMany 关联表的不同
- Hibernate ManyToMany 删除两个实体的关联
- jpa 中@ManyToMany 标签使用后,只对关联表进行删除的写法
- jpa 中@ManyToMany 标签使用后,只对关联表进行删除的写法
- manyTomany中遇到的问题
- 在Hibernate中@ManyTOMany 单/双向外键关联
- Django - ManyToMany relationship problem
- ManyToMany关联映射
- Hibernate中的Entity类之间的ManyToMany关联
- ManyToMany双向外键关联(基于注解)的映射案例(简单版)
- Jpa中ManyToMany和OneToMany的双向控制
- django ManyToMany Filed通过through自定义赋值
- django ManyToMany Filed通过through自定义赋值
- 多对多关联查询 ManyToMany
- 八种主流NoSQL数据库系统对比
- 裂项法
- 守护进程
- Javascript 最简单的动态显示当前时间的代码
- WPF(Binding)
- Django 中 ManyToMany 的关联方法
- 错位相减法
- 【2008级的一些事】学会说不
- ulipad在xp下的安装及使用UliPad进行Django项目开发
- linux之awk
- PHP开启PDO
- 编写并使用程序库
- ORA-14404:分区表包含不同表空间中的分区
- 哥德巴赫猜想