Django之ORM-model模型属性

Django1.8.2中文文档:Django1.8.2中文文档 或者 https://yiyibooks.cn/xx/django_182/index.html

项目准备

注释:关于项目准备,其实和后面的大部分内容都无关,或者说,可以不看,但为了自己和他人更好的体验,还是放上去。

创建项目

1.创建项目test1000;

2.创建应用booktest;

注册应用:

INSTALLED_APPS = [
    'booktest.apps.BooktestConfig',
]

3.创建数据库

create database test1000 default charset utf8;

在settings文件下配置数据库

DATABASES = {
    'default': {
        # 'ENGINE': 'django.db.backends.sqlite3',
        'ENGINE': 'django.db.backends.mysql',
        # 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
        'NAME': 'test1000',  # 使用的数据库的名字,数据库必须手动创建
        'USER': 'root',  # 链接mysql的用户名
        'PASSWORD': 'root',  # 对应用户的密码
        'HOST': '127.0.0.1',  # 指定mysql数据库所在电脑ip
        'PORT': '3306',  # mysql服务的端口号
    }
}
数据库配置

4.在test1000/__init__.py中加如下内容:
注意:如果没有pymysql需要先pip install

import pymysql
pymysql.install_as_MySQLdb()

5.定义模型类

class BookInfo(models.Model):
    """图书模型类"""
    # 图书名称
    btitle = models.CharField(max_length=20)
    # 出版日期
    bpub_date = models.DateField()
    # 阅读量
    bread = models.IntegerField(default=0)
    # 评论量
    bcomment = models.IntegerField(default=0)
    # 删除标记
    isDelete = models.BooleanField(default=False)


class HeroInfo(models.Model):
    """图书模型类"""
    # 英雄名
    hname = models.CharField(max_length=20)
    # 性别
    hgender = models.BooleanField(default=False)
    # 备注
    hcomment = models.CharField(max_length=200)
    # 关系属性
    bhbook = models.ForeignKey(to="BookInfo")
    # 删除标记
    isDelete = models.BooleanField(default=False)
定义图书和英雄类

生成迁移数据

python manage.py makemigrations
python manage.py migrate

插入数据

INSERT INTO `test1000`.`booktest_bookinfo` (`btitle`, `bpub_date`, `bread`, `bcomment`, `isDelete`) VALUES ('射雕英雄传', '1980-05-01', 12, 34, 0)
INSERT INTO `test1000`.`booktest_bookinfo` (`btitle`, `bpub_date`, `bread`, `bcomment`, `isDelete`) VALUES ('天龙八部', '1986-07-24', 36, 40, 0)
INSERT INTO `test1000`.`booktest_bookinfo` (`btitle`, `bpub_date`, `bread`, `bcomment`, `isDelete`) VALUES ('笑傲江湖', '1995-12-24', 20, 80, 0)
INSERT INTO `test1000`.`booktest_bookinfo` (`btitle`, `bpub_date`, `bread`, `bcomment`, `isDelete`) VALUES ('雪山飞狐', '1987-11-11', 58, 24, 0)


INSERT INTO `test1000`.`booktest_heroinfo` (`hname`, `hgender`, `hbook_id`, `hcomment`, `isDelete`) VALUES
('郭靖',1,1,'降龙十八掌',0),
('黄蓉',0,1,'打狗棍法',0),
('黄药师',1,1,'弹指神通',0),
('欧阳锋',1,1,'蛤蟆功',0),
('梅超风',0,1,'九阴白骨爪',0),
('乔峰',1,2,'降龙十八掌',0),
('段誉',1,2,'六脉神剑',0),
('虚竹',1,2,'天山六阳掌',0),
('王语嫣',0,2,'神仙姐姐',0),
('令狐冲',1,3,'独孤九剑',0),
('任盈盈',0,3,'弹琴',0),
('岳不群',1,3,'华山剑法',0),
('东方不败',0,3,'葵花宝典',0),
('胡斐',1,4,'胡家刀法',0),
('苗若兰',0,4,'黄衣',0),
('程灵素',0,4,'医术',0),
('袁紫衣',0,4,'六合拳',0);
插入数据

6.index页面显示书籍

创建模板templates文件夹;
去settings里面注册模板文件夹;
创建index页面;

编写index页面,使用ul渲染书籍数据;
给index添加a标签指向create路由;

