django

一,入门
1.介绍
2.搭建开发环境
2.1安装虚拟环境
使用Python进行项目开发时,由于不同的项目需要,可能会配置多个开发环境,不同开发环境之间的项目依赖包如果混合在一起,可能会引起意想不到的错误。
通过虚拟环境隔离不同开发环境,方便不同开发环境的共存。

#安装python虚拟环境
sudo apt-get install virtualenv
#vrtaulenvwrapper是virtualenv的扩展包,用于更方便管理虚拟环境
sudo apt-get install virtualenvwrapper

2.2配置虚拟环境
此时还不能使用virtualenvwrapper,实际上你需要运行virtualenvwrapper.sh文件才行。
配置步骤如下:

1、查看virtualenvwrapper的安装路径
	sudo find / -name virtualenvwrapper.sh
2、创建目录用来存放虚拟环境
	mkdir ~/myvirtualenvs
3、在~/.bashrc中添加行
	export WORKON_HOME=/home/cuixin/myvirtualenvs
	source /usr/share/virtualenvwrapper/virtualenvwrapper.sh
4、运行: source ~/.bashrc

此时virtualenvwrapper就可以使用了。
2.3virtualenvwrapper的功能
配置好virtualenvwrapper,就可以使用它的功能,方便管理虚拟环境

workon:			        列出虚拟环境列表
lsvirtualenv:			列出虚拟环境列表
mkvirtualenv:			新建虚拟环境
workon [虚拟环境名称]:	切换/进入虚拟环境
rmvirtualenv :		    删除虚拟环境
deactivate: 			离开虚拟环境

2.4创建虚拟环境

进入本地虚拟环境的目录文件夹
	cd ~/myvirtualenvs/
创建虚拟环境 根据需要选择3和2
	mkvirtualenv -p /usr/bin/python3  virtualenv-django
    mkvirtualenv -p /usr/bin/python  virtualenv-django
进入虚拟环境
	workon virtualenv-django
查看虚拟环境中已经安装的包
	pip list
	pip freeze

2.5安装django
开发文档:http://www.2xkt.com/documents/django_182/index.html
建议安装1.8.2版本,这是一个稳定性高、使用广、文档多的版本

1.	进入虚拟环境
	workon virtualenv-django
2.	安装django
	pip install django==1.8.2
3.	查看版本,进入python shell:
	python3
	import django
	django.get_version()

说明:使用pip install django命令进行安装时,会自动删除旧版本,再安装新版本
2.6创建项目

命令django-admin startproject test1

进入test1目录,目录结构如下图:
图1
manage.py:一个命令行工具,可以使你用多种方式对Django项目进行交互
内层的目录test1:项目的真正的Python包
_init _.py:一个空文件,它告诉Python这个目录应该被看做一个Python包
settings.py:项目的配置
urls.py:项目的URL声明
wsgi.py:项目与WSGI兼容的Web服务器入口

3.设计模型
3.1设计介绍
本示例完成“图书-英雄”信息的维护,需要存储两种数据:图书、英雄
1.图书表结构设计:

1.表名:BookInfo
2.图书名称:btitle
3.图书发布时间:bpub_date

2.英雄表结构设计

4.表名:HeroInfo
5.英雄姓名:hname
6.英雄性别:hgender
7.英雄简介:hcontent
8.所属图书:hbook

3.图书-英雄的关系为一对多

create table bookinfo(
     bid int auto_increment primary key,
     btitle varchar(100),
     bpubdate date
);
create table heroinfo(
     hid int auto_increment primary key,
     hname varchar(100),
     hgender bit,
     hcontent longtext,
     hbook_id int,
     foreign key(hbook_id) references bookinfo(bid)
);

