5Python全栈之路系列之Django模型续

Python全栈之路系列之Django模型续

连表操作一对一

appmodels.py文件内添加以下内容用户创建一对多关系的表:

from django.db import models

# Create your models here.

class UserType(models.Model):
    nid = models.AutoField(primary_key=True)
    caption = models.CharField(max_length=32)
    
class UserInfo(models.Model):
    username = models.CharField(max_length=32)
    password = models.CharField(max_length=16)
    user_type = models.ForeignKey(‘UserType‘)

app的名字添加到项目的settings.py配置文件的INSTALLED_APPS中,然后再数据库中生成表:

E:\DjangoProjects>python manage.py makemigrations
E:\DjangoProjects>python manage.py migrate

基本操作

进入带有django环境变量的项目,然后把模型导入进去,用于做下面的操作

E:\DjangoProjects>python manage.py shell
Python 3.5.2 (v3.5.2:4def2a2901a5, Jun 25 2016, 22:18:55) [MSC v.1900 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> from app01 import models

添加数据

# 通过create方式进行数据的添加
>>> models.UserType.objects.create(caption=‘版主‘)
<UserType: UserType object>
# 通过save保存的方式添加数据
>>> obj = models.UserType(caption=‘管理员‘)
>>> obj.save()
# 通过字典的方式进行数据添加
>>> UserInfoDict = {‘username‘:‘ansheng‘,‘password‘:‘helloword‘,‘user_type‘: models.UserType.objects.get(nid=1)}
# 通过**UserInfoDict把数据以字典方式传给create
>>> models.UserInfo.objects.create(**UserInfoDict)
<UserInfo: UserInfo object>
>>> UserInfoDict = {‘username‘:‘hello‘,‘password‘:‘word‘,‘user_type‘: models.UserType.objects.get(nid=2)}
>>> models.UserInfo.objects.create(**UserInfoDict)
<UserInfo: UserInfo object>
# 如果知道user_type_id代表多少,那么也可以直接写数字
>>> UserInfoDict = {‘username‘:‘ansheng‘,‘password‘:‘helloword‘,‘user_type_id‘: 2}
>>> models.UserInfo.objects.create(**UserInfoDict)
<UserInfo: UserInfo object>

修改数据

# 指定条件更新
>>> models.UserInfo.objects.filter(password=‘helloword‘).update(password=‘hw‘)
1
# 获取id=1的这条数据对象
>>> obj = models.UserInfo.objects.get(id=1)
# 把username字段修改成as
>>> obj.username = ‘as‘
# 保存操作
>>> obj.save()

删除数据

>>> models.UserInfo.objects.filter(username=‘ansheng‘, user_type_id=‘2‘).delete()
(1, {‘app01.UserInfo‘: 1})

查询数据

# 获取单条数据,不存在则报错
>>> models.UserInfo.objects.get(id=1)
<UserInfo: UserInfo object>
>>> models.UserInfo.objects.get(id=23)
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "C:\Python\Python35\lib\site-packages\django\db\models\manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "C:\Python\Python35\lib\site-packages\django\db\models\query.py", line 385, in get
    self.model._meta.object_name
app01.models.DoesNotExist: UserInfo matching query does not exist.
# 获取全部数据
>>> models.UserInfo.objects.all()
<QuerySet [<UserInfo: UserInfo object>]>
# 获取指定条件的数据
>>> models.UserInfo.objects.filter(username=‘as‘)
<QuerySet [<UserInfo: UserInfo object>]>

单表查询

查询出来的结果都是queryset对象

query方法

query是用来查看查询语句的,即django生成的SQL

>>> ret = models.UserType.objects.all()
>>> print(ret.query)
SELECT `app01_usertype`.`nid`, `app01_usertype`.`caption` FROM `app01_usertype`

values与values_list

>>> ret = models.UserType.objects.all().values(‘nid‘)
# 返回的列表,列表里面套字典
>>> print(type(ret),ret)
<class ‘django.db.models.query.QuerySet‘> <QuerySet [{‘nid‘: 1}, {‘nid‘: 2}]>
>>> ret = models.UserType.objects.all().values_list(‘nid‘)
# 返回一个列表,列表里面套集合
>>> print(type(ret),ret)
<class ‘django.db.models.query.QuerySet‘> <QuerySet [(1,), (2,)]>

双下划线连表操作

>>> ret = models.UserInfo.objects.all().values(‘username‘,‘user_type__caption‘)
# INNER
>>> print(ret.query)
SELECT `app01_userinfo`.`username`, `app01_usertype`.`caption` FROM `app01_userinfo` INNER JOIN `app01_usertype` ON (`app01_userinfo`.`user_type_id` = `app01_usertype`.`nid`)
>>> ret = models.UserInfo.objects.all()
>>> for item in ret:
...  print(item,item.id,item.user_type.nid,item.user_type.caption,item.user_type_id)
...
UserInfo object 1 1 版主 1

查询实例

获取用户类型是超级管理员的所有用户

正向查找

通过双下划线连表查询

>>> ret = models.UserInfo.objects.filter(user_type__caption = "管理员").values(‘username‘,‘user_type__caption‘)
>>> print(ret,type(ret),ret.query)
<QuerySet [{‘user_type__caption‘: ‘管理员‘, ‘username‘: ‘hello‘}]> <class ‘django.db.models.query.QuerySet‘> SELECT `app01_userinfo`.`username`, `app01_usertype`.`caption` FROM `app01_userinfo` INNER JOIN `app01_usertype` ON (`app01_userinfo`.`user_type_id` = `app01_usertype`.`nid`) WHERE `app01_usertype`.`caption` = 管理员

反向查找

先查找UserType表中数据,再把这个数据和UserInfo表中进行过滤

>>> obj = models.UserType.objects.filter(caption= ‘管理员‘).first()
>>> print(obj.nid, obj.caption)
2 管理员
>>> print(obj.userinfo_set.all())
<QuerySet [<UserInfo: UserInfo object>]>

把UserType表里的所有字段和userinfo表进行一个匹配,如果有匹配到就显示出来

>>> ret = models.UserType.objects.all().values(‘nid‘,‘caption‘,‘userinfo__username‘)
>>> print(ret)
<QuerySet [{‘userinfo__username‘: ‘as‘, ‘nid‘: 1, ‘caption‘: ‘版主‘}, {‘userinfo__username‘: ‘hello‘, ‘nid‘: 2, ‘caption‘: ‘管理员‘}]>

连表操作多对多

两种创建多对多表的方式

手动指定第三张表进行创建

class HostGroup(models.Model):
    hgid = models.AutoField(primary_key=True)
    host_id = models.ForeignKey(‘Host‘)
    group_id = models.ForeignKey(‘Group‘)
    
class Host(models.Model):
    hid = models.AutoField(primary_key=True)
    hostname = models.CharField(max_length=32)
    ip = models.CharField(max_length=32)
    
class Group(models.Model):
    gid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=16)
    # 指定第三张表
    h2g = models.ManyToManyField(‘Host‘, through=‘HostGroup‘)

