Django框架中模型的配置与数据库的操作

版权声明:长安白猫 https://blog.csdn.net/weixin_44074810/article/details/90815330

ORM
表------->类
字段----->属性

模型

重点:、

  1. 模型配置
  2. 数据的增删改
    1. 增:book = BookInfo() book.save() 和 BookInfo.objects.create()
    2. 删:book.delete() 和 BookInfo.objects.get().delete()
    3. 改:book.name=‘xxx’ book.save() 和 BookInfo.object.get().update(name=xxx)
      3.数据的查询
    4. 基础查询
    5. F对象和Q对象
    6. 关联对象
    7. 查询集QuerySet

一、项目准备

  1. 创建项目
    django-admin startproject bookmanager

  2. 创建应用
    python manager.py startapp book

  3. 更换python解释器:按需选择
    查看路径:which python

  4. 添加子应用
    在INSTALLED_APPS中添加子应用

  5. 本地化
    更改语言,时区
    #设置中文
    LANGUAGE_CODE = ‘zh-Hans’
    #亚洲上海时区
    TIME_ZONE = ‘Asia/Shanghai’

  6. 模板路径
    在应用同级目录下,创建templates模板文件夹
    在TEMPLATES 中 DIRS 中写入你的templates路径
    [os.path.join(BASE_DIR,‘templates’)],

  7. 项目中匹配urls
    正则 : 路径只要不是admin/就算匹配成功。并包含到应用中的urls.py
    url(r’^’,include(‘book.urls’))

  8. 应用中匹配urls.py
    应用中创建 urls.py
    正则 : 路径中包含booklist/,就调用视图中对应的bookList函数
    from django.conf.urls import url
    from book.views import bookList(

urlpatterns = [

# 匹配书籍列表信息的URL,调用对应的bookList视图
url(r'^booklist/$',bookList)

]

  1. 准备视图
    定义视图:提供书籍列表信息
    def bookList(request):

    return HttpResponse(‘OK!’)

10.开启服务器, 测试项目
进入项目文件中, 开启项目对应的服务器
python manage.py runserver
点击网址查看

二、配置
在settings.py中保存了数据库的连接配置信息,Django默认初始配置使用sqlite数据库

1. 使用MySQL数据库首先需要安装驱动程序
pip install PyMySQL

2. 在Django的 工程 同名子目录的  __init__.py  文件中添加如下语句
import pymysql
pymysql.install_as_MySQLdb()

3. 修改DATABASES配置信息
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'HOST': '127.0.0.1',  # 数据库主机
        'PORT': 3306,  # 数据库端口
        'USER': 'root',  # 数据库用户名
        'PASSWORD': 'mysql',  # 数据库用户密码
        'NAME': 'book'  # 数据库名字
    }
}

4. 在MySQL中创建数据库
create database book charset=utf8;

三、定义模型类
模型类被定义在"应用/models.py"文件中。
模型类必须继承自Model类,位于包django.db.models中。

接下来首先以"图书-人物"管理为例进行演示。

1 定义

在models.py 文件中定义模型类。

from django.db import models

# Create your models here.
# 准备书籍列表信息的模型类
class BookInfo(models.Model):
    # 创建字段,字段类型...
    name = models.CharField(max_length=20, verbose_name='名称')
    pub_date = models.DateField(verbose_name='发布日期',null=True)
    readcount = models.IntegerField(default=0, verbose_name='阅读量')
    commentcount = models.IntegerField(default=0, verbose_name='评论量')
    is_delete = models.BooleanField(default=False, verbose_name='逻辑删除')

    class Meta:
        db_table = 'bookinfo'  # 指明数据库表名
        verbose_name = '图书'  # 在admin站点中显示的名称

    def __str__(self):
        """定义每个数据对象的显示信息"""
        return self.name

# 准备人物列表信息的模型类
class PeopleInfo(models.Model):
    GENDER_CHOICES = (
        (0, 'male'),
        (1, 'female')
    )
    name = models.CharField(max_length=20, verbose_name='名称')
    gender = models.SmallIntegerField(choices=GENDER_CHOICES, default=0, verbose_name='性别')
    description = models.CharField(max_length=200, null=True, verbose_name='描述信息')
    book = models.ForeignKey(BookInfo, on_delete=models.CASCADE, verbose_name='图书')  # 外键
    is_delete = models.BooleanField(default=False, verbose_name='逻辑删除')

    class Meta:
        db_table = 'peopleinfo'
        verbose_name = '人物信息'

    def __str__(self):
        return self.name