设计成类,外键就是设计成一个对象
3.2数据库配置
(1).在settings.py文件中,通过DATABASES项进行数据库设置
(2).django支持的数据库包括:sqlite、mysql等主流数据库
(3).Django默认使用SQLite数据库
3.3创建应用
在一个项目中可以创建一到多个应用,每个应用进行一种业务处理
创建应用的命令:
python manage.py startapp booktest
应用的目录结构如下图
图1
3.4定义模型类
1.1.3.4定义模型类
1.有一个数据表,就有一个模型类与之对应
2.打开models.py文件,定义模型类
3.引入包from django.db import models
4.模型类继承自models.Model类
5.说明:不需要定义主键列,在生成时会自动添加,并且值为自动增长
6.当输出对象时,会调用对象的str方法

from django.db import models

# Create your models here.
'''
实体类
'''
class BookInfo(models.Model):
    btitle=models.CharField(max_length=100)
    bpubdate=models.DateTimeField(null=True)
    def __str__(self):
        return 'BookInfo(btitle=%s)'%self.btitle

class HeroInfo(models.Model):
    hname=models.CharField(max_length=100)
    hgender=models.BooleanField()
    hcontent=models.TextField()
    hbookinfo=models.ForeignKey(BookInfo)
    def __str__(self):
        return 'HeroInfo(hname=%s)'%self.hname

3.5生成数据表
1.激活模型:编辑settings.py文件,将booktest应用加入到installed_apps中
图2
2.生成迁移文件:根据模型类生成sql语句,迁移文件被生成到应用的migrations目录

python manage.py makemigrations

图3
3.执行迁移:执行sql语句生成数据表

python manage.py migrate

3.6测试数据操作
1.激活进入python shell,进行简单的模型API练习

python manage.py shell

2.引入需要的包:

from booktest.models import *
from datetime import *

3.单个对象的增删改查
4.关联对象的操作

引入需要的包:
from booktest.models import *
from datetime import *

**************单个对象的操作**************

1、查询所有图书信息:
BookInfo.objects.all()


2、新建图书信息:
b = BookInfo()
b.btitle="射雕英雄传"
b.bpub_date=datetime(year=1990,month=1,day=10)
b.save()


3、查找图书信息:
b=BookInfo.objects.get(pk=1)
输出图书信息:
b
b.id
b.btitle


4、修改图书信息:
b.btitle="天龙八部"
b.save()


5、删除图书信息:
b.delete()

**************关联对象的操作**************

1、对于HeroInfo可以按照下面的操作方式进行
添加,注意添加关联对象

h=HeroInfo()
h.htitle='郭靖'
h.hgender=True
h.hcontent='降龙十八掌'
h.hbook=b
h.save()


2、获得关联集合:返回当前book对象的所有hero

b=BookInfo.objects.get(pk=1)
b.heroinfo_set.all()

4.管理站点
4.1服务器
1.1.4.1服务器
运行如下命令可以开启服务器

python manage.py runserver ip:port

可以不写ip,默认端口为8000
这是一个纯python编写的轻量级web服务器,仅在开发阶段使用
打开浏览器,输入网址“ip:port”可以打开默认页面
如果修改文件不需要重启服务器,如果增删文件需要重启服务器
通过ctrl+c停止服务器
4.2管理操作
1.1.4.2管理操作
站点分为“内容发布”和“公共访问”两部分
“内容发布”的部分负责添加、修改、删除内容,开发这些重复的功能是一件单调乏味、缺乏创造力的工作。为此,Django会根据定义的模型类完全自动地生成管理模块

(1)使用django的管理
创建一个管理员用户

python manage.py createsuperuser,按提示输入用户名、邮箱、密码

启动服务器,通过“ip:port/admin”访问,输入上面创建的用户名、密码完成登录
进入管理站点,默认可以对groups、users进行管理
(2)管理界面本地化
编辑settings.py文件,设置编码、时区

LANGUAGE_CODE = 'zh-Hans'
TIME_ZONE = 'Asia/Shanghai'

(3)向admin注册booktest的模型
打开booktest/admin.py文件,注册模型

from django.contrib import admin
from models import BookInfo
admin.site.register(BookInfo)

