• 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)
    自定义分页功能代码
  • 相关阅读:
    canvas beginPath()的初步理解
    高效取余运算(n-1)&hash原理探讨
    EntityUtils.toString(entity)处理字符集问题解决
    python计算不规则图形面积算法
    VMware与 Device/Credential Guard 不兼容,解决办法及心得
    Java爬取51job保存到MySQL并进行分析
    纯C语言实现循环双向链表创建,插入和删除
    纯C语言实现顺序队列
    纯C语言实现链队
    纯C语言实现链栈
  • 原文地址:https://www.cnblogs.com/mitsui/p/7081029.html
Copyright © 2020-2023  润新知