Django---models操作

D jango 模型是與數據庫相關的,與數據庫相關的代碼一般寫在 models.py 中,Django 支持 sqlite3, MySQL, PostgreSQL等數據庫,只需要在settings.py中配置即可,不用更改models.py中的代碼,豐富的API極大的方便了使用。

1、數據庫的連接方式以及設置:
在Django中默認使用的數據庫類型是sqlite3,如果想要使用其他數據庫就需要在settings中設置數據庫的連接方式:
# Database
# https://docs.djangoproject.com/en/1.10/ref/settings/#databases

# sqlite3數據庫連接方式
# DATABASES = {
#     ‘default‘: {
#         ‘ENGINE‘: ‘django.db.backends.sqlite3‘,
#         ‘NAME‘: os.path.join(BASE_DIR, ‘db.sqlite3‘),
#     }
# }

# MySQL數據庫連接方式
DATABASES = {
    ‘default‘: {
    ‘ENGINE‘: ‘django.db.backends.mysql‘,
    ‘NAME‘:‘dbname‘,
    ‘USER‘: ‘root‘,
    ‘PASSWORD‘: ‘xxx‘,
    ‘HOST‘: ‘‘,
    ‘PORT‘: ‘‘,
    }
}
2、開始創建表
數據需要在models.py文件中創建
class UserInfo(models.Model):
    # CharField類型不能爲空,最少要指定一個長度
    user = models.CharField(max_length=32)
    email = models.EmailField(max_length=32)
    pwd = models.CharField(max_length=32)
    user_type = models.ForeignKey(‘UserType‘)

class UserType(models.Model):
    nid = models.AutoField(primary_key=True)
    caption = models.CharField(max_length=16)
注:在創建外鍵的時候直接寫上UserType和‘UserType‘的區別就是python程序從上到下解釋的順序問題,如果把UserType這個類寫到下面就會沒事了
運行Djando項目程序,執行命令創建數據:
python3 manage.py makemigrations
python3 manage.py migrate
創建表的的參數:
技術分享
1、models.AutoField  自增列 = int(11)
  如果沒有的話,默認會生成一個名稱爲 id 的列,如果要顯示的自定義一個自增列,必須將給列設置爲主鍵 primary_key=True。
2、models.CharField  字符串字段
  必須 max_length 參數
3、models.BooleanField  布爾類型=tinyint(1)
  不能爲空,Blank=True
4、models.ComaSeparatedIntegerField  用逗號分割的數字=varchar
  繼承CharField,所以必須 max_lenght 參數
5、models.DateField  日期類型 date
  對於參數,auto_now = True 則每次更新都會更新這個時間;auto_now_add 則只是第一次創建添加,之後的更新不再改變。
6、models.DateTimeField  日期類型 datetime
  同DateField的參數
7、models.Decimal  十進制小數類型 = decimal
  必須指定整數位max_digits和小數位decimal_places
8、models.EmailField  字符串類型(正則表達式郵箱) =varchar
  對字符串進行正則表達式
9、models.FloatField  浮點類型 = double
10、models.IntegerField  整形
11、models.BigIntegerField  長整形
  integer_field_ranges = {
    SmallIntegerField: (-32768, 32767),
    IntegerField: (-2147483648, 2147483647),
    BigIntegerField: (-9223372036854775808, 9223372036854775807),
    PositiveSmallIntegerField: (0, 32767),
    PositiveIntegerField: (0, 2147483647),
  }
12、models.IPAddressField  字符串類型(ip4正則表達式)
13、models.GenericIPAddressField  字符串類型(ip4和ip6是可選的)
  參數protocol可以是:both、ipv4、ipv6
  驗證時,會根據設置報錯
14、models.NullBooleanField  允許爲空的布爾類型
15、models.PositiveIntegerFiel  正Integer
16、models.PositiveSmallIntegerField  正smallInteger
17、models.SlugField  減號、下劃線、字母、數字
18、models.SmallIntegerField  數字
  數據庫中的字段有:tinyint、smallint、int、bigint
19、models.TextField  字符串=longtext
20、models.TimeField  時間 HH:MM[:ss[.uuuuuu]]
21、models.URLField  字符串,地址正則表達式
22、models.BinaryField  二進制
23、models.ImageField   圖片
24、models.FilePathField 文件
更多字段
技術分享
1、null=True
  數據庫中字段是否可以爲空
2、blank=True
  django的 Admin 中添加數據時是否可允許空值
3、primary_key = False
  主鍵,對AutoField設置主鍵後,就會代替原來的自增 id 列
4、auto_now 和 auto_now_add
  auto_now   自動創建---無論添加或修改,都是當前操作的時間
  auto_now_add  自動創建---永遠是創建時的時間
5、choices
GENDER_CHOICE = (
        (uM, uMale),
        (uF, uFemale),
    )
gender = models.CharField(max_length=2,choices = GENDER_CHOICE)
6、max_length
7、default  默認值
8、verbose_name  Admin中字段的顯示名稱
9、name|db_column  數據庫中的字段名稱
10、unique=True  不允許重複
11、db_index = True  數據庫索引
12、editable=True  在Admin裏是否可編輯
13、error_messages=None  錯誤提示
14、auto_created=False  自動創建
15、help_text  在Admin中提示幫助信息
16、validators=[]
17、upload-to
更多參數
執行成功狀態:
技術分享
 1 bogon:django_modes01 zk$ python3 manage.py makemigrations
 2 Migrations for app01:
 3   app01/migrations/0001_initial.py:
 4     - Create model UserInfo
 5     - Create model UserType
 6     - Add field user_type to userinfo
 7 bogon:django_modes01 zk$ python3 manage.py migrate
 8 Operations to perform:
 9   Apply all migrations: admin, app01, auth, contenttypes, sessions
10 Running migrations:
11   Rendering model states... DONE
12   Applying contenttypes.0001_initial... OK
13   Applying auth.0001_initial... OK
14   Applying admin.0001_initial... OK
15   Applying admin.0002_logentry_remove_auto_add... OK
16   Applying app01.0001_initial... OK
17   Applying contenttypes.0002_remove_content_type_name... OK
18   Applying auth.0002_alter_permission_name_max_length... OK
19   Applying auth.0003_alter_user_email_max_length... OK
20   Applying auth.0004_alter_user_username_opts... OK
21   Applying auth.0005_alter_user_last_login_null... OK
22   Applying auth.0006_require_contenttypes_0002... OK
23   Applying auth.0007_alter_validators_add_error_messages... OK
24   Applying auth.0008_alter_user_username_max_length... OK
25   Applying sessions.0001_initial... OK
狀態

 

如果提示:No changes detected
需要在settings.py的配置文件檢測一下有沒有註冊app

技術分享

 在MySQL中就可以看到生成的表:

技術分享

 外鍵關係:

技術分享

3.開始創建數據

創建數據的時候有兩種方式:

第一種方式:

obj = models.表名(字段名=‘***‘)
obj.save()

第二種方式:

models.表名.objects.create(字段名=‘***‘)

在views.py中寫入數據:

from django.shortcuts import render,HttpResponse
from app01 import models

# Create your views here.

def index(request):
    # 創建用戶類型表
    models.UserType.objects.create(caption=‘管路員‘)
    models.UserType.objects.create(caption=‘普通用戶‘)
    models.UserType.objects.create(caption=‘超級管理員‘)

    # 創建用戶信息表
    user_info_dict_1 = {‘user‘: ‘ales‘,
                      ‘email‘: ‘[email protected]‘,
                      ‘pwd‘: 123,
                      ‘user_type‘: models.UserType.objects.get(nid=1),
                      }

    user_info_dict_2 = {‘user‘: ‘eric‘,
                      ‘email‘: ‘[email protected]‘,
                      ‘pwd‘: 123,
                      ‘user_type_id‘: 2,
                      }

    models.UserInfo.objects.create(**user_info_dict_1)
    models.UserInfo.objects.create(**user_info_dict_2)
    print(‘yes‘)

    return HttpResponse(‘ok‘)

運行Django 項目訪問指定文件創建數據:

技術分享

技術分享

4、了不起的雙下劃線之外鍵正向查找和基本操作

技術分享
 1     #
 2     #
 3     # models.Tb1.objects.create(c1=‘xx‘, c2=‘oo‘)  增加一條數據,可以接受字典類型數據 **kwargs
 4 
 5     # obj = models.Tb1(c1=‘xx‘, c2=‘oo‘)
 6     # obj.save()
 7 
 8     #
 9     #
10     # models.Tb1.objects.get(id=123)         # 獲取單條數據,不存在則報錯(不建議)
11     # models.Tb1.objects.all()               # 獲取全部
12     # models.Tb1.objects.filter(name=‘seven‘) # 獲取指定條件的數據
13 
14     #
15     #
16     # models.Tb1.objects.filter(name=‘seven‘).delete() # 刪除指定條件的數據
17 
18     #
19     # models.Tb1.objects.filter(name=‘seven‘).update(gender=‘0‘)  # 將指定條件的數據更新,均支持 **kwargs
20     # obj = models.Tb1.objects.get(id=1)
21     # obj.c1 = ‘111‘
22     # obj.save()                                                 # 修改單條數據
基本操作

 

技術分享
 1 # 獲取個數
 2     #
 3     # models.Tb1.objects.filter(name=‘seven‘).count()
 4 
 5     # 大於,小於
 6     #
 7     # models.Tb1.objects.filter(id__gt=1)              # 獲取id大於1的值
 8     # models.Tb1.objects.filter(id__lt=10)             # 獲取id小於10的值
 9     # models.Tb1.objects.filter(id__lt=10, id__gt=1)   # 獲取id大於1 且 小於10的值
10 
11     # in
12     #
13     # models.Tb1.objects.filter(id__in=[11, 22, 33])   # 獲取id等於11、22、33的數據
14     # models.Tb1.objects.exclude(id__in=[11, 22, 33])  # not in
15 
16     # contains
17     #
18     # models.Tb1.objects.filter(name__contains="ven")
19     # models.Tb1.objects.filter(name__icontains="ven") # icontains大小寫不敏感
20     # models.Tb1.objects.exclude(name__icontains="ven")
21 
22     # range
23     #
24     # models.Tb1.objects.filter(id__range=[1, 2])   # 範圍bettwen and
25 
26     # 其他類似
27     #
28     # startswith,istartswith, endswith, iendswith,
29 
30     # order by
31     #
32     # models.Tb1.objects.filter(name=‘seven‘).order_by(‘id‘)    # asc
33     # models.Tb1.objects.filter(name=‘seven‘).order_by(‘-id‘)   # desc
34 
35     # limit 、offset
36     #
37     # models.Tb1.objects.all()[10:20]
38 
39     # group by
40     from django.db.models import Count, Min, Max, Sum
41     # models.Tb1.objects.filter(c1=1).values(‘id‘).annotate(c=Count(‘num‘))
42     # SELECT "app01_tb1"."id", COUNT("app01_tb1"."num") AS "c" FROM "app01_tb1" WHERE "app01_tb1"."c1" = 1 GROUP BY "app01_tb1"."id"
進階操作(雙下劃線) 
  •  查

單表查詢:

# ret = models.UserType.objects.all()
# print(ret.query)    
# ret.query後臺返回的是查詢的sql語句

  結果:

SELECT `app01_usertype`.`nid`, `app01_usertype`.`caption` FROM `app01_usertype`

  獲取查詢結果的類型:

ret = models.UserType.objects.all()
print(type(ret), ret)

  結果:

<class ‘django.db.models.query.QuerySet‘> <QuerySet [<UserType: UserType object>, <UserType: UserType object>, <UserType: UserType object>]>

  可以看到類型是一個QuerySet類型,後面是所有的對象,每一個元素就是一個對象,可以循環拿出每一次的數據:

ret = models.UserType.objects.all()
    print(type(ret), ret)

    for item in ret:
        print(item)

  其結果就是每一次循環出來的結果的對象:

UserType object
UserType object
UserType object

  每一個對象都代表一個數據,要出去這些數據如下:

ret = models.UserType.objects.all()
    print(type(ret), ret)

    for item in ret:
        print(item, item.nid, item.caption)

  取出的結果:

UserType object 1 管路員
UserType object 2 普通用戶
UserType object 3 超級管理員

    從結果看出每次輸出item的時候都是一個對象(一行數據中所有的對象,對象中封裝了所有的數據),在modes中有__str__方法(返回什麼,就輸出什麼,就是查看方便), 在python2.7中叫__unicode__如果在UserType這個類裏面使用這個方法:

class UserType(models.Model):
    nid = models.AutoField(primary_key=True)
    caption = models.CharField(max_length=16)

    def __str__(self):
        return ‘%s-%s‘ % (self.nid, self.caption)

  然後重新訪問下:

1-管路員 1 管路員
2-普通用戶 2 普通用戶
3-超級管理員 3 超級管理員

  就可以看到每一個對象都看到了返回的相對應的參數了。

  查詢單個字段:

ret = models.UserType.objects.all().values(‘nid‘)
    print(type(ret), ret)

  結果查詢出nid字段對應的所有的數據 :

<class ‘django.db.models.query.QuerySet‘> <QuerySet [{‘nid‘: 1}, {‘nid‘: 2}, {‘nid‘: 3}]>

  可以看查詢的sql語句,用query方法:

ret = models.UserType.objects.all().values(‘nid‘)
print(type(ret), ret.query)

  查詢的結果:

<class ‘django.db.models.query.QuerySet‘> SELECT `app01_usertype`.`nid` FROM `app01_usertype`

  當通過values循環取值的時候,如下:

ret = models.UserType.objects.all().values(‘nid‘)
    print(type(ret), ret.query)
    for item in ret:
        print(item, type(item))

  結果:

<class ‘django.db.models.query.QuerySet‘> SELECT `app01_usertype`.`nid` FROM `app01_usertype`
{‘nid‘: 1} <class ‘dict‘>
{‘nid‘: 2} <class ‘dict‘>
{‘nid‘: 3} <class ‘dict‘>

  通過結果可以看出,最外部是QuerySet,內部元素封裝了一個是封裝了這一行所有數據的對象,另外只拿到了某幾列的字典!

  當通過values_list循環取值的時候,如下:

ret = models.UserType.objects.all().values_list(‘nid‘)
    print(type(ret), ret)

  查詢結果:

<class ‘django.db.models.query.QuerySet‘> <QuerySet [(1,), (2,), (3,)]>

  依然是queryset,但是結果就是列表中包含的元組,values和values_list的區別就是:values取的是字典類型,values_list把內部元素變成元組了。通過for循環更直觀,如下:

ret = models.UserType.objects.all().values_list(‘nid‘)
    print(type(ret), ret)
    for item in ret:
        print(type(item), item)

  結果:

<class ‘django.db.models.query.QuerySet‘> <QuerySet [(1,), (2,), (3,)]>
<class ‘tuple‘> (1,)
<class ‘tuple‘> (2,)
<class ‘tuple‘> (3,)

連表查詢:

連表查詢的時候和sqlachemy有多不同,django沒有join這個方法:

  通過UserInfo做連表查詢

ret = models.UserInfo.objects.all()
    print(type(ret), ret)
    for item in ret:
        print(item, item.user_type, item.id, item.email, item.user, item.pwd)

  查詢結果:

<class ‘django.db.models.query.QuerySet‘> <QuerySet [<UserInfo: UserInfo object>, <UserInfo: UserInfo object>]>
UserInfo object UserType object 1 [email protected] ales 123
UserInfo object UserType object 2 [email protected] eric 123

  首先輸出的是查找出來的UserInfo用戶信息表,封裝了用戶所有的信息,而UserType就是一個對象,這個對象裏封裝的就是一行信息對應的字段(nid和caption),取出UserType對應的信息,例如:

ret = models.UserInfo.objects.all()
print(type(ret), ret)
for item in ret:
        print(item, item.user_type, item.id, item.email, item.user, item.pwd)
        print(item.user_type.nid, item.user_type.caption)

  取出的UserType對應的信息結果:

<class ‘django.db.models.query.QuerySet‘> <QuerySet [<UserInfo: UserInfo object>, <UserInfo: UserInfo object>]>
UserInfo object UserType object 1 [email protected] ales 123
UserInfo object UserType object 2 [email protected] eric 123
1 管路員
2 普通用戶

  可以直接取出對應外鍵的那一列user_type_id:

    ret = models.UserInfo.objects.all()
    print(type(ret), ret)
    for item in ret:
        print(item, item.user_type, item.id, item.email, item.user, item.pwd)

print(item.user_type.nid, item.user_type.caption, item.user_type_id)

 結果:

<class ‘django.db.models.query.QuerySet‘> <QuerySet [<UserInfo: UserInfo object>, <UserInfo: UserInfo object>]>
UserInfo object UserType object 1 [email protected] ales 123
1 管路員 1
UserInfo object UserType object 2 [email protected] eric 123
2 普通用戶 2

  如果只想看到數據對應的名稱,就需要加映射values:

    ret = models.UserInfo.objects.all().values(‘user‘, ‘user_type__caption‘)
    print(ret, ret.query)
 

  結果:

<QuerySet [{‘user‘: ‘ales‘, ‘user_type__caption‘: ‘管路員‘}, {‘user‘: ‘eric‘, ‘user_type__caption‘: ‘普通用戶‘}]> SELECT `app01_userinfo`.`user`, `app01_usertype`.`caption` FROM `app01_userinfo` INNER JOIN `app01_usertype` ON (`app01_userinfo`.`user_type_id` = `app01_usertype`.`nid`)

  通過結果可以看到user_type__caption可以跨表直接獲取相應的結果,再看sql語句中django本身加上了一個join。

  如果在models中在加上一個表"P",然後在UserType中增加一條外鍵指向"平"P",需求:要查找UserInfo表中的name和UserType表中的caption和P表中的neme的方法就是在找下一個對象的時候繼續加雙下劃線:

  增加的表結構:

技術分享

  查詢語法:

ret = models.UserInfo.objects.all().values(‘user‘, ‘user_type__caption‘, ‘user_type__p__name‘)
print(ret, ret.query)

  查詢的結果:

<QuerySet [{‘user_type__p__name‘: ‘allan‘, ‘user_type__caption‘: ‘管路員‘, ‘user‘: ‘ales‘}, {‘user_type__p__name‘: ‘allan‘, ‘user_type__caption‘: ‘普通用戶‘, ‘user‘: ‘eric‘}]> SELECT `app01_userinfo`.`user`, `app01_usertype`.`caption`, `app01_p`.`name` FROM `app01_userinfo` INNER JOIN `app01_usertype` ON (`app01_userinfo`.`user_type_id` = `app01_usertype`.`nid`) INNER JOIN `app01_p` ON (`app01_usertype`.`p_id` = `app01_p`.`id`)

  如果要拿用戶類型是管理員的所有用戶:

ret = models.UserInfo.objects.filter(user_type__caption="管路員").values(‘user‘, ‘user_type__caption‘)
    print(ret)

  結果:

<QuerySet [{‘user‘: ‘ales‘, ‘user_type__caption‘: ‘管路員‘}]>

5、了不起的上下劃線值外鍵反向查找

  找到管理員相關聯的信息:

obj = models.UserType.objects.filter(caption=‘管理員‘).first()
print(obj.nid, obj.caption)

  輸出結果:

1 管理員

  這裏查找的是usertype中的數據,如果通過usertype表查找到userinfo表中的信息就得用***_set:

    obj = models.UserType.objects.filter(caption=‘管理員‘).first()
    print(obj.nid, obj.caption)
    print(obj.userinfo_set.all())

    ret = models.UserType.objects.all().values(‘nid‘, ‘caption‘, ‘userinfo__user‘)
    print(ret)

  查詢結果:

1 管理員
<QuerySet [<UserInfo: UserInfo object>]>
<QuerySet [{‘caption‘: ‘管理員‘, ‘userinfo__user‘: ‘alex‘, ‘nid‘: 1}, {‘caption‘: ‘普通用戶‘, ‘userinfo__user‘: ‘eric‘, ‘nid‘: 2}, {‘caption‘: ‘超級管理員‘, ‘userinfo__user‘: None, ‘nid‘: 3}]>
[27/Aug/2016 15:35:31] "GET /index/ HTTP/1.1" 200 2

  如果需要固定字段查找:

obj = models.UserType.objects.all().values(‘nid‘, ‘userinfo__user‘)
    print(obj)

  結果:

<QuerySet [{‘userinfo__user‘: ‘alex‘, ‘nid‘: 1}, {‘userinfo__user‘: ‘eric‘, ‘nid‘: 2}, {‘userinfo__user‘: None, ‘nid‘: 3}]>

6、多對多之表創建

  多對多創建表的時候直接使用ManyToManyField讓django自動創建第三張表或者自己手動創建第三張表,第三張表如果指定多個字段的hu

models表結構(自定義的第三張表):

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=‘HostToGroup‘)

class HostToGroup(models.Model):
    hgid = models.AutoField(primary_key=True)
    host_id = models.ForeignKey(‘Host‘)
    group_id = models.ForeignKey(‘Group‘)
    status = models.IntegerField()

  插入數據:

    models.Host.objects.create(hostname=‘c1‘, ip=‘1.1.1.1‘)
    models.Host.objects.create(hostname=‘c2‘, ip=‘1.1.1.2‘)
    models.Host.objects.create(hostname=‘c3‘, ip=‘1.1.1.3‘)
    models.Host.objects.create(hostname=‘c4‘, ip=‘1.1.1.4‘)
    models.Host.objects.create(hostname=‘c5‘, ip=‘1.1.1.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=‘運營部‘)
    models.Group.objects.create(name=‘銷售部‘)
    models.Group.objects.create(name=‘客服部‘)

  技術分享技術分享

  操作表:

  獲取財務部的對象:

    obj = models.Group.objects.get(gid=2)
    print(obj.gid, obj.name, obj.h2g.all())

  結果:

2 財務部 <QuerySet []>

  給財務部添加主機:

   # 添加一臺主機       
   obj = models.Group.objects.get(gid=2)
    # print(obj.gid, obj.name, obj.h2g.all())
    h1 = models.Host.objects.get(hid=1)
    obj.h2g.add(h1)

技術分享

   # 把剩下的全部添加 
   obj = models.Group.objects.get(gid=2)
    # print(obj.gid, obj.name, obj.h2g.all())
    # h1 = models.Host.objects.get(hid=1)
    q = models.Host.objects.filter(hid__gt=1)
    obj.h2g.add(*q)

 技術分享

將一臺機器分配給多個組(就得用反向操作了):

    h = models.Host.objects.get(hid=1)
    h.group_set.add(*models.Group.objects.filter(gid__gt=2))

  技術分享

  操作自己手動創建的第三張關係表:

  表結構:

技術分享

  表的數據還是原來的數據。

  創建表之間的關係,需要自己手動創建關係:

models.HostToGroup.objects.create(status=1, group_id_id=2, host_id_id=3)

  技術分享 

 


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章