刷新管理页面,可以对BookInfo的数据进行增删改查操作
问题:如果在str方法中返回中文,在修改和添加时会报ascii的错误
解决:在str()方法中,将字符串末尾添加“.encode(‘utf-8’)”
(4)自定义管理页面
django提供了admin.ModelAdmin类
通过定义ModelAdmin的子类,来定义模型在Admin界面的显示方式

class QuestionAdmin(admin.ModelAdmin):
...
admin.site.register(Question, QuestionAdmin)

列表页属性
添加、修改页属性

*****************列表页属性*****************

1、list_display:显示字段,可以点击列头进行排序
list_display = ['pk', 'btitle', 'bpub_date’]

2、list_filter:过滤字段,过滤框会出现在右侧
list_filter = ['btitle’]

3、search_fields:搜索字段,搜索框会出现在上侧
search_fields = ['btitle’]

4、list_per_page:分页,分页框会出现在下侧
list_per_page = 10


*****************添加、修改页属性*****************


1、fields:属性的先后顺序
fields = ['bpub_date', 'btitle’]

2、fieldsets:属性分组
fieldsets = [
    ('basic',{'fields': ['btitle']}),
    ('more', {'fields': ['bpub_date']}),
]

(5)关联对象
对于HeroInfo模型类,有两种注册方式
方式一:与BookInfo模型类相同
方式二:关联注册

************关联注册************

1、接下来实现关联注册
from django.contrib import admin
from models import BookInfo,HeroInfo
class HeroInfoInline(admin.StackedInline):
    model = HeroInfo
    extra = 2
class BookInfoAdmin(admin.ModelAdmin):
    inlines = [HeroInfoInline]
admin.site.register(BookInfo, BookInfoAdmin)
2、可以将内嵌的方式改为表格
class HeroInfoInline(admin.TabularInline)

(6)bool值的显示
发布性别hgender的显示不是一个直观的结果,可以使用方法进行封装
在admin注册中使用gender代替hgender

*******************封装*******************
def gender(self):
    if self.hgender:
        return '男'
    else:
        return '女'
gender.short_description = '性别’

*******************注册*******************
class HeroInfoAdmin(admin.ModelAdmin):
    list_display = ['id', 'hname', 'gender', 'hcontent']

5.视图介绍
5.1视图介绍
图1
图2
(1).在django中,视图对WEB请求进行回应
(2).视图接收reqeust对象作为第一个参数,包含了请求的信息
(3).视图就是一个python函数,被定义在views.py中
(4).定义完成视图后,需要配置urlconf,否则无法处理请求

******************views.py******************
from django.shortcuts import render

from django.http import *

def index(request):
    return HttpResponse('hello world')

5.2URLconf
(1).在django中,定义URLconf包括正则表达式、视图两部分
(2).django使用正则表达式匹配请求的URL,一旦匹配成功,则调用应用的视图
(3).注意:只匹配路径部分,即除去域名、参数后的字符串
(4).在mydjangoproject/urls.py插入book,使主urlconf连接到book.urls模块
(5).在book中的urls.py中添加urlconf

******************在mydjangoproject/urls.py中插入book的urls******************
#在mydjangoproject/urls.py插入book,使主urlconf连接到book.urls模块

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

urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    url(r'^laowang/',include('book.urls')),
]




******************在在在book/urls.py中中中添加urlconf******************

#在book/urls.py中添加urlconf

from django.conf.urls import url
from django.contrib import  admin
from . import views
"""
这里一定加$
"""
urlpatterns = [
    url(r'^index$', views.index)
]
******************最后进入book/view.py******************
from django.shortcuts import render

from django.http import *

def index(request):
    return HttpResponse('hello world')

6.模板
6.1定义模版
(1).模板是html页面,可以根据视图中传递的数据填充值
(2).创建模板的目录如下图:
tu3
(3).修改settings.py文件,设置TEMPLATES的DIRS值

'DIRS': [os.path.join(BASE_DIR, 'templates')],

(4).在模板中访问视图传递的数据

{{输出值,可以是变量,也可以是对象.属性}}
{%执行代码段%}

(5)定义index.html模板
(6)定义detail.html模板


*****************定义index.html模板*****************
<!DOCTYPE html>
<html>
<head>
  <title>首页</title>
</head>
<body>
<h1>图书列表</h1>
<ul>
{%for book in booklist%}
<li>
  <a href="{{book.id}}">
    {{book.btitle}}
  </a>
</li>
{%endfor%}
</ul>
</body>
</html>



*****************定义details.html模板*****************
在模板中访问对象成员时,都以属性的方式访问,即方法也不能加括号
<!DOCTYPE html>
<html>
<head>
  <title>详细页</title>
</head>
<body>
<h1>{{book.btitle}}</h1>
<ul>
  {%for hero in book.heroinfo_set.all%}
  <li>{{hero.hname}}---{{hero.hcontent}}</li>
  {%endfor%}
</ul>
</body>
</html>

6.2使用模版

from django.shortcuts import render

from django.http import *
from django.template import RequestContext,loader
from book.models import BookInfo

def index(request):
    #获取版本信息
    temp = loader.get_template('book/index.html')
    #上下文对象
    cxt=RequestContext(request,{'name':'老王'})
    #响应内容
    content=temp.render(cxt)
    #相应对象
    resp=HttpResponse(content)
    #返回
    return resp


django提供了函数Render()简化视图调用模板、构造上下文
Render简写,代替上面写法

from django.shortcuts import render

from django.http import *
from django.template import RequestContext,loader
from book.models import BookInfo

def index(request):
    '''首页'''
    resp=render(request,'book/index.html',{'name':'老王'})
    return resp

6.3去除模板的硬编码
解决:使用命名的url设置超链接
修改mydiangproject/urls.py文件,在include中设置namespace

 url(r'^',include('book.urls',namespace='x')),

修改book/urls.py文件,设置name

urlpatterns = [
    url(r'^$', views.index,name='y1'),
    url(r'^books$', views.select_all,name='y2'),
    url(r'^laowang/(\d+)$', views.select_by_id,name='y3'),
]

修改book_list.html模板中的链接
模板

<a href="{%url 'booktest:detail' book.id%}">

示例代码

   <td><a href="{% url 'x:y3' i.id %}">{{i.btitle}}</a></td>

6.4Render简写
django提供了函数Render()简化视图调用模板、构造上下文。6.2已给出例子
二,模型
1.orm
MVC框架中包括一个重要的部分,就是ORM,它实现了数据模型与数据库的解耦,即数据模型的设计不需要依赖于特定的数据库,通过简单的配置就可以轻松更换数据库
ORM是“对象-关系-映射”的简称,主要任务是:
(1).根据对象的类型生成表结构
(2).将对象、列表的操作,转换为sql语句
(3).将sql查询到的结果转换为对象、列表
这极大的减轻了开发人员的工作量,不需要面对因数据库变更而导致的无效劳动
Django中的模型包含存储数据的字段和约束,对应着数据库中唯一的表
图1
1.1使用MySql数据库
(1).在虚拟环境中安装mysql包
(2).在mysql中创建数据库
(3).打开settings.py文件,修改DATABASES项

*****************1、在虚拟环境中安装mysql包*****************
pip install PyMySQL

MySQLdb 只适用于python2.x,发现python3上的pip装不上。它在py3的替代品是:pip install PyMySQL
而django默认的还是使用MySQLdb:执行会报:ImportError: No module named 'MySQLdb'
解决:
在站点的 __init__.py 文件中添加

import pymysql
pymysql.install_as_MySQLdb()


*****************2、在mysql中创建数据库表*****************

create database test2 charset=utf8

*****************3、修改DATABASES项*****************
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'test2',
        'USER': '用户名',
        'PASSWORD': '密码',
        'HOST': '数据库服务器ip,本地可以使用localhost',
        'PORT': '端口,默认为3306',
    }
}

1.2mysql的日志文件
mysql.log是mysql的日志文件,里面记录的对MySQL数据库的操作记录。默认情况下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日志文件所在的位置。
使用下面的命令可以实时查看mysql的日志文件:

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

在这里插入图片描述
在这里插入图片描述
1.3开发流程
(1).在models.py中定义模型类,要求继承自models.Model
(2).把应用加入settings.py文件的installed_app项
(3).生成迁移文件
(4).执行迁移生成表
(5).使用模型类进行crud操作
1.4使用数据库生成模型类

python manage.py inspectdb > appname/models.py

python manage.py inspectdb > booktest/models.py

一般不使用,因为默认生成的内容多而复杂。所以一般是自己定义模版类。
2.定义模型
(1).在模型中定义属性,会生成表中的字段
(2).django根据属性的类型确定以下信息:
a)当前选择的数据库支持字段的类型
b)渲染管理表单时使用的默认html控件
c)在管理站点最低限度的验证
(3).django会为表增加自动增长的主键列,每个模型只能有一个主键列,如果使用选项设置某属性为主键列后, 则django不会再生成默认的主键列
(4).属性命名限制
a)不能是python的保留关键字
b)由于django的查询方式,不允许使用连续的下划线
2.1属性
一种是限定数据库端的,另外一种是限定后台admin的
(1).定义属性时,需要字段类型
(2).字段类型被定义在django.db.models.fields目录下,为了方便使用,被导入到django.db.models中
(3).使用方式
a)导入from django.db import models
b)通过models.Field创建字段类型的对象,赋值给属性
(4).对于重要数据都做逻辑删除,不做物理删除,实现方法是定义isDelete属性,类型为BooleanField,默认值为False
字段类型