django帮我们创建第三张表

创建以下表关系用于测试多对多

class Host(models.Model):
    hid = models.AutoField(primary_key=True)
    hostname = models.CharField(max_length=32)
    ip = models.CharField(max_length=32)
    
class Group(models.Model):
    gid = models.AutoField(primary_key=True)
    name = models.CharField(max_length=16)
    # 任意一个字段,会自动生成第三张表,且第三张表会自动的添加联合唯一索引,Unique
    h2g = models.ManyToManyField(‘Host‘)

插入以下数据用于测试

# Host插入数据
>>> models.Host.objects.create(hostname=‘localhost‘, ip=‘192.168.1.1‘)
<Host: Host object>
>>> models.Host.objects.create(hostname=‘linux-node1‘, ip=‘192.168.1.2‘)
<Host: Host object>
>>> models.Host.objects.create(hostname=‘linux-node2‘, ip=‘192.168.1.3‘)
<Host: Host object>
>>> models.Host.objects.create(hostname=‘web-node1‘, ip=‘192.168.1.4‘)
<Host: Host object>
# Group插入数据
>>> models.Group.objects.create(name=‘市场部‘)
<Group: Group object>
>>> models.Group.objects.create(name=‘技术部‘)
<Group: Group object>
>>> models.Group.objects.create(name=‘财务部‘)
<Group: Group object>
>>> models.Group.objects.create(name=‘运维部‘)
<Group: Group object>
>>> models.Group.objects.create(name=‘销售部‘)
<Group: Group object>