1) 数据库表名
模型类如果未指明表名,Django默认以小写app应用名_小写模型类名为数据库表名。
可通过db_table指明数据库表名。

2) 关于主键
jango会为表创建自动增长的主键列,每个模型只能有一个主键列,
如果使用选项设置某属性为主键列后django不会再创建自动增长的主键列。
默认创建的主键列属性为id,可以使用pk代替,pk全拼为primary key。

3) 属性命名限制
不能是python的保留关键字。
不允许使用连续的下划线,这是由django的查询方式决定的。
定义属性时需要指定字段类型,通过字段类型的参数指定选项,语法如下:
属性=models.字段类型(选项)

Charfiled 必须设置max_length

verbose_name 主要是admin后台显示

4) 外键
在设置外键时,需要通过on_delete选项指明主表删除数据时,
对于外键引用表数据如何处理,在django.db.models中包含了可选常量

  1. CASCADE级联,删除主表数据时连通一起删除外键表中数据

  2. PROTECT保护,通过抛出ProtectedError异常,来阻止删除主表中被外键应用的数据

  3. SET_NULL设置为NULL,仅在该字段null=True允许为null时可用

  4. SET_DEFAULT设置为默认值,仅在该字段设置了默认值时可用

  5. SET()设置为特定值或者调用特定方法

  6. DO_NOTHING不做任何操作,如果数据库前置指明级联性,此选项会抛出IntegrityError异常

2 迁移

将模型类同步到数据库中。

1)生成迁移文件
python manage.py makemigrations

2)同步到数据库中
python manage.py migrate

3 添加数据

在MySQL数据库中添加数据

四、shell工具

shell工具
Django的manage工具提供了shell命令,帮助我们配置好当前工程的运行环境(如连接好数据库等),
以便可以直接在终端中执行测试python语句。

  1. 通过如下命令进入shell
    python manage.py shell

  2. 进入shell后导入你所键的模型类

例:from book.models import BookInfo,PeopleInfo

五、数据库的操作 增、删 、改

1 增加
增加数据有两种方法。

from boook.models import BookInfo

# 方式1 
# 需要手动调用 save() -----> book.save()
book = BookInfo(
    name='python',
    pub_data='2019-06-03'
)
book.save()

# 方式2 直接入库  create -----> 通过模型类.objects.create()保存。
# objects 模型的管理类
# 我们对模型的 增删改查 都找它
BookInfo.objects.create(
    name='java',
    pub_data='2010-06-06'
)

2 修改
修改更新有两种方法

from boook.models import BookInfo

# 方式1  ( 手动调用save )

# 1.先查询数据
book = BookInfo.objects.get(id=1)

# 2.直接修改实例的属性
book.readcount=20

# 3. 调用save方法
book.save()



# 方式2  直接更新  ( update )
使用模型类.objects.filter().update(),会返回受影响的行数
# filter
BookInfo.objects.filter(id=1).update(
    readcount = 100,
    commentcount = 200

3 删除
删除有两种方法

# 方式1
# 1. 先查询出数据
book = BookInfo.objects.get(id=5)
# 2. 调用删除方法
book.delete()

# 方式2
模型类.objects.filter().delete()

BookInfo.objects.filter(id=6).delete()

六、数据库的操作—查询

基础条件查询
1 基本查询

   1. 查询单一结果,如果不存在会抛出模型类.DoesNotExist异常。
    2. all查询多个结果。
    3. count查询结果数量。

# 返回一个数据
book = BookInfo.objects.get(id=1)

# 查询的id 不存在时会抛出异常
book = BookInfo.objects.get(id=100)
try:
    book = BookInfo.objects.get(id=100)
except BookInfo.DoesNotExist:
    pass

# 返回所有结果,是一个列表
BookInfo.objects.all()

# count   返回的是查询到的数量
BookInfo.objects.all().count()
BookInfo.objects.count()

2 过滤查询
实现SQL中的where功能,包括

   1. filter过滤出多个结果
    2. exclude排除掉符合条件剩下的结果
    3. get过滤单一结果

对于过滤条件的使用,上述三个方法相同,故仅以filter进行讲解。

过滤条件的表达语法如下:

属性名称__比较运算符=值
# 属性名称和比较运算符间使用两个下划线,所以属性名不能包括多个下划线

BookInfo-----> 模型类

1)相等
exact:表示判等。
例:查询编号为1的图书。
BookInfo.objects.filter(id__exact=1)
可简写为:
BookInfo.objects.filter(id=1)
--------------------------------------------------------------------------------
# 查询编号为1的图书
# exact 精确的 准确的  就是等于
BookInfo.objects.get(id_exact=1)
BookInfo.objects.get(id=1)  # 相当于是第一个的简写
BookInfo.objects.filter(id=1)  # 返回的是一个列表 想要获得的是一个对象利用下标的形式
# BookInfo.objects.filter(id=1)[0]

2)模糊查询
contains:是否包含。
    说明:如果要包含%无需转义,直接写即可。
例:查询书名包含'传'的图书。
BookInfo.objects.filter(name__contains='传')

startswith、endswith:以指定值开头或结尾。
例:查询书名以'部'结尾的图书
BookInfo.objects.filter(name__endswith='部')

以上运算符都区分大小写,在这些运算符前加上i表示不区分大小写,
如iexact、icontains、istartswith、iendswith.

----------------------------------------------------------------------------
# 查询书名包含'湖'的图书
# contains  包含 的意思
BookInfo.objects.filter(name__contains='湖')


# 查询书名以'部'结尾的图书
# endswith  以什么结尾的意思
BookInfo.objects.filter(name__endswith='部')

3) 空查询
isnull:是否为null。
例:查询书名为空的图书。
BookInfo.objects.filter(name__isnull=True)
4) 范围查询
in:是否包含在范围内。
例:查询编号为1或3或5的图书
BookInfo.objects.filter(id__in=[1,3,5])

5)比较查询
    gt大于 (greater then)
    gte大于等于 (greater then equal)
    lt小于 (less then)
    lte小于等于 (less then equal)

例:查询编号大于3的图书
BookInfo.objects.filter(id__gt=3)

不等于的运算符,使用exclude()过滤器。
例:查询编号不等于3的图书
BookInfo.objects.filter(id__gt=3)
6)日期查询
year、month、day、week_day、hour、minute、second:对日期时间类型的属性进行运算。

例:查询1980年发表的图书。
BookInfo.objects.filter(pub_date__year=1980)

例:查询1990年1月1日后发表的图书。
BookInfo.objects.filter(pub_date__gt='1990-1-1')
  1. F和Q对象
F对象  ----> # 对两个属性的比较 

语法:
filter (字段名__运算符=F('字段名'))

例:查询阅读量大于等于评论量的图书。
from django.db.models import F
BookInfo.objects.filter(readcount__gt=F('commentcount'))

可以在F对象上使用算数运算。
例:查询阅读量大于2倍评论量的图书。
BookInfo.objects.filter(readcount__gt=F('commentcount')*2)

Q对象

多个过滤器逐个调用表示逻辑与关系,同sql语句中where部分的and关键字。

例:需要查询id 大于2 并且阅读量大于20的书籍

# 方式1
# filter().filter()
BookInfo.objects.filter(id__gt=2).filter(readcount__gt=20)

# 方式2
# filter(条件,条件)
BookInfo.objects.filter(id__gt=2,readcount__gt=20)



如果需要实现逻辑或or的查询,需要使用Q()对象结合|运算符,Q对象被义在django.db.models中。
语法如下:
Q(属性名__运算符=值)

例:需要查询id大于2 或者  阅读量大于40的书籍
from django.db.models import Q
BookInfo.objects.filter(Q(id__gt=2)|Q(readcount__gt=40))

Q对象可以使用&、|连接,&表示逻辑与,|表示逻辑或。
Q对象前可以使用~操作符,表示非not。
例:查询编号不等于3的图书。
BookInfo.objects.filter(~Q(id=3))
  1. 聚合函数和排序函数
1. 聚合函数 

Sum,Max,Min,Avg,Count

聚合函数需要使用   aggregate
语法形式是:aggregate(Xxx('字段'))

# 当前书籍的阅读总量
from django.db.models import Sum,Max,Min,Avg,Count
BookInfo.objects.aggregate(Sum('readcount'))


注意aggregate的返回值是一个字典类型
{'属性名__聚合类小写':值}
如:
{'readcount__sum': 126}

使用count时一般不使用aggregate()过滤器。
例:查询图书总数。
BookInfo.objects.count()
注意count函数的返回值是一个数字。
  1. 排序
使用order_by对结果进行排序

 默认升序
BookInfo.objects.all().order_by('readcount')
 降序  在order_by()括号中的参数加上 - 就表示降序
BookInfo.objects.all().order_by('-readcount')
  1. 关联查询
书籍和人物的关系是 一对多
书籍中没有任何关于人物的字段
人物中有关于书籍的字段  book 外键

语法形式:

    通过书籍查询人物信息(已知主表数据,关联查询从表数据)
    主模型(实例对象).关联模型类名小写_set.all()
    
    
    通过人物查询书籍信息(已知 从表数据,关联查询主表数据)
    从表模型(实例对象).外键

例: 查询书籍为1的所有人物信息

通过书籍  查询人物

1. 查询书籍
book = BookInfo.objects.get(id=1)
2. 根据书籍关联人物信息
book.perpleinfo_set.all()

例:查询人物为1的书籍信息


根据书籍 查询人物

from boook.models import PerpleInfo
1. 查询人物
person = PerpleInfo.objects.get(id=1)
2. 根据人物关联查询书籍
# person.book  实例对象
person.book
person.book.name  # 得到真实的名字
  1. 关联过滤查询
由多模型类条件查询一模型类数据:

语法如下:

关联模型类名小写__属性名__条件运算符=值

    注意:如果没有"__运算符"部分,表示等于。




语法形式
    需要的是  书籍信息 ,已知条件是  人物信息
    需要的是  主表数据 ,已知条件是  从表信息
    
    filter(关联模型类型小写__字段__运算符=值)
    
    需要的是  人物信息 ,已知条件是  书籍信息
    需要的是  从表信息 ,已知条件是  主表信息
    
    filter(外键__字段__运算符=值)

例:查询图书,要求图书人物为"郭靖"

需要的是图书,条件是人物

1. BookInfo.objects.filter(perpleinfo__name__exact='郭靖')
2. BookInfo.objects.filter(perpleinfo__name='郭靖')

例:查询图书,要求图书中人物的描述包含"八"

BookInfo.objects.filter(perpleinfo__description__contains='八')


例:查询书名为“天龙八部”的所有人物
PerpleInfo.objects.filter(book__name='天龙八部')

例:查询图书阅读量大于30的所有人物
PerpleInfo.objects.filter(book__readcount__gt=50)

5.查询集QuerySet

查询集,也称查询结果集、QuerySet,表示从数据库中获取的对象集合。

当调用如下过滤器方法时,Django会返回查询集(而不是简单的列表):
    1. all():返回所有数据。
    2. filter():返回满足条件的数据。
    3. exclude():返回满足条件之外的数据。
    4. order_by():对结果进行排序。

2 两大特性

1)惰性执行 
创建查询集不会访问数据库,直到调用数据时,才会访问数据库,调用数据的情况包括迭代、序列化、与if合用
例如,当执行如下语句时,并未进行数据库查询,只是创建了一个查询集books
	books = BookInfo.objects.all()
继续执行遍历迭代操作后,才真正的进行了数据库的查询
	for book in books:
    	    print(book.name)


2)缓存 
使用同一个查询集,第一次使用时会发生数据库的查询,然后Django会把结果缓存下来,
再次使用这个查询集时会使用缓存的数据,减少了数据库的查询次数。
情况一:如下是两个查询集,无法重用缓存,每次查询都会与数据库进行一次交互,增加了数据库的负载。

from book.models import BookInfo
 [book.id for book in BookInfo.objects.all()]
 [book.id for book in BookInfo.objects.all()]

情况二:经过存储后,可以重用查询集,第二次使用缓存中的数据。

books=BookInfo.objects.all()
[book.id for book in books]
[book.id for book in books]

3 限制查询集

可以对查询集进行取下标或切片操作,等同于sql中的limit和offset子句。
注意:不支持负数索引。

对查询集进行切片后返回一个新的查询集,不会立即执行查询。
如果获取一个对象,直接使用[0],等同于[0:1].get(),但是如果没有数据,[0]引发IndexError异常,
[0:1].get()如果没有数据引发DoesNotExist异常。

示例:获取第1、2项,运行查看。
books = BookInfo.objects.all()[0:2]
books

  1. 分页

#查询数据
books = BookInfo.objects.all()
#导入分页类
from django.core.paginator import Paginator
#创建分页实例
paginator=Paginator(books,2)
#获取指定页码的数据
page_skus = paginator.page(1)
#获取分页数据
total_page=paginator.num_pages

猜你喜欢

转载自blog.csdn.net/weixin_44074810/article/details/90815330