1.AutoField:一个根据实际ID自动增长的IntegerField,通常不指定
a)如果不指定,一个主键字段将自动添加到模型中
2.BooleanField:true/false 字段,此字段的默认表单控制是CheckboxInput
3.NullBooleanField:支持null、true、false三种值
4.CharField(max_length=字符长度):字符串,默认的表单样式是 TextInput
5.TextField:大文本字段,一般超过4000使用,默认的表单控件是Textarea
6.IntegerField:整数
7.DecimalField(max_digits=None, decimal_places=None):使用python的Decimal实例表示的十进制浮点数
a)DecimalField.max_digits:位数总数
b)DecimalField.decimal_places:小数点后的数字位数
8.FloatField:用Python的float实例来表示的浮点数
9.DateField[auto_now=False, auto_now_add=False]):使用Python的datetime.date实例表示的日期
a)参数DateField.auto_now:每次保存对象时,自动设置该字段为当前时间,用于"最后一次修改"的时间戳,它总是使用当前日期,默认为false
b)参数DateField.auto_now_add:当对象第一次被创建时自动设置当前时间,用于创建的时间戳,它总是使用当前日期,默认为false
c)该字段默认对应的表单控件是一个TextInput. 在管理员站点添加了一个JavaScript写的日历控件,和一个“Today"的快捷按钮,包含了一个额外的invalid_date错误消息键
d)auto_now_add, auto_now, and default 这些设置是相互排斥的,他们之间的任何组合将会发生错误的结果
10.TimeField:使用Python的datetime.time实例表示的时间,参数同DateField
11.DateTimeField:使用Python的datetime.datetime实例表示的日期和时间,参数同DateField
12.FileField:一个上传文件的字段
13.ImageField:继承了FileField的所有属性和方法,但对上传的对象进行校验,确保它是个有效的image