单个添加数据

# 获取组中gid=1的这条数据
>>> obj = models.Group.objects.get(gid=1)
# 获取表中的内容
>>> obj.gid, obj.name
(1, ‘市场部‘)
# 获取第三张表的内容
>>> obj.h2g.all()
<QuerySet []>
# 获取一个主机
>>> h1 = models.Host.objects.get(hid=2)
# 获取主机的IP
>>> h1.ip
‘192.168.1.2‘
# 把主机hid=2和组gid=1的这两条数据做一个对应关系,放入第三章比哦中
>>> obj.h2g.add(h1)
# 查看输入
>>> obj.h2g.all()
<QuerySet [<Host: Host object>]>

批量添加

# 获取GID大于2的所有主机
>>> h = models.Host.objects.filter(hid__gt=2)
# 获取到两条数据
>>> h
<QuerySet [<Host: Host object>, <Host: Host object>]>
# 把上面的主机添加到第三张表内
>>> obj.h2g.add(*h)
# 添加的数据总和为三条
>>> obj.h2g.all()
<QuerySet [<Host: Host object>, <Host: Host object>, <Host: Host object>]>

反向操作

上面的例子中我们往一个部门中添加了多台机器,那么现在我们将一个机器添加到多个部门中

# 获取ip=‘192.168.1.3‘的这台机器
>>> host = models.Host.objects.get(ip=‘192.168.1.3‘)
# 把上面的那台机器添加到gid大于2的所有部门内
>>> host.group_set.add(*models.Group.objects.filter(gid__gt=2))

多对多操作的一些奇葩方法

remove()

# 删除在关系表中gid=3的这条数据
>>> host.group_set.remove(*models.Group.objects.filter(gid=3))

delete()

# 原始数据和关系表中的数据都删除
>>> host.group_set.all().delete()
# 总影响行数8,在app01.Group内删除了3条,在app01.Group_h2g删除了5条
(8, {‘app01.Group‘: 3, ‘app01.Group_h2g‘: 5})

为了不影响后面的测试,请重新恢复以下数据

models.Group.objects.create(name=‘市场部‘)
models.Group.objects.create(name=‘技术部‘)
models.Group.objects.create(name=‘财务部‘)
models.Group.objects.create(name=‘运维部‘)
models.Group.objects.create(name=‘销售部‘)

set()

如果传入过来的数据在表中没有,那么就添加进来,如果有那么就进行移除
接收一个参数clear,如果clear=true,那么就先全部清除,然后再添加,默认clear=false
>>> host.group_set.set(models.Group.objects.filter(gid=6))

create()

# gid大于8的全部加入进来,相当于add()
>>> host.group_set.add(*models.Group.objects.filter(gid__gt=8))

get_or_create()

# 如果有就获取,没有就添加,元数据也会被添加
>>> host =models.Host.objects.get(ip=‘192.168.1.3‘)
>>> r = host.group_set.get_or_create(name=‘技术部‘)
# 如果没有,返回True,并添加数据
>>> r
(<Group: Group object>, True)
# 已经有了,返回False,不执行任何操作
>>> r = host.group_set.get_or_create(name=‘技术部‘)
>>> r
(<Group: Group object>, False)

update_or_create()

与上述方法一致

自定义第三张表特性

  1. 自定义的第三张表不会创建联合唯一索引,Unique
  2. 在对第三张表操作的时候,只能使用第三张表明进行操作

第三张表添加约束

# 在第三张表内添加下面的类
class Meta:
    unique_together = [
        (‘host_id‘, ‘group_id‘)
    ]

插入一条数据

# 两个外键都会加上_id
>>> models.HostGroup.objects.create(host_id_id=1, group_id_id=1)
<HostGroup: HostGroup object>

#Python全栈之路 #Django

时间: 2024-10-06 10:30:35

5Python全栈之路系列之Django模型续的相关文章

4Python全栈之路系列之Django模型

Python全栈之路系列之Django模型 MTV开发模式 把数据存取逻辑.业务逻辑和表现逻辑组合在一起的概念有时被称为软件架构的Model-View-Controller(MVC)模式.在这个模式中,Model代表数据存取层,View代表的是系统中选择显示什么和怎么显示的部分,Controller指的是系统中根据用户输入并视需要访问模型,以决定使用哪个视图的那部分. Django紧紧地遵循这种MVC模式,可以称得上是一种MVC框架. 以下是Django中M.V和C各自的含义: **M**: 数

