Django框架多表查询实例分析


Posted in Python onJuly 04, 2018

本文实例讲述了Django框架多表查询。分享给大家供大家参考,具体如下:

多表查询是模型层的重要功能之一, Django提供了一套基于关联字段独特的解决方案.

ForeignKey

来自Django官方文档的模型示例:

from django.db import models
class Blog(models.Model):
  name = models.CharField(max_length=100)
  tagline = models.TextField()
class Author(models.Model):
  name = models.CharField(max_length=50)
  email = models.EmailField()
class Entry(models.Model):
  blog = models.ForeignKey(Blog)
  authors = models.ManyToManyField(Author)
  headline = models.CharField(max_length=255)
  body_text = models.TextField()
  pub_date = models.DateField()
  mod_date = models.DateField()
  n_comments = models.IntegerField()
  n_pingbacks = models.IntegerField()
  rating = models.IntegerField()

class ForeignKey

ForeignKey字段接受一个Model类作为参数, 类型与被参照的字段完全相同:

blog = models.ForeignKey(Blog)

ForeignKey.to_field

关联到的关联对象的字段名称。默认地,Django 使用关联对象的主键。

blog = models.ForeignKey(Blog, to_field=Blog.name)

ForeignKey.db_constraint

Django Model的ForeignKey字段的主要功能是维护一个一对多的关系, 以进行关联查询.

只有在db_constraint=True时Django model才会在数据库上建立外键约束, 在该值为False时不建立约束.

默认db_constraint=True.

ForeignKey.related_name

这个名称用于让关联的对象反查到源对象.

如果你不想让Django 创建一个反向关联,请设置related_name 为 '+' 或者以'+' 结尾.

ForeignKey.related_query_nameForeignKey.related_name作为默认值, 两者功能的具体说明请参见相关文档

使用ForeignKey查询

前向查询

若关系模型A包含与模型B关联的关联字段, 模型A的实例可以通过关联字段访问与其关联的模型B的实例:

>>> e = Entry.objects.get(id=2)
>>> e.blog # Returns the related Blog object.

修改e.blog并调用save方法存入数据库

>>> e.blog = some_blog
>>> e.save()

如果ForeignKey 字段有null=True 设置(即它允许NULL值),可以分配None来删除对应的关联性

>>> e = Entry.objects.get(id=2)
>>> e.blog = None
>>> e.save() # "UPDATE blog_entry SET blog_id = NULL ...;"

Django提供了一种使用双下划线__的查询语法:

>>> Entry.objects.filter(blog__name='Beatles Blog')

反向查询

被索引的关系模型可以访问所有参照它的模型的实例,如Entry.blog作为Blog的外键,默认情况下Blog.entry_set是包含所有参照Blog的Entry示例的查询集,可以使用查询集API取出相应的实例。

>>>b = Blog.objects.get(id=1)
>>>b.entry_set.all()

Entry.blog的related_name和related_query_name可以设置该查询集的名字。

ManyToManyField

来自Django官网的示例:

from django.db import models
class Person(models.Model):
  name = models.CharField(max_length=50)
class Group(models.Model):
  name = models.CharField(max_length=128)
  members = models.ManyToManyField(Person, through='Membership', through_fields=('group', 'person'))
class Membership(models.Model):
  group = models.ForeignKey(Group)
  person = models.ForeignKey(Person)
  inviter = models.ForeignKey(Person, related_name="membership_invites")
  invite_reason = models.CharField(max_length=64)

class ManyToManyField

ManyToManyField.through

Django 会自动创建一个表来管理多对多关系, 若要手动指定关联表则需要使用through关键字参数.

ManyToManyField.through_fields

上文示例中Membership 有两个外键指向Person (person 和inviter),这使得关联关系含混不清并让Django 不知道使用哪一个。

在这种情况下,必须使用through_fields 明确指定Django 应该使用哪些外键

through_fields 接收一个二元组('field1', 'field2'),其中field1 为指向定义ManyToManyField 字段的模型的外键名称(本例中为group),field2 为指向目标模型的外键的名称(本例中为person).

ManyToManyField.db_table

默认情况下,关联表的名称使用多对多字段的名称和包含这张表的模型的名称以及Hash值生成,如:memberShip_person_3c1f5

若要想要手动指定表的名称,可以使用db_table关键字参数指定.

others

下列API和ForeignKey中的同名API相同.

  • ManyToManyField.db_constraint
  • ManyToManyField.related_name
  • ManyToManyField.related_query_name

使用ManyToManyField查询

多对多关系和ForeignKey具有相似的API.

>>>e = Group.objects.get(id=3)
>>>e.members.all() # Returns all members objects for this Group.

反向查询:

>>>a = Person.objects.get(id=1)
>>>a.group_set.all()

同样related_name可以设置反向查询集的名称。

添加删除关联

因为ManyToManyField自动维护关联表,程序员不便于直接访问.ManyToManyField提供了API用于添加和删除关联(即through表中的记录).

使用一个自动维护through表的模型作为示例:

class User(models.Model):
  user_id = models.IntegerField(primary_key=True)