字段选项

1.通过字段选项,可以实现对字段的约束
2.在字段对象时通过关键字参数指定
3.null:如果为True,Django 将空值以NULL 存储到数据库中,默认值是 False
4.blank:如果为True,则该字段允许为空白,默认值是 False
a)对比:null是数据库范畴的概念,blank是表单验证证范畴的
5.db_column:字段的名称,如果未指定,则使用属性的名称
6.db_index:若值为 True, 则在表中会为此字段创建索引,在设计数据库的时候创建。
7.default:默认值
8.primary_key:若为 True, 则该字段会成为模型的主键字段
9.unique:如果为 True, 这个字段在表中必须有唯一值

关系

关系的类型包括
1.ForeignKey:一对多,将字段定义在多的端中
2.ManyToManyField:多对多,将字段定义在任意一端中
3.OneToOneField:一对一,将字段定义在任意一端中

可以维护递归的关联关系,使用’self’指定,详见“自关联”

用一访问多:对象.模型类小写_set
bookinfo.heroinfo_set
用一访问一:对象.模型类小写
heroinfo.bookinfo
访问id:对象.属性_id
heroinfo.book_id
2.2元选项
(1).元信息db_table:定义数据表名称,推荐使用小写字母,数据表的默认名称

<app_name>_<model_name>