1Python全栈之路系列之Django初体验

Python全栈之路系列之Django初体验 Django不得不说在Python中是一个非常强大的全栈框架,而且入门也比较简单,只要你学完了基本的Django知识,接着再做一两个项目,不大不小就成,然后你再去学其它的框架你会发现,在那些小而美的框架中,你学起来将非常的快,因为你在学习Django的时候就已经学习并且体验过了Web开发流程,所以会有这么一个现象出现,有些新手朋友在学习Flask.Tornado等小而美的框架时,很多概念不是很理解,比如ORM.路由等,但你学Django就不会出现这种

7Python全栈之路系列之Django表单

Python全栈之路系列之Django表单 从Request对象中获取数据 HttpRequest对象包含当前请求URL的一些信息: 熟悉/方法 描述 例如 request.path 除域名以外的请求路径 /hello/ request.get_host() 访问的域名 127.0.0.1:8000" or www.example.com request.get_full_path() 请求路径,可能包含查询字符串 /hello/?print=true request.is_secure() 是

2Python全栈之路系列之Django路由与视图

Python全栈之路系列之Django路由与视图 路由说白了就是与视图(函数)的对应关系,怎么说呢,一个路由对应一个视图,比如上面文章中所提到的那样,当打开/users/路径的时候会让users这个函数来进行逻辑处理,把处理的结果再返回到前端. 那么django是怎么知道从哪里找路由的配置文件入口呢?其实这在settings.py文件中已经被定义了: ROOT_URLCONF = 'ansheng.urls' 路由的配置 绝对地址访问 # 访问地址必须是http://127.0.0.1:8000

8Python全栈之路系列之Django Cookie 与Sessi

Python全栈之路系列之Django Cookie与Sessi Cookies cookies是浏览器为Web服务器存储的一小段信息,每次浏览器从某个服务器请求页面时,它向服务器回送之前收到的cookies. 存取Cookies 创建Cookies def set_cookie(request):     # 创建HttpResponse对象     Response = HttpResponse()     # 创建cookie     Response.set_cookie("Cookie

5Python全栈之路系列之字符串格式化

Python全栈之路系列之字符串格式化 This PEP proposes a new system for built-in string formatting operations, intended as a replacement for the existing '%' string formatting operator. Python目前提供的字符串格式化方式有两种: 百分号方式 format方式 这两种方式在Python2和Python3中都适用,百分号方式是Python一直内置

5Python全栈之路系列之IO多路复用

Python全栈之路系列之IO多路复用 What is IO Multiplexing? IO多路复用是指内核一旦发现进程指定的一个或者多个IO条件准备读取,它就通知该进程. 举例说明 你是一名老师(线程),上课了(启动线程),这节课是自习课,学生都在自习,你也在教室里面坐着,只看着这帮学生,什么也不干(休眠状态),课程进行到一半时,A同学(socket)突然拉肚子,举手说:老湿我要上厕所(read),然后你就让他去了,过了一会,B同学(socket)在自习的过程中有个问题不太懂,就请你过去帮她

5Python全栈之路系列之算法

ython全栈之路系列之算法 一个算法的优劣可以用空间复杂度与时间复杂度来衡量. 冒泡排序 冒泡排序(英语:Bubble Sort,台湾另外一种译名为:泡沫排序)是一种简单的排序算法.它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来.走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成.这个算法的名字由来是因为越小的元素会经由交换慢慢"浮"到数列的顶端. from random import randint li = [randint

3Python全栈之路系列之D

Python全栈之路系列之Django模板 模板是一个文本,用于分离文档的表现形式和内容,模板定义了占位符以及各种用于规范文档该如何显示的各部分基本逻辑(模板标签).模板通常用于产生HTML,但是Django的模板也能产生任何基于文本格式的文档. 如何使用模板系统 在Python代码中使用Django模板的最基本方式如下: 可以用原始的模板代码字符串创建一个Template对象,Django同样支持用指定模板文件路径的方式来创建Template对象; 调用模板对象的render方法,并且传入一套