1. 程式人生 > >5Python全棧之路系列之Django模型續

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


5Python全棧之路系列之Django模型續