(2).ordering:对象的默认排序字段,获取对象的列表时使用,接收属性构成的列表

class BookInfo(models.Model):
    ...
    class Meta():
        ordering = ['id']

(3).字符串前加-表示倒序,不加-表示正序

class BookInfo(models.Model):
    ...
    class Meta():
        ordering = ['-id']

排序会增加数据库的开销
2.3示例演示
(1).创建test2项目,并创建booktest应用,使用mysql数据库
(2).定义图书模型

class BookInfo(models.Model):
    btitle = models.CharField(max_length=20)
    bpub_date = models.DateTimeField()
    bread = models.IntegerField(default=0)
    bcomment = models.IntegerField(default=0)
    isDelete = models.BooleanField(default=False)

(3).英雄模型

class HeroInfo(models.Model):
    hname = models.CharField(max_length=20)
    hgender = models.BooleanField(default=True)
    isDelete = models.BooleanField(default=False)
    hcontent = models.CharField(max_length=100)
    hbook = models.ForeignKey('BookInfo')

(4).定义index、detail视图
(5).index.html、detail.html模板
(6).配置url,能够完成图书及英雄的展示
2.4测试数据
(1).模型BookInfo的测试数据

insert into booktest_bookinfo(btitle,bpub_date,bread,bcommet,isDelete) values
('射雕英雄传','1980-5-1',12,34,0),
('天龙八部','1986-7-24',36,40,0),
('笑傲江湖','1995-12-24',20,80,0),
('雪山飞狐','1987-11-11',58,24,0)