<h2>index页面</h2>
<a href="/create">添加</a>
<ul>
    {% for book in books %}
        <li>{{ book.btitle }}</li>
    {% endfor %}
</ul>
index.html

编写函数,使用模板渲染显示书籍的页面
编写index函数,返回页面渲染;

def index(request):
    """显示书籍"""
    # 获取所有书名
    books = models.BookInfo.objects.all()
    # 使用模板渲染书籍
    return render(request, "booktest/index.html", {"books": books})
index函数

进行url匹配;
将路由导向booktest里面的路由文件;

from django.conf.urls import include, url
from django.contrib import admin

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^', include('booktest.urls')),  # 包含booktest应用中的路由文件
]
test1000/url.py

主要路由统一写在此处,不再重复写

# booktest/url.py

from django.conf.urls import url
from booktest import views

urlpatterns = [
    url(r'^index/', views.index),  # 显示图书信息
    url(r'^create/', views.create),  # 添加一本书籍
    url(r'^delete(\d+)/', views.delete),  # 删除一本书籍
    url(r'^areas/$', views.areas),  # 自关联案例
]

7.进行书籍添加处理
编写create函数,创建bookinfo对象,保存数据,导入redirect,给create函数返回redirect到/index页面;

def create(request):
    """增加一本书籍"""
    # 1.创建bookinfo对象
    b = models.BookInfo()
    b.btitle = "流星蝴蝶剑"
    b.bpub_date = date(1990, 1, 1)
    # 2.保存进数据库
    b.save()
    # 3.返回应答,让浏览器再访问首页
    # return HttpResponse("ok")
    return redirect('/index')
create函数

给create函数进行路由匹配;

8.进行删除书籍处理
给图书后面添加删除链接,链接应加上书籍id;

<a href="/create">添加</a>
<ul>
    {% for book in books %}
        <li>{{ book.btitle }}--<a href="/delete{{ book.id }}">删除</a></li>
    {% endfor %}
</ul>

编写delete函数;

def delete(request, bid):
    """删除一本书籍"""
    # 1.获取书籍对象
    book = models.BookInfo.objects.get(id=bid)
    # 2.删除书籍
    book.delete()
    # 3.重定向
    return redirect('/index')
delete函数

进行路由匹配,注意路由匹配时应接收书籍id;即:

url(r'^delete(\d+)/', views.delete),  # 删除一本书籍

a标签中url的/

<a href="/create">添加</a>

a标签记得前面统一加上/;
没加斜杠的,表示在当前的路由下进行拼接,比如现在在是http://127.0.0.1:8000/index,路由是create,那么就会拼接成/index/create;
而加了斜杠就不会出现这个问题,斜杠表示http://127.0.0.1:8000/,会直接拼接到根路由下;

Django ORM

  • O:(objects)->类和对象。
  • R:(Relation)->关系,关系数据库中的表格。
  • M:(Mapping)->映射。

ORM框架的功能:

  • a)能够允许我们通过面向对象的方式来操作数据库。
  • b)可以根据我们设计的模型类帮我们自动生成数据库中的表格。
  • c) 通过方便的配置就可以进行数据库的切换。

字段属性和选项

模型类属性命名限制

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

字段类型

使用时需要引入django.db.models包,字段类型如下:

类型

描述

AutoField

自动增长的IntegerField,通常不用指定,不指定时Django会自动创建属性名为id的自动增长属性。
BooleanField 布尔字段,值为True或False。
NullBooleanField 支持Null、True、False三种值。
CharField(max_length=字符长度)

字符串。参数max_length表示最大字符个数。

TextField 大文本字段,一般超过4000个字符时使用。
IntegerField 整数。
DecimalField(max_digits=None, decimal_places=None)

十进制浮点数。

参数max_digits表示总位数。参数decimal_places表示小数位数。

FloatField 浮点数。参数同上,精确度不如上面的。
FileField 上传文件字段。
ImageField 继承于FileField,对上传的内容进行校验,确保是有效的图片。
DateField

日期。年月日
参数auto_now表示每次保存对象时,自动设置该字段为当前时间,用于"最后一次修改"的时间戳,它总是使用当前日期,默认为false。
参数auto_now_add表示当对象第一次被创建时自动设置当前时间,用于创建的时间戳,它总是使用当前日期,默认为false。
参数auto_now_add和auto_now是相互排斥的,组合将会发生错误。