class Flight(models.Model):
  flight_id = models.IntegerField(primary_key=True)
  reserve = models.ManyToManyField(User, related_name='flight_reserve')

首先获得要进行关联的Flight和User实例:

flights = Flight.objects.filter(flight_id=flight_id)
if flights.count() != 0:
  flight = flights[0]
users = User.objects.filter(id=user_id)
if users.count() != 0:
  user = users[0]

通过拥有关联字段的Flight实例进行添加关联操作:

flight.reserve.add(user)
flight.save()

删除操作与这类似:

flight.reserve.remove(user)
flight.save()

希望本文所述对大家基于Django框架的Python程序设计有所帮助。

Python 相关文章推荐
跟老齐学Python之有容乃大的list(1)
Sep 14 Python
python 把数据 json格式输出的实例代码
Oct 31 Python
Python中turtle作图示例
Nov 15 Python
django 环境变量配置过程详解
Aug 06 Python
python实现自动化报表功能(Oracle/plsql/Excel/多线程)
Dec 02 Python
pytorch中torch.max和Tensor.view函数用法详解
Jan 03 Python
Pycharm 2020最新永久激活码(附最新激活码和插件)
Sep 17 Python
Django Xadmin多对多字段过滤实例
Apr 07 Python
django 数据库返回queryset实现封装为字典
May 19 Python
python math模块的基本使用教程
Jan 16 Python
你喜欢篮球吗?Python实现篮球游戏
Jun 11 Python
进行数据处理的6个 Python 代码块分享
Apr 06 Python
python 借助numpy保存数据为csv格式的实现方法
Jul 04 #Python
Python将一个CSV文件里的数据追加到另一个CSV文件的方法
Jul 04 #Python
python中csv文件的若干读写方法小结
Jul 04 #Python
Python画柱状统计图操作示例【基于matplotlib库】
Jul 04 #Python
pandas将numpy数组写入到csv的实例
Jul 04 #Python
Python实现的简单排列组合算法示例
Jul 04 #Python
把csv文件转化为数组及数组的切片方法
Jul 04 #Python
You might like
php 使用post,get的一种简洁方式
2010/04/25 PHP
PHP中限制IP段访问、禁止IP提交表单的代码
2011/04/23 PHP
codeigniter中测试通过的分页类示例
2014/04/17 PHP
PHP调试的强悍利器之PHPDBG
2016/02/22 PHP
thinkPHP框架对接支付宝即时到账接口回调操作示例
2016/11/14 PHP
JS类定义原型方法的两种实现的区别评论很多
2007/09/12 Javascript
使用Jquery来实现可以输入值的下拉选单 雏型
2011/12/06 Javascript
javascript为下拉列表动态添加数据项
2014/05/23 Javascript
基于NodeJS的前后端分离的思考与实践(五)多终端适配
2014/09/26 NodeJs
javascript冒泡排序小结
2016/04/10 Javascript
探究JavaScript中的五种事件处理程序方式
2016/12/07 Javascript
从零开始学习Node.js系列教程之SQLite3和MongoDB用法分析
2017/04/13 Javascript
微信小程序实现动态设置页面标题的方法【附源码下载】
2017/11/29 Javascript
jQuery中库的引用方法
2018/01/06 jQuery
AngularJS与BootStrap模仿百度分页的示例代码
2018/05/23 Javascript
vue axios数据请求及vue中使用axios的方法
2018/09/10 Javascript
Vue多组件仓库开发与发布详解
2019/02/28 Javascript
微信小程序常用赋值方法小结
2019/04/30 Javascript
微信小程序实现音乐播放页面布局
2020/12/11 Javascript
微信小程序学习之自定义滚动弹窗
2020/12/20 Javascript
[01:11:02]Secret vs Newbee 2019国际邀请赛小组赛 BO2 第一场 8.15
2019/08/17 DOTA
python socket网络编程步骤详解(socket套接字使用)
2013/12/06 Python
Python将list中的string批量转化成int/float的方法
2018/06/26 Python
python使用pip安装模块出现ReadTimeoutError: HTTPSConnectionPool的解决方法
2019/10/04 Python
使用Python实现Wake On Lan远程开机功能
2020/01/22 Python
pycharm无法导入本地模块的解决方式
2020/02/12 Python
Python实现AI自动抠图实例解析
2020/03/05 Python
解决python父线程关闭后子线程不关闭问题
2020/04/25 Python
基于PyTorch的permute和reshape/view的区别介绍
2020/06/18 Python
关于PyCharm安装后修改路径名称使其可重新打开的问题
2020/10/20 Python
加拿大鞋子连锁店:Town Shoes
2016/09/26 全球购物
Java 中访问数据库的步骤?Statement 和PreparedStatement 之间的区别?
2012/06/05 面试题
2014最新版群众路线四风整改措施
2014/09/24 职场文书
信用卡工作证明范本
2015/06/19 职场文书
护士爱岗敬业心得体会
2016/01/25 职场文书
vite+vue3.0+ts+element-plus快速搭建项目的实现
2021/06/24 Vue.js