(2).模型HeroInfo的测试数据`

insert into booktest_heroinfo(hname,hgender,hbook_id,hcontent,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)

3.模型成员
3.1类的属性
(1).objects:是Manager类型的对象,用于与数据库进行交互
(2).当定义模型类时没有指定管理器,则Django会为模型类提供一个名为objects的管理器
(3).支持明确指定模型类的管理器

class BookInfo(models.Model):
    ...
    books = models.Manager()

(4).当为模型类指定管理器后,django不再为模型类生成名为objects的默认管理器
3.2管理器Manager
(1).管理器是Django的模型进行数据库的查询操作的接口,Django应用的每个模型都拥有至少一个管理器
(2).自定义管理器类主要用于两种情况
a)情况一:向管理器类中添加额外的方法:见下面“创建对象”中的方式二
b)情况二:修改管理器返回的原始查询集:重写get_queryset()方法

class BookInfoManager(models.Manager):
    def get_queryset(self):
        return super(BookInfoManager, self).get_queryset().filter(isDelete=False)
class BookInfo(models.Model):
    ...
    books = BookInfoManager()

3.3创建对象
(1).当创建对象时,django不会对数据库进行读写操作
(2).调用save()方法才与数据库交互,将对象保存到数据库中
(3).使用关键字参数构造模型对象很麻烦,推荐使用下面的两种之式
说明: _init _方法已经在基类models.Model中使用,在自定义模型中无法使用,
a)方式一:在模型类中增加一个类方法

class BookInfo(models.Model):
    ...
    @classmethod
    def create(cls, title, pub_date):
        book = cls(btitle=title, bpub_date=pub_date)
        book.bread=0
        book.bcommet=0
        book.isDelete = False
        return book
引入时间包:from datetime import *
调用:book=BookInfo.create("hello",datetime(1980,10,11));
保存:book.save()

b)方式二:在自定义管理器中添加一个方法
在管理器的方法中,可以通过self.model来得到它所属的模型类

class BookInfoManager(models.Manager):
    def create_book(self, title, pub_date):
        book = self.model()
        book.btitle = title
        book.bpub_date = pub_date
        book.bread=0
        book.bcommet=0
        book.isDelete = False
        return book

class BookInfo(models.Model):
    ...
    books = BookInfoManager()
调用:book=BookInfo.books.create_book("abc",datetime(1980,1,1))
保存:book.save()

在方式二中,可以调用self.create()创建并保存对象,不需要再手动save()

class BookInfoManager(models.Manager):
    def create_book(self, title, pub_date):
        book = self.create(btitle = title,bpub_date = pub_date,bread=0,bcommet=0,isDelete = False)
        return book

class BookInfo(models.Model):
    ...
    books = BookInfoManager()
调用:book=Book.books.create_book("abc",datetime(1980,1,1))
查看:book.pk

3.4实例的属性
DoesNotExist:在进行单个查询时,模型的对象不存在时会引发此异常,结合try/except使用
3.5实例的方法
(1).str (self):重写object方法,此方法在将对象转换成字符串时会被调用
(2).save():将模型对象保存到数据表中
(3).delete():将模型对象从数据表中删除
4.模型查询
(1).查询集表示从数据库中获取的对象集合
(2).查询集可以含有零个、一个或多个过滤器
(3).过滤器基于所给的参数限制查询的结果
(4).从Sql的角度,查询集和select语句等价,过滤器像where和limit子句
(5)接下来主要讨论如下知识点
a)查询集
字段查询:比较运算符,F对象,Q对象
4.1查询集
(1).在管理器上调用过滤器方法会返回查询集
(2).查询集经过过滤器筛选后返回新的查询集,因此可以写成链式过滤
(3).惰性执行/懒加载:创建查询集不会带来任何数据库的访问,直到调用数据时,才会访问数据库
(4).何时对查询集求值:迭代,序列化,与if合用
(5).返回查询集的方法,称为过滤器

all()
filter()
exclude()
order_by()
values():一个对象构成一个字典,然后构成一个列表返回

写法:

filter(键1=值1,键2=值2)
等价于
filter(键1=值1).filter(键2=值2)

(6).返回单个值的方法

get():返回单个满足条件的对象
如果未找到会引发"模型类.DoesNotExist"异常
如果多条被返回,会引发"模型类.MultipleObjectsReturned"异常
count():返回当前查询的总条数
first():返回第一个对象
last():返回最后一个对象
exists():判断查询集中是否有数据,如果有则返回True

(7).限制查询集

查询集返回列表,可以使用下标的方式进行限制,等同于sql中的limit和offset子句
注意:不支持负数索引
使用下标后返回一个新的查询集,不会立即执行查询
如果获取一个对象,直接使用[0],等同于[0:1].get(),但是如果没有数据,[0]引发IndexError异常,[0:1].get()引发DoesNotExist异常

(8).查询集的缓存
每个查询集都包含一个缓存来最小化对数据库的访问
在新建的查询集中,缓存为空,首次对查询集求值时,会发生数据库查询,django会将查询的结果存在查询集的缓存中,并返回请求的结果,接下来对查询集求值将重用缓存的结果

情况一:这构成了两个查询集,无法重用缓存,每次查询都会与数据库进行一次交互,增加了数据库的负载
print([e.title for e in Entry.objects.all()])
print([e.title for e in Entry.objects.all()])

情况二:两次循环使用同一个查询集,第二次使用缓存中的数据
querylist=Entry.objects.all()
print([e.title for e in querylist])
print([e.title for e in querylist])

何时查询集不会被缓存:当只对查询集的部分进行求值时会检查缓存,但是如果这部分不在缓存中,那么接下来查询返回的记录将不会被缓存,这意味着使用索引来限制查询集将不会填充缓存,如果这部分数据已经被缓存,则直接使用缓存中的数据
4.2字段查询

实现where子名,作为方法filter()、exclude()、get()的参数

1.语法:属性名称__比较运算符=值

表示两个下划线,左侧是属性名称,右侧是比较类型
对于外键,使用“属性名_id”表示外键的原始值
转义:like语句中使用了%与,匹配数据中的%与,在过滤器中直接写,例如:filter(title__contains="%")=>where title like ‘%%%’,表示查找标题中包含%的

2.比较运算符

exact:表示判等,大小写敏感;如果没有写“ 比较运算符”,表示判等

filter(isDelete=False)

contains:是否包含,大小写敏感

exclude(btitle__contains='传')

startswith、endswith:以value开头或结尾,大小写敏感

exclude(btitle__endswith='传')

isnull、isnotnull:是否为null

filter(btitle__isnull=False)

在前面加个i表示不区分大小写,如iexact、icontains、istartswith、iendswith
in:是否包含在一些值内

filter(pk__in=[1, 2, 3, 4, 5])

range:是否包含在范围内

filter(pk__range=[1,5])

gt、gte、lt、lte:大于、大于等于、小于、小于等于

filter(id__gt=3)

year、month、day、week_day、hour、minute、second:对日期间类型的属性进行运算

filter(bpub_date__year=1980)
filter(bpub_date__gt=date(1980, 12, 31))

跨关联关系的查询:处理join查询
语法:模型类名 <属性名> <比较>
注:可以没有__<比较>部分,表示等于,结果同inner join
可返向使用,即在关联的两个模型中都可以使用

filter(heroinfo__hcontent__contains='八')

查询的快捷方式:pk,pk表示primary key,默认的主键是id

filter(pk__lt=6)

3.聚合函数
aggregate(聚合函数)和annotate(在aggregate的基础上进行GROUP BY操作)
函数:Avg,Count,Max,Min,Sum

from django.db.models import Max
maxDate = queryset.aggregate(Max('bpub_date'))
HeroInfo.objects.values_list('hbookinfo_id').annotate(Count('id'))

count的一般用法:

count = list.count()

4.F对象

可以使用模型的字段A与字段B进行比较,如果A写在了等号的左边,则B出现在等号的右边,需要通过F对象构造
list.filter(bread__gte=F(‘bcommet’))
django支持对F()对象使用算数运算

list.filter(bread__gte=F('bcommet') * 2)

F()对象中还可以写作“模型类__列名”进行关联查询

list.filter(isDelete=F('heroinfo__isDelete'))

对于date/time字段,可与timedelta()进行运算

list.filter(bpub_date__lt=F('bpub_date') + timedelta(days=1))

5.Q对象

过滤器的方法中关键字参数查询,会合并为And进行
需要进行or查询,使用Q()对象
Q对象(django.db.models.Q)用于封装一组关键字参数,这些关键字参数与“比较运算符”中的相同

from django.db.models import Q
list.filter(Q(pk_ _lt=6))

Q对象可以使用&(and)、|(or)操作符组合起来,当操作符应用在两个Q对象时,会产生一个新的Q对象

list.filter(pk_ _lt=6).filter(bcommet_ _gt=10)
list.filter(Q(pk_ _lt=6) | Q(bcommet_ _gt=10))

使用~(not)操作符在Q对象前表示取反

list.filter(~Q(pk__lt=6))

可以使用&|~结合括号进行分组,构造做生意复杂的Q对象
过滤器函数可以传递一个或多个Q对象作为位置参数,如果有多个Q对象,这些参数的逻辑为and
过滤器函数可以混合使用Q对象和关键字参数,所有参数都将and在一起,Q对象必须位于关键字参数的前面
5.自连接(略)

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值