Django操作之ORM與自定制分頁


一.創建表

Django自帶數據庫ORM是基於SQLite,如果使用sqlite則不需要做配置修改,如果需要基於mysql連接則需要做相關配置:

1.在安裝好的mysql中創建數據庫,注意字符集選擇utf8以便支持漢字(ORM不支持創建數據庫,只能創建表)

2.在創建的Django項目同名文件夾中 setting.py 配置對於mysql數據庫的連接:

 1 # 1.將默認的設置注釋掉:
 2 # DATABASES = {
 3 #     'default': {
 4 #         'ENGINE': 'django.db.backends.sqlite3',
 5 #         'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
 6 #     }
 7 # }
 8 
 9 # 2.設置對於mysql的連接:
10 DATABASES = {
11     'default': {
12         'ENGINE': 'django.db.backends.mysql',  
13         'NAME':'new',    #數據庫名稱
14         'USER': 'root',  #用戶名
15         'PASSWORD': 'pwd',   #密碼
16         'HOST': 'localhost',      #連接地址,可以不填
17         'PORT': 3306,    #端口
18     }
19 }    

3.在同層目錄下的__init__.py文件導入對應模塊:

 import pymysql 

 pymysql.install_as_MySQLdb() 

此時基本配置已經完成,接下來進入處理業務代碼的app01文件夾下的models.py中進行對ORM的建表操作

 1 from django.db import models #導入django ORM對應模塊
 2 
 3 # Create your models here.
 4 class Class1(models.Model):  #繼承models模塊定制類,即創建表,類名為表明
 5     cid = models.AutoField(primary_key=True)    #創建主鍵,AutoField為自增(主鍵可以不寫,不寫時默認生成一行名稱為ID的主鍵列)
 6     cname = models.CharField(max_length=32)     #創建char類型字符串,最大長度32
 7     
 8 class Teacher(models.Model):
 9     tid = models.AutoField(primary_key=True)
10     tname = models.CharField(max_length=32)
11 
12 class Student(models.Model):
13     sid = models.AutoField(primary_key=True) 
14     sname = models.CharField(max_length=32)
15     Class = models.ForeignKey(Class1)  #創建外鍵,括號里面填寫外鍵關系的表名 這個類在生成時,Class列會顯示為Class_id即自寫的列名加_id 
16 
17 class Guanxi(models.Model):
18     teacher = models.ForeignKey(Teacher)
19     Class = models.ForeignKey(Class1)
基於ORM類形式創建表

當類表定制完畢時,cmd切換到Django項目的根目錄,運行命令:(注意將python添加至環境變量)

 python manage.py makemigrations  

 python manage.py migrate 

此時數據表即完成創建成功,如有報錯,注意查看某個字段是否類型錯誤,檢查之前步驟是否有遺漏。

如果是用的sqlite創建,可以用pycharm自帶的可視化以及Django的sqlite結合查看表。(將項目中的sqlite3拖拽到pycharm編輯器右上角點開的Database中)

 

二:基於ORM對表進行增刪改查:

本次操作在views模塊中,因此首先導入之前創建的表類

from app01 import models

 1 查:
 2 res = models.UserType.objects.all() #獲取表所有數據,得到一個QuerySet[obj,obj,obj],類似一個個對象組成的列表,循環列表取到的為對象,擁有表的字段屬性。
 3 for row in res:
 4     print(row.cid,row.cname)
 5 
 6 res = models.UserType.objects.all() .first() #獲取表所有數據的第一行,實際為一個Obj對象,可以res.cid,res.cname取值
 7 
 8 res = models.UserType.objects.filter(cid=1) 
 9 res = models.UserInfo.objects.filter(id__gt=1) id大於1