TimeField 时间,参数同DateField。小时分秒
DateTimeField 日期时间,参数同DateField。年月日时分秒

 选项

通过选项实现对字段的约束,选项如下:

选项名 描述
default 默认值。
primary_key 若为True,则该字段会成为模型的主键字段,默认值是False,一般作为AutoField的选项使用。
unique 如果为True, 这个字段在表中必须有唯一值,默认值是False。
db_index 若值为True, 则在表中会为此字段创建索引,默认值是False。
db_column 字段的名称,如果未指定,则使用属性的名称。
null 如果为True,表示允许为空,默认值是False。
blank 如果为True,则该字段允许为空白,默认值是False。

对比:null是数据库范畴的概念,blank是表单验证证范畴的。

经验:当修改模型类之后,如果添加的选项不影响表的结构,则不需要重新做迁移,例如商品的选项中default和blank不影响表的结构;

如果想要更深入的了解模型的选型和字段,建议看官方文档,百度Django1.8.2.中文文档即可。

单表查询

配置MySQL的日志文件

让其产生mysql.log,即是mysql的日志文件,里面记录了对mysql数据库的操作记录。
1).使用下面的命令打开mysql的配置文件,取消68,69行的注释,然后保存。

sudo vi /etc/mysql/mysql.conf.d/mysqld.cnf

2).重启mysql服务,就会产生mysql日志文件。

sudo service mysql restart

3).打开mysql的日志文件

/var/log/mysql/mysql.log # mysql日志文件所在位置

4).使用下面命令实时查看mysql文件的内容

sudo tail -f /var/log/mysql/mysql.log

查询函数

通过模型类.object属性可以调用如下函数,实现对模型类对应的数据表的查询;
注意,查询集里面,还可以再次调用一下函数进行处理,即如果你通过filter等函数查询出来的数据,还可以调用filter等函数进行处理;

函数名 功能 返回值 备注
get() 返回表中满足条件的一条且只能有一条数据 返回对象;

如果查到多条数据,则抛异常:MultipleObjectsReturned
查询不到数据,则抛异常:DoesNotExist

all() 返回模型类对应表格中的所有数据。 QuerySet类型 查询集
filter() 返回满足条件的数据 QuerySet类型

参数写查询条件;

条件格式:模型类属性名__条件名=值。

exclude 返回不满足条件的数据 QuerySet类型 参数写查询条件;
order_by 对查询结果进行排序。 QuerySet类型 参数中写根据哪些字段进行排序。

filter方法示例:

1. 判等 exact。
例:查询编号为1的图书。

BookInfo.objects.get(id=1)
BookInfo.objects.get(id__exact=1)

2. 模糊查询
例:查询书名包含'传'的图书。contains

BookInfo.objects.filter(btitle__contains='')

例:查询书名以'部'结尾的图书 endswith 开头:startswith

BookInfo.objects.filter(btitle__endswith='')

3. 空查询 isnull
select * from booktest_bookinfo where title is not null;
例:查询书名不为空的图书。isnull

BookInfo.objects.filter(btitle__isnull=False)

4. 范围查询 in
select * from booktest_bookinfo where id in (1,3,5)
例:查询编号为1或3或5的图书。

BookInfo.objects.filter(id__in = [1,3,5])

5. 比较查询

  • gt(greate than) 大于
  • lt(less than) 小于
  • gte(equal) 大于等于
  • lte 小于等于

例:查询编号大于3的图书。

BookInfo.objects.filter(id__gt = 3)

6. 日期查询
例:查询1980年发表的图书。

BookInfo.objects.filter(bpub_date__year=1980)

例:查询1980年1月1日后发表的图书。

from datetime import date
BookInfo.objects.filter(bpub_date__gt = date(1980,1,1))

exclude方法示例:
例:查询id不为3的图书信息。
BookInfo.objects.exclude(id=3)

order_by示例方法:
作用:进行查询结果进行排序
降序(.all()可以省略)

# 例1:查询所有图书信息,按照id从小到大顺序进行排序;
BookInfo.objects.all().order_by('id')    # 按照升序排序
# 查询所有图书信息,按照id从大到小顺序进行排序;
BookInfo.objects.all().order_by('-id') # 按照降序排序
# 把id大于3的图书信息按阅读量从大到小排序显示。
BookInfo.objects.filter(id__gt=3).order_by('-bread') # 把id大于3的图书信息按阅读量从大到小排序显示。