10 res = models.UserInfo.objects.filter(id__lt=1) id小於1
11 #filter查詢時,括號里面可以添加條件,得到的依然為QuerySet,需要取值依舊需要for 循環 或者后面加.first()方法,當然也可以按索引取值,得到的也是obj對象
12 
13 res = models.UserInfo.objects.all().values('id','name') #實際還是QuerySet,括號里面可以限定需要查詢的列,不同的是,這里循環出來的不再是對象,而是一個個的字典 QuerySet[{'id':'xx','name':'xx'} ] 取值需按字典key取值。
14 # 跨表  __
15     # result = models.UserInfo.objects.all().values('id','name',"ut__title")
16     # for item in result:
17     #     print(item['id'],item['name'],item['ut__title'])
18 
19 
20 res = models.UserInfo.objects.all().values_list('id','name') #得到QuerySet[(1,'f'), ] 循環出來的還是一個個的列表,列表索引取值。
21 
22 # 跨表  __
23     # result = models.UserInfo.objects.all().values_list('id','name',"ut__title")
24     # for item in result:
25     #     print(item[0],item[1],item[2])
26 
27 
28 
29 增:
30 #增加為create(),括號里面填寫數據行需要的各個數據即可
31    models.UserType.objects.create(title='普通用戶')
32 
33 
34 
35 刪:
36 #刪除需在查詢到數據的基礎上,后面加上.delete()方法即可
37 models.UserInfo.objects.filter(id=1).delete()
38 
39 
40 改:
41 #對應的,修改也是在查詢的基礎上,加.update()方法
42 models.Student.objects.filter(sid=a1).update(sname=name,Class_id=cid)
43 
44 #外鍵操作:以下操作基於2個表已經建立外鍵關系的基礎
45 ##正向操作:
46 # UserInfo,ut是FK字段 - 正向操作  PS: 一個用戶只有一個用戶類型
47 obj = models.UserInfo.objects.all().first()
48 print(obj.name,obj.age,obj.ut.title)  
49 #通過.外鍵名.對應關系表的字段列名即可拿到UserType表里面的title列值
50 #同樣的如果有多個關系表連表操作時,可以一直.外鍵無窮無盡的連表取到需要的值
51 
52 #反向操作:
53 # UserType, 表名小寫_set.all()  - 反向操作   PS: 一個用戶類型下可以有很多用戶
54 obj = models.UserType.objects.all().first() #取到用戶類型的其中一個Obj
55 print('用戶類型',obj.id,obj.title)
56 #通過用戶類型查看該類型下有多少個用戶
57  for row in obj.userinfo_set.all():  
58      print(row.name,row.age)
59 
60 
61 result = models.UserType.objects.all()
62     for item in result:
63         print(item.title,item.userinfo_set.filter(name='xx'))
Django ORM操作表

 

 1 有三個表:
 2 class Boy(models.Model):
 3     name = models.CharField(max_length=32)
 4 
 5 class Girl(models.Model):
 6     nick = models.CharField(max_length=32)
 7 
 8 class Love(models.Model):
 9     b = models.ForeignKey('Boy',null=True)
10     g = models.ForeignKey('Girl',null=True)
11     #聯合唯一索引
12     #class Meta:
13       #  unique_together = [
14         #    ('b','g'),
15         #]
16 
17 1.通過Boy表中name為條件查找Girl表有關聯的nick值:
18 插數據:
19 # obj_list = [
20     #     models.Boy(name='劉德華'),
21     #     models.Boy(name='張學友'),
22     #     models.Boy(name='郭富城'),
23     #     models.Boy(name='黎明'),
24     # ]
25     # objs = [
26     #     models.Girl(nick='陳慧琳'),
27     #     models.Girl(nick='容祖兒'),
28     #     models.Girl(nick='鄭秀文'),
29     #     models.Girl(nick='蒙嘉慧'),
30     #     ]
31     # models.Boy.objects.bulk_create(obj_list,5)
32     # models.Girl.objects.bulk_create(objs,5)
33 建立關系
34     # models.Love.objects.create(b_id=1,g_id=1)
35     # models.Love.objects.create(b_id=1,g_id=4)
36     # models.Love.objects.create(b_id=2,g_id=2)
37     # models.Love.objects.create(b_id=2,g_id=3)
38     # models.Love.objects.create(b_id=2,g_id=4)
39 多對多的關系查詢:
40     # lo_list = models.Love.objects.filter(b__name='劉德華').values('b__name','g__nick')
41     # for i in lo_list:
42     #     print(i['b__name'],i['g__nick'])
43     #
44     # lov_list = models.Love.objects.filter(b__name='張學友').select_related('b','g')
45     # for row in lov_list:
46     #     print(row.b.name,row.g.nick)
47 
48 二。兩個表的關系也可以不再建關系表Love,通過Django內置ORM的功能同樣可以建立表之間的關系,查找時通過間接查找。
49 class Boy(models.Model):
50     name = models.CharField(max_length=32)
51     m = models.ManyToManyField('Girl')
52 
53 class Girl(models.Model):
54     nick = models.CharField(max_length=32)
55 
56 如此,同樣可以建立關系,只不過增刪改查相應也有變化。
57 
58 obj = models.Boy.objects.filter(name='劉德華').first()  #取到篩選出的Boy對象:
59     #
60     obj.m.add(1)
61     obj.m.add(*[2,3,])
62 
63     # 刪:
64     obj.m.remove(1,)
65     obj.m.remove(*[2,])
66 
67     #
68     obj.m.set([1,2,])  #實為重置,將之前的全部刪除重新建立關系
69 
70     #
71     q = obj.m.all()  #q得到對應關系的Girl對象
ORM表多對多操作

 