Q对象

作用:用于查询时条件之间的逻辑关系。not and or,可以对Q对象进行&|~操作。

使用之前需要先导入:

from django.db.models import Q

例:查询id大于3且阅读量大于30的图书的信息。

BookInfo.objects.filter(id__gt=3, bread__gt=30)
BookInfo.objects.filter(Q(id__gt=3)&Q(bread__gt=30))

例:查询id大于3或者阅读量大于30的图书的信息。

BookInfo.objects.filter(Q(id__gt=3)|Q(bread__gt=30))

例:查询id不等于3图书的信息。

BookInfo.objects.filter(~Q(id=3))

F对象

作用:用于类属性之间的比较。比如要查询评论量大于阅读量的文章书籍时就可以使用;

使用之前需要先导入:

from django.db.models import F

例:查询图书阅读量大于评论量图书信息。

BookInfo.objects.filter(bread__gt=F('bcomment'))

例:查询图书阅读量大于2倍评论量图书信息。

BookInfo.objects.filter(bread__gt=F('bcomment')*2)

聚合函数

作用:对查询结果进行聚合操作。

  • sum
  • count
  • avg
  • max
  • min

aggregate:调用这个函数来使用聚合。 返回值是一个字典

使用前需先导入聚合类:

from django.db.models import Sum,Count,Max,Min,Avg

例:查询所有图书的数目。

BookInfo.objects.all().aggregate(Count('id'))
{'id__count': 5}

例:查询所有图书阅读量的总和。

BookInfo.objects.aggregate(Sum('bread'))
{'bread__sum': 126}


count函数

返回一个数字
作用:统计满足条件数据的数目。

例:统计所有图书的数目。

BookInfo.objects.all().count()
BookInfo.objects.count()
结果:5

例:统计id大于3的所有图书的数目。

BookInfo.objects.filter(id__gt=3).count()

查询相关函数小结

  • get:返回一条且只能有一条数据,返回值是一个对象, 参数可以写查询条件。
  • all:返回模型类对应表的所有数据,返回值是QuerySet。
  • fiter:返回满足条件的数据,返回值是QuerySet,参数可以写查询条件。
  • exclude:返回不满足条件的数据,返回值是QuerySet,参数可以写查询条件。
  • order_ by:对查询结果进行排序,返回值是QuerySet, 参数中写排序的字段。

注意:

  • 1. get, flter,exclude函数中可以写查询条件,如果传多个参数,条件之间代表且的关系。
  • 2. all, fiter, exclude, order. by函数的返回值是QuerySet类的实例对象,叫做查询集。

from diango.db.models import F,Q Sum,Count Avg, Max,Min

  • F对象:用于类属性之间的比较。
  • Q对象:用于条件之间的逻辑关系。
  • aggregate:进行聚合操作,返回值是一个字典,进行聚合的时候需要先导入聚合类。
  • count:返回结果集中数据的数目,返回值是一个数字。

注意:
对一个QuerySet实例对象,可以继续调用上面的所有函数。


参考文档:
http://python.usyiyi.cn/translate/django_182/ref/models/querysets.html

查询集

all, filter, exclude, order_by调用这些函数会产生一个查询集,QuerySet类对象可以继续调用上面的所有函数。

查询集特性

1)惰性查询:只有在实际使用查询集中的数据的时候才会发生对数据库的真正查询。
2)缓存:当使用的是同一个查询集时,第一次的时候会发生实际数据库的查询,然后把结果缓存起来,之后再使用这个查询集时,使用的是缓存中的结果。

限制查询集

可以对一个查询集进行取下标或者切片操作来限制查询集的结果。
对一个查询集进行切片操作会产生一个新的查询集,下标不允许为负数。

取出查询集第一条数据的两种方式:

方式  说明
b[0]  如果b[0]不存在,会抛出IndexError异常
b[0:1].get()  如果b[0:1].get()不存在,会抛出DoesNotExist异常。

exists:判断一个查询集中是否有数据。True False

books = BookInfo.objects.all()
books1 = books[0:0]
book.exists()
# True
book1.exists()
# False

猜你喜欢

转载自www.cnblogs.com/yifchan/p/python-1-25.html