三.Django之自定義分頁

 由於Django自帶分頁具有局限性,且其它框架都不包含分頁功能,因此這里自定義一個分頁功能模塊。

 1 # Create your views here.
 2 #定制分頁類:
 3 class PageInfo(object):
 4     def __init__(self,current_page,all_count,per_page,base_url,show_page=11):
 5         """
 6 
 7                 :param current_page:當前頁
 8                 :param all_count: 數據庫總行數
 9                 :param per_page: 每頁顯示行數
10                 :param base_url: 需要分頁的url
11                 :param show_page: 頁面可以顯示的頁數
12                 :return:
13          """
14         """將傳入的當前頁轉為int 如果傳入的為字符串,拋出異常直接
15         將當前頁設置為第一頁"""
16         try:
17             self.current_page = int(current_page)
18         except Exception as e:
19             self.current_page = 1
20 
21         self.per_page = per_page
22         """通過數據庫所有數據的行數除以每頁顯示的行數,得到需要一共
23         顯示的頁數,如果有余數則商要+1,余下的行單獨一頁"""
24         a,b = divmod(all_count,per_page)
25         if b:
26             a = a+1
27         self.all_pager = a
28         self.show_page = show_page
29         self.base_url = base_url
30 
31     """通過當前頁碼以及頁面顯示行數來獲取頁面上顯示的具體行的數據
32     如第1頁就是1-10行,第2頁為11-20行,"""
33     def start(self):
34         return (self.current_page-1) * self.per_page
35     def end(self):
36         return self.current_page * self.per_page
37 
38     """實際執行函數"""
39     def pager(self):
40 
41         page_list = []
42         #如果頁面上顯示11頁,樣式應該是當前頁前面一半后面一半,所以-1然后/2
43         half = int((self.show_page-1)/2)
44         # 如果數據總頁數<11 show_page,即不足11頁,就只顯示數據一共能顯示的頁數
45         if self.all_pager < self.show_page:
46             begin = 1
47             stop = self.all_pager
48         # :param begin:當前頁面顯示的最左頁,即第一頁
49         # :param stop: 當前顯示的最右,即最后一頁
50         else:
51             # 如果當前頁 <=5,永遠顯示1,11
52             if self.current_page <= half:
53                 begin = 1
54                 stop =self.show_page
55             else:
56                 # 如果當前頁+5 大於實際存在的最大頁,比如一共有35頁,當前頁為
57                 # 32,再取后5頁就是37,則36、37為空,所以加個判定,超過極限就
58                 # 取最右頁為實際最大頁,最左就是-11,即還是一共顯示11頁,
59                 if self.current_page + half > self.all_pager:
60                     begin = self.all_pager - self.show_page + 1
61                     stop = self.all_pager
62                 else:
63                     #這里為正常情況,顯示當前頁的前5頁跟后5頁
64                     begin = self.current_page-half
65                     stop = self.current_page + half 
66 
67         #上一頁功能    
68         #當前頁小於等於1,上一頁沒有內容
69         if self.current_page <= 1:
70             prev = "<li><a href='#'>上一頁</a></li>"
71         #拼接字符串生成li a標簽 上一頁頁數為當前頁-1,添加到列表中    
72         else:
73             prev = "<li><a href='%s?page=%s'>上一頁</a></li>" %(self.base_url,self.current_page-1,)
74         page_list.append(prev)
75         
76         #當前頁面同時顯示的頁面,由上面賦值的最左與最右頁決定,+1是因為for循環range不顧尾
77         for i in range(begin,stop+1):
78             if i == self.current_page:
79                 # 當前頁給一個class,CSS顯示效果區別於其它頁
80                 temp = "<li class='active'><a  href='%s?page=%s'>%s</a></li>" % (self.base_url, i, i,)
81             else:
82                 temp = "<li><a href='%s?page=%s'>%s</a></li>" % (self.base_url, i, i,)
83             page_list.append(temp)    
84         
85         #下一頁功能,同樣的當前頁>=最大頁一樣不跳轉    
86         if self.current_page >= self.all_pager:
87             nex = "<li><a href='#'>下一頁</a></li>"
88         else:
89             nex = "<li><a href='%s?page=%s'>下一頁</a></li>" % (self.base_url, self.current_page + 1,)
90         page_list.append(nex)
91         #此時列表中按順序含有上一頁的li a標簽,需要顯示的11頁li a標簽,以及下一頁標簽
92         #拼接成字符串並作為函數的返回值以供調用接收
93         return ''.join(page_list)
自定義分頁功能代碼

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM