Django 的安装
Copy pip3 install pipenv
cd / opt && mkdir appcation && cd appcation
pipenv --python 3.7
pipenv shell
pipenv install django == 2.0 . 5
django - admin startproject devops
# 上解释: 创建虚拟环境、目录、 在虚拟环境中安装django,创建项目 devops
(appcation) [root @ localhost appcation] # tree
.
├── devops
│ ├── db . sqlite3
│ ├── devops
│ │ ├── __init__ . py
│ │ ├── settings . py
│ │ ├── urls . py
│ │ └── wsgi . py
│ └── manage . py
├── Pipfile
└── Pipfile . lock
项目目录详解
manage.py 一个实用的命令行工具,可让你以各种方式与该 Django 项目进行交互
内层 devops/ 目录是你项目中的实际Python包。通过它你可以导入它里面的任何东西
devops/init .py: 一个空文件,告诉Python该目录是一个Python包
devops/settings.py: 该Django项目的配置文件
devops/urls.py: 该Django项目的 URL 声明
devops/wsgi.py: 一个WSGI兼容的Web服务器的入口
新建 App
Copy # 新建一个名为dashboard的app
python manage . py startapp dashboard
Copy # 配置url
from django . urls import path , include
urlpatterns = [
path ( 'dashboard/' , include ( "dashboard.urls" ))
]
Copy # 激活app
INSTALLED_APPS = (
... .
'dashboard' ,
)
App中编写视图
Copy # 子路由: dashboard/urls.py
from django . conf . urls import url
from . import views
urlpatterns = [
url ( r ' ^$ ' , views.index, name = 'index' ),
]
# 子视图: dashboard/views.py
from django . http import HttpResponse
def index ( request ):
return HttpResponse ( "Hello world !!!" )
启动服务
Copy python manage . py runserver # 启动服务
python manage . py runserver 8000 # 指定端口启动服务
python manage . py runserver 0.0 . 0 . 0 : 8000 # 指定IP和端口启动服务
启动 Django 报错解决:
ModuleNotFoundError: No module named '_sqlite3'
Copy yum install sqlite - devel
# 在重新编译 python
配置静态文件
Copy STATIC_URL = '/static/'
STATICFILES_DIRS = (
os . path . join (BASE_DIR, "static" ),
)
配置时区
Copy TIME_ZONE = ’Asia / Shanghai’
HttpRequest对象
由django创建
属性
Copy HttpRequest . scheme ===> request . scheme <=== 请求协议
HttpRequest . body ===> request . body <=== 请求主体
HttpRequest . path ===> request . path <=== 请求路径
HttpRequest . method ===> request . method <=== 请求方式
HttpRequest . encoding ===> request . encoding <=== 请求编码
HttpRequest . GET ===> request . GET <=== 请求实例对象参数
HttpRequest . POST ===> request . POST <=== 请求实例对象参数
HttpRequest . META ===> request . META <=== 请求元素
方法
Copy HttpRequest . get_host () ===> request . get_host () <=== 请求的主机
HttpRequest . get_port () ===> request . get_port () <=== 请求的端口
HttpRequest . get_full_path () ===> request . get_full_path () <=== 请求的路径
HttpRequest . is_secure () ===> request . is_secure () <=== 请求是否是安全的
HttpRequest . is_ajax () ===> request . is_ajax () <=== 请求是否 ajax 方式
HttpResponse对象
传递一个字符串作为页面的内容到 HttpResponse 构造函数
Copy >>> from django . http import HttpResponse
>>> response = HttpResponse ( "Here's the text of the Web page." )
>>> response = HttpResponse ( "Text only, please." , content_type = "text/plain" )
属性:
Copy HttpResponse.content ===> 响应内容
HttpResponse.charset ===> 响应编码
HttpResponse.status_code ===> 响应状态
HttpResponse.reason_phrase ===> 响应消息的原因说明
方法
Copy HttpResponse . __init__ (content = ”, content_type = None , status = 200 , reason = None , charset = None )
JsonResponse 对象
方法
Copy JsonResponse (data, encoder = DjangoJSONEncoder, safe = True , json_dumps_params = None , ** kwargs)
示例
Copy >>> from django . http import JsonResponse
>>> response = JsonResponse ({ 'foo' : 'bar' })
>>> response . content
b '{"foo": "bar"}'
>>> response = JsonResponse ([ 1 , 2 , 3 ], safe = False ) # 加上 safe=False , 允许非字典
视图错误
Copy 报错: In order to allow non - dict objects to be serialized set the safe parameter to False .
解决: return JsonResponse (data = data, safe = False )
QueryDIct对象
在HttpRequest 对象中,GET 和POST 属性是django.http.QueryDict 的实例,它是一个自定
义的类似字典的类,用来处理同一个键带有多个值。这个类的需求来自某些HTML 表单元
素传递多个值给同一个键
request.POST 和request.GET 的QueryDict 在一个正常的请求/响应循环中是不可变的。若
要获得可变的版本,需要使用.copy()
实例化QueryDict
Copy QueryDict . __init__ (query_string = None , mutable = False , encoding = None )
示例
Copy >>> QueryDict ( 'a=1&a=2&c=3' )
< QueryDict : { 'a' : [ '1' , '2' ] , 'c' : [ '3' ] } >
通过fromkeys实例化QueryDict (1.11新增)
Copy classmethod QueryDict . fromkeys (iterable, value = ”, mutable = False , encoding = None )
示例
Copy >>> QueryDict . fromkeys ([ 'a' , 'a' , 'b' ], value = 'val' )
< QueryDict : { 'a' : [ 'val' , 'val' ] , 'b' : [ 'val' ] } >
QueryDict方法:
Copy QueryDict . get (key,default = None )
QueryDict . setdefault (key,default = None ) [source]
QueryDict . update (other_dict)
QueryDict . items ()
QueryDict . values ()
QueryDict . copy ()
QueryDict . getlist (key,default = None )
QueryDict . setlist (key,list_) [source]
QueryDict . appendlist (key,item)
QueryDict . setlistdefault (key,default_list = None )
QueryDict . lists ()
QueryDict . pop (key)
QueryDict . popitem ()
QueryDict . dict ()
QueryDict . urlencode (safe = None )
GET与POST请求
GET请求与传参 那如何获取url后面的这个参数呢?---它是被存放在request.GET中,是一种QueryDict数据类型
那怎样取到cc变量中某一个值?
Copy print (request.GET. get ( "aa" )) -- > (打印aa变量)结果为bb
prin t (request.GET. getlist ( "cc" )) --->结果为列表[ 'dd' , 'ee' ] # 解决传入同样的key,只获取一个值
print (request.GET) -- > (完整的request请求)结果为 < QueryDict : { 'aa' : [ 'bb' ] , 'cc' : [ 'dd' , 'ee' ] } >
加载摸版
django.template.loader 这个模块提供了两种方法加载模板
Copy get_template (template_name, using = None )
加载指定模板并返回Template对象; 它与get_template类似,它尝试每个名称并返回第一个存在的模板
Copy select_template (template_name_list, using = None )
从文件加载内容
Copy from django . template import Context , loader
def index ( request ):
t = loader . get_template ( "test.html" )
context = { "name" : "hello reboot !!!" }
return HttpResponse (t. render (context, request))
快捷方式:render()
Copy from django . shortcuts import render
def index ( request ):
context = { 'name' : "reboot" }
return render (request, 'test.html' , context)
实战用户登陆
配置django 数据库
Copy DATABASES = {
'default' : {
'ENGINE' : 'django.db.backends.mysql' ,
'NAME' : 'django' ,
'USER' : 'root' ,
'PASSWORD' : 'aabb122..' ,
'HOST' : '192.168.1.33' ,
'PORT' : 3306 ,
}
}
同步数据
Copy python manage . py migrate
Django API 创建用户
#使用 django shell 创建普通用户:创建users最直接的方法是使用create_user()辅助函数
普通用户
Copy
>>> from django . contrib . auth . models import User
>>> user = User . objects . create_user ( "rock" , "rock@51reboot.com" , "123456" )
创建管理员
Copy # 创建管理员
python manage . py createsuperuser --username = reboot --email = reboot @ 51reboot . com
修改密码
Django不会在user模型上存储原始的(明文)密码,而只是一个哈希。因为这个原因,不要尝
试直接操作user的password属性。这也是为什么创建一个user时要使用辅助函数
Copy >>> from django . contrib . auth . models import User
>>> u = User . objects . get (username = 'rock' )
>>> u . set_password ( '654321' )
>>> u . save ()
执行用户登录
Copy 用户登录的时候,数据库中会保留 session 数据,可以看到
Django如何处理一个请求
django 加载 ROOT_URLCONF指定的模块,并寻找可用的urlpattems,它是 django.conf.urls.url()实例的的一个python列表。
django 依次匹配每个URL,在于请求的URL匹配到第一个url停下来
一旦其中的正则表打死匹配上,django将导入并调用给出的视图,它是一个简单的Python函数(或者一个基于类的视图)。 视图将获得如下参数:
参数二:如果匹配的正则表达式返回了没有命名的组,那么正则表达式匹配的内容将作为位置参数提供给视图。
参数三:关键字参数由正则表达式匹配的命名组组成,但是可以被 django.conf.urls.url() 的可选参数 kwargs 覆盖
如果没有匹配到正则表达式,或者如果过程中抛出一个异常,Django 将调用一个适当的错误处理视图: handler404, handler500, hander403, handler400
URL 路由
对于高质量的Web 应用来说,使用简洁、优雅的URL路由是一个非常值得重视的细节。 Django 让你随心所欲设计你的URL,不受框架束缚。 为了给一个应用设计URL,你需要创建一个Python 模块,通常称为URLconf(URL conÒguration)。这个模块是纯粹的Python 代码,包含URL 模式(简单的正则表达式)到 Python 函数(你的视图)的简单映射
Copy # setting.py
ROOT_URLCONF = '项目.urls'
URLconf
URLconf 是一个python模块,是一个URL模式(简单正则表达式)到Python函数(视图)之间的映射
URLpatterns
urlpatterns 是一个 url() 实例类型的Python列表
urlpatterns 中的每个正则表达式在第一次访问它们时被编译
URl 函数
Copy url (regex, view, kwargs = None , name = None )
regex: 一个字符串(原始字符串)或简单的正则表达式
view: view参数是一个视图函数或as_view()的结果(基于类的视图)
include
Copy include (module, namespace = None , app_name = None )
include (pattern_list)
include ((pattern_list, app_namespace), namespace = None )
include ((pattern_list, app_namespace, instance_namespace))
pattern_list: 可迭代的django.conf.urls.url()实例
instance_namespace: 实例的命名空间
include 示例
示例1:
Copy urlpatterns = [
url ( r ' ^$ ' , RedirectView. as_view (url = '/dashboard/' )),
url ( r ' ^ dashboard/' , include ( 'dashbard.urls' )),
url ( r ' ^ account/' , include ( 'account.urls' )),
url ( r ' ^ admin/' , admin.site.urls),
]
示例2:
Copy urlpatterns = [
url ( r ' ^ user/' , include ([
url ( r ' ^ list/' , view.userlist, name = 'user_list' ),
url ( r ' ^ info/' , view.userinfo, name = 'userer_inf' ),
url ( r ' ^ modify/' , include ([
url ( r 'status/ $ ' , view.modifystatus, name = 'user_modify_status' )
]))
]))
]
URL参数—— 位置参数
若要从URL 中捕获一个值,只需要在它周围放置一对圆括号。
Copy from django . conf . urls import url
from . import views
urlpatterns = [
url ( r ' ^ articles/2003/ $ ' , views.special_case_2003),
url ( r ' ^ articles/ ( [0-9] {4} ) / $ ' , views.year_archive),
url ( r ' ^ articles/ ( [0-9] {4} ) / ( [0-9] {2} ) / $ ' , views.month_archive),
url ( r ' ^ articles/ ( [0-9] {4} ) / ( [0-9] {2} ) / ( [0-9] + ) / $ ' , views.article_detail),
]
请求地址: / articles / 2003 / 03 / 03 /
调用函数:views . article_detail (request, "2003" , '03' , '03' )
URL参数——关键字参数
Copy # 语法
(?p < name > pattern)
pattern 是一个正则表达式,也是关键字参数的值
Copy # 示例
from django . conf . urls import url
from . import views
urlpatterns = [
url ( r ' ^ articles/2003/ $ ' , views.special_case_2003),
url ( r ' ^ articles/ ( ?P<year>[0-9] {4} ) / $ ' , views.year_archive),
url ( r ' ^ articles/ ( ?P<year>[0-9] {4} ) / ( ?P<month>[0-9] {2} ) / $ ' , views.month_archive),
url ( r ' ^ articles/ ( ?P<year>[0-9] {4} ) / ( ?P<month>[0-9] {2} ) / ( ?P<day>[0-9] {2} ) / $ ' ,views.article_detail),
]
请求地址: / articles / 2003 / 03 / 03 /
调用函数:views . article_detail (request, year = '2003' , month = '03' , day = '03' )
URL参数——额外参数
URLconfs 具有一个钩子,让你传递一个Python 字典作为额外的参数传递给视图函数
django.conf.urls.url() 函数可以接收一个可选的第三个参数,它是一个字典,表示想要传递给视图函数的额外关键字参数
Copy # 示例
from django . conf . urls import url
from . import views
urlpatterns = [
url ( r ' ^ blog/ ( ?P<year>[0-9] {4} ) / $ ' , views.year_archive, { 'foo' : 'bar' }),
]
请求地址: / blog / 2005 /
调用函数:views . year_archive (request, year = '2005' ,foo = 'bar' )
URL反向解析
django给每个URL取了一个名字,存储每个URL与name的映射关系
根据Django 视图的标识和将要传递给它的参数的值,获取与之关联的URL。这种方式叫做
反向解析URL、反向URL匹配、反向URL查询或者简单的URL反查
Copy from django . conf . urls import url
from . import views
urlpatterns = [
url ( r 'articles/ ( 0-9 ) {4} / $ ' , view.year_archive, name = 'news-year-archive' ),
]
视图中使用
Copy from django . core . urlresolvers import reverse
year = 2006
return HttpResponseRedirect ( reverse ( 'news-year-archive' , arg = (year, )))
摸版中使用
Copy < a href = "<div data-gb-custom-block data-tag=" url " data-0='news-year-archive'></div>" > {{ yearvar }} Archive </ a >
基于类的视图
视图是一个可调用的对象,它接受一个请求然后返回一个响应,这个可调用对象可以不只是函数,Django提供一些可以用作视图的类
基于类的视图使用Python对象实现视图,它提供除函数视图之外的另一种方式
View
属性 :
http_method_names 方法: as_view() dispatch() http_method_not_allowed()
类视图登陆验证
Copy from django . contrib . auth . decorators import login_required
from django . utils . decorators import method_decorato
class FooView ( View ):
@method_decorator (login_required)
def get ( request , * args , ** kwargs ):
return HttpResponse ( "hello world" )
数据分页
Paginator对象 And Page对象
Copy class Paginator(object_list, per_page, orphans=0, allow_empty_first_page=True)
Copy # 属性
- Paginator . count 所有页面的objects总数
- Paginator . num_pages 页面总数
- Paginator . page_range 页码的范围,从1开始,例如[ 1 , 2 , 3 , 4 ]
# 方法
- Paginator . page (number) 返回一个page对象 , number, 当前显示的是第几页
Page 对象
Copy class Page ( object_list , number , paginator )
Copy # 属性
- Page . object_list 当前页面的对象列表
- Page . number 当前页的序号,从1开始
- Page . paginator Paginator对象
# 方法
- Page . has_next () 如果有下一页,返回True
- Page . has_previous () 如果有上一页,返回 True
- Page . has_other_pages () 如果有上一面或下一页,返回True
- Page . next_page_number () 返回下一页的页码。如果不存在,抛出InvalidPage异常
- Page . previous_page_number () 返回上一页的页码。如果不存在,抛出InvalidPage异常
- Page . start_index () 返回当前页上的第一个对象,相对于分页列表的所有对象的序号
- Page . end_index () 返回当前页上的最后一个对象,相对于分页列表的所有对象的序号
模型
什么是模型
模型是你数据唯一的、权威的信息源。它包含你所存储数据的必要字段和行为,每个模型对应数据库中的唯一的一张表
如何编写模型
模型: 每个模型都用一个类表示,该类继承自 django.db.models.Model, 每个模型有多个类的属性变量,而每个类的属性变量又都代表了数据库中的一个字段
字段: 每个字段通过Field类的一个实例表示 --- 例如字符字段CharField和日期字段 DateTimeField. 这种方法告诉 Django,每个字段中报错着什么类型的数据
字段名: 每个Field实例中(例如username)就是自动的名字,并且是机器可短的格式,你将在Pythoin代码中使用到它的值,并且你的数据库将它用作列表的列表
常见模型字段
DateField / DateTimeField
自增主键字段
默认情况下Django会给每个模型添加羡慕这个字段
Copy id = models . AutoField (primary_key = True )
如果Django看到你显式地设置了Field.primary_key, 就不会自动添加id列
每个模型只能有一个字段指定 primary_key=True (无论是显式生命还是自动添加)
字段的自述名
每个字段类型都解散一个可选的位置参数----自动的自数名,如果没有给定自述名,Django将根据字段的署名名称自动创建自述名---将属性名的下划线替换成空格
ForeignKey、ManyToManyField 和 OneToOneField 这三个可以使用 verbose_name指定自述名
Copy # 例如: 自述名为: "person's first name"
first_name = models . CharField ( "person's first name" , max_length = 30 )
# 例如: 自述名为: "first name"
first_name = models . Charfield (max_length = 30 )
字段选项
null ===> 如果为True, Django 将用NULL来再数据库中存储空值,默认 False
blank ===> 如果为True,该字段允许不填,默认False, null 是纯数据范畴,blank 是数据验证范畴
choices ===> 由二元组组成的一个可迭代对象,如果设置了choices,默认表单将是选择框,值是 choices中选项
Copy YEAR_IN_SCHOOL_CHOICES = (
( 'FR' , 'Freshman' ) ,
( 'SO' , 'Sophomore' ) ,
( 'JR' , 'Junior' ) ,
( 'SR' , 'Senior' ) ,
)
default ===> 字段的默认值,可以是一个值或者调用的对象
primary_key ===> 如果为True,那么这个字段就是模型的主键
unique ===> 如果该值为True,这个字段的值在整张表中必须是唯一的
模型 meta 选项
模型元数据是 任何不是字段的数据 , 比如排序选项(ordering ), 数据库表名(db_table ).在模型中添加 class Meta是可选的
Copy # 使用内部的class Meta 定义模型的元数据,例如
from django . db import models
class User ( models . Model ):
username = models . IntegerField ()
class Meta :
ordering = [ 'username' ]
meta选项: db_table
db_table 是用于指定自定义数据库表名的。 Django有一套默认的按照一定规则生成数据模型对应的数据库表妹,如果你想使用自定义表妹,就通过这个属性指定
惹不提供该参数, Django会使用 app_label + "_" + module_name 作为表的名字
Copy class Meta :
db_table = 'server'
Django 会根据模型类的名称和包含它的应用的名称自动指定数据表名称,一个模型的数据库表名称,由这个模型的应用名和模型类名称之间加上下划线组成
使用Meta类中的 db_table 参数来重写数据表的名称
当你通过 db_table 覆写表名称时,强烈推荐使用小写字母给表命名
meta选项:order
这个字段是告诉Django模型对象返回的记录结果集是安装哪个字段排序的
Copy # 例如三列: order_date、 pub_date 、author
class Meta :
ordering = [ 'order_date' ] # 按订单升序排列
ordering = [ '-order_date' ] # 按订单降序排列, - 表示降序
ordering = [ '?order_date' ] # 随机排序, ? 表示随机
ordering = [ '-pub_date' , 'author' ] # 对 pub_date 降序, 然后对 author 升序
meta选项:app_label
app_label 这个选项只在一种情况下使用,就是你的模型类不在默认的应用程序包下的 model.py 文件中,这时候你需要制定你这个模型类是哪个应用程序的
Copy class Meta :
appp_label = 'myapp'
meta选项:get_lates_by
由于Django的管理方法中有个**lastest()**方法,就是得到最近一行记录,如果你的数据模型中有DateField 或 DateTimeField类型的字段,你可以通过这个选项来制定 lastest() 是按照哪个字段进行选取的
一个 DateField 活 DateTimeField 字段的名字,惹提供该选项,该模块将拥有一个 get_latest() 函数以得到最新的对象(依据那个字段)
Copy class Meta :
get_lastest_by = 'order_date'
meta选项:verbose_name
verbose_name 的意思很简单,就是给你的模型类起一个更可读的名字
Copy class Meta :
verbose_name = 'pizza'
meta选项:managed
由于Django会自动根据模型类生成映射的数据库表,如果你不希望Django这么做,那么把managed的值设置为 False
默认值为T入耳,这个选项为True时,Django可以对数据库进行 migrate活migrations、删除等操作,在这个时间Django将管理数据库表的生命周期
如果为False的时候,不会对数据库进行创建、删除等操作。可以用于先有表、数据库视图等,其他操作是一样的
数据库迁移
迁移是Django用户同步你的发生改变的模型(添加一个字段,删除一个字段,等待)到你的数据库
迁移命令
makemigrations ===> 负责基于你的模型修改创建一个新的迁移
migrate ===> 负责执行迁移,以及撤销和列出迁移的状态
sqlmigrate ===> 展示迁移的sql语句
生成迁移文件
例如APP名字: dashboard
Copy python manage . py makemigrations dashboard
# 会扫描和比较你当前迁移文件里面的版本,同事新的迁移文件会被创建
展示迁移的 sql 语句
Copy python manage . py sqlmigrate dashboard 0007
数据迁移
Copy python manage . py migrate dashboard
创建对象
使用关键字参数实例化模型实例来创建一个对象,然后调用save()把它保存到数据库中
也可以使用一条语句穿件并保存一个对象,使用create()方法
查询对象
Copy all_users = User . objects . all ()
u = User . objects . filter (username = 'rock' )
u = User . objects . all (). filter (username = 'rock' )
Entry . object . filter ( ===> 查询以 'what' 开头,发布日期在2005年1月30日至当天之前直接的所有记录
headline__startswith = 'what'
). exclude (
pub_date__gte = datetime.date. today ()
). filter (
pub_date__gte = datetime ( 2005 , 1 , 30 )
)
Copy one_entry = Entry . objects . get (pk = 1 ) ===> 通过主键查询
# 如果没有查询到,将返回 DoesNotExist 异常,
# 如果有多条记录,将返回 MultipleObjectsReturned 异常
Copy # 限制查询集
Entry . object . all () [ : 5 ]
Entry . object . all () [ 5 : 10 ]
Copy # 字段查询
Entry . objects . filter (pub_date__lte = '2006-01-01' ) === select * from blog_entry where pub_date <= '2006-01-01'
startswith,endswith 以指定字符串开头或结尾
istartswith,iendswith 忽略大小写以指定字符串开头或结尾
year / month /day /week_day 对应日期和日期时间字段 ,匹配年/月/日/星期
Copy >>> Entry . objects . get (headline__exact = "Man bites dog" )
select ... where headline = 'Man bites dog'
>>> Blog . objects . get (id__exact = 14 )
>>> Blog . objects . get (id = 14 )
>>> Blog . objects . get (pk = 14 ) # django内置, id必须是主键
Entry . objects . filter (pub_date__year = 2005 ). order_by ( '-pub_date' , 'headline' ) # 降序,再升序
Entry . objects . order_by ( '?' ) # 随机排序
values
返回一个 ValuesQuerySet-------QuerySet的一个自雷,迭代时返回字典而不是模型实例对象
values() 接受可选的位置反水 fields , 它指定 SELECT 应该限制哪些字段。如果指定字段,每个字典将只包含指定的字段的键、值。如果没有指定字段,每个字段将包含数据库表中所有字段的键和值
Copy User . objects . values ( 'id' , 'username' )
values_list
与values()类似,只是在迭代时返回的元组而不是字典。每个元组包含传递给values_list()调用的字段值-----所有第一个元素为第一个字段,以此类推
Copy User . objects . values_list ( 'id' , 'username' )
defer
在一些复制的数据建模情况下,你的模型可能包含大量字段,其中一些可能包含大量数据(例如:文本),或者需要昂贵的处理来将它们转换为Python对象。如果你在某些情况下使用查询集的结果,当你最初获取数据时不知道是否需要某些特定字段,可以告诉Django不要从数据库中检索它们。
Copy User . objects . defer ( 'username' , 'email' )
删除对象
删除对象使用delete()。这个方法将立即删除对象且没有返回值
Copy Entry . objects . filter (pub_date__year = 2005 ). delete ()
拷贝模型实例
虽然没有建的方法用于拷贝模型实例,但还是很容易创建一个新的实例并让它的所有字段都拷贝过来。最简单的方法是,只需要将 pk 设置为 None
Copy blog = Blog (name = "My blog" , tagline = 'Blogging is easy' )
blog . save () # blog.pk == 1
blog . pk = None
blog . save () # blog.pk == 2
更新对象
更新对象使用 update()
Copy Entry . objects . filter (pub_date__year = 2007 ). update (headline = "Everything is the same" )
F()
F() 允许Django在未实际链接数据的情况下具有对数据库字段的值的引用,通常在更新数据时需要先从数据库里将原数据取出后放在内存里,然后编辑某些属性,最后提交。例如
Copy # 普通方法
order = Order . objects . get (orderid = '123456' )
order . amount += 1
order . save ()
# F() 方法
from django . db . models import F
order = Order . objects . get (orderid = '123456' )
order . amount = F ( 'amount' ) + 1
order . save ()
Q()
Q 对象(django.db.models.Q)可以对关键字参数进行封装,从而更好第应用多个查询,可以组合 and, or ,not 操作符,当一个操作符是用于两个Q的对象,它产生一个新的Q对象
Copy Order . objects . get (
Q (name__startswith = 'who' ),
Q (create_time = date ( 2016 , 10 , 2 )) | Q (create_time = date ( 2016 , 10 , 5 ))
)
# 相当于
select * from polls where name LIKE "who%" and (create_time= '2005-05-02' or create_time= '2016-010-05' )
序列化模型对象
Copy from django . core import serializers
data = serializers . serialize ( 'json' , SomeModel.objects. all ())
序列化子集
Copy from django . core import serializers
data = serializers . serialize ( 'json' , User.objects. all ()[ 0 : 10 ], fields = ( 'username' , 'is_active' ))
模型关系
多对一关系
django 是使用 django.db.models.ForeignKey 定义多多疑关系
ForeignKey 需要一个位置参数来制定本Model关联的Model,ForeignKey关联的Model是‘一’, ForeignKey所在的 Model是‘多‘
比如汽车和制造商的例子, 一辆汽车智能属于一个制造商,但是一个制造商有多辆汽车
Copy class Manufacturer ( models . Model ): # 制造商
name = models . CharField (max_length = 30 )
class Car ( models . Model ): # 汽车
manufacturer = models . ForeignKey (Manufacturer)
name = models . CharField (max_length = 30 )
# 正向查询 (ForeignKey所在的模型查询关联的模型)
car = Car . objects . get (pk = 2 )
car . manufacturer # 返回一条 Manufacturer 对象
# 反向查询 (ForeignKey指向的模型查询ForeignKey所在的模型)
manufacturer = Manufacturer . objects . get (pk = 1 )
manufacturer . car_set . all () # 返回多个 car 对象
add(obj, obj2,....) # 添加----指定的模型对象到管理的对象集中
create(**kwargs) # 创建一个新的对象,将它保存并放在关联的对象集中,返回新创建的对象
remove(obj1,obj2,...) # 从关联的对象集中删除指定的模型对象
clear() # 从关联的对象集中删除所有的对象
多对多关系
要实现多对多,就要使用 django.db.models.ManyToManyField类, 和 ForeignKey一样,它也有一个位置参数,用来指定和它管理的Model
如果不仅仅要知道两个 Model 之间是多对多的关系,还需要知道这个关系的更多信息,比如 Person 和 Group是多对多的关系,每个 person 可以在多个Group里,那么 group里可以有多个 person
Copy class Group ( models . Model ):
#....
class Person ( models . Model ):
groups = models . ManyToManyField (Group)
建议以被管理模型名称的复数形式作为 ManyToManyField 的名字
在哪个模型中设置 ManyToManyField 并不重要,在两个模型中任选一个即可 ----不要在两个模型中都设置
一对一关系
一多疑是通过 django.db.models.OneToOneField 来实现的,被管理的Model会被加上 Unique的限制, OneToOneField 要一个位置参数,与模型关联的类
当某个对象想扩展自另一个对象时,最常用的方式就是在这个对象的主键上添加一对一关系
Django 日志
Django 使用Python内建的loggin模块打印日志,Python 的logging配置由四个部分组成:
记录器
Logger为日志系统的入口。 每个logger命名都是bucket, 你可以向这个bucket写入需要处理的消息
每个logger都有一个日志级别。日志接不表示该logger将要处理的消息的严重性。Python日志级别:
Copy DEBUG : 用户调试目的底层系统消息
INFO : 普通的系统消息
WARNING : 表示出现一个较小的问题
ERROR : 表示出现一个较大的问题
CRITICAL : 表示出现一个致命的问题
写入logger 的每条消息都是一条日志。每条日志也具有一个日志级别,它表示对应的消息的严重性。每个日志记录还可以包含表述正在打印的事件的元信息
当一条消息传递给logger时,消息的日志级别将与logger的日志级别进行比较。日过消息的日志级别大于等于logger的日志级别,该消息将往下继续处理。如果小于,该消息将被忽略
logger一旦决定消息需要处理,它将传递该消息给一个Handler
Logger配置
logger对应的值是个自动,其每一个键都是logger的名字,每一个值又是个字典,描述了如何配置毒药的Logger实例
- level (可选的) logger 的级别 - propagate (可选的) logger的传播设置 - filters (可选的) logger 的filter 的标识付列表 - handlers (可选的) logger的handlers的标识符的列表
Copy # 配置示例
LOGGING = {
'loggers' :{
reboot : {
'handlers' : [ 'file_handler' , 'console_handler' ] ,
'level' : 'DEBUG'
}
}
}
处理程序 ---- Handler
Handler 决定如何处理logger中的每条消息。 它表示一个特定的日志行为,例如将消息写入到屏幕上,写到文件中或者写到网络 socket
与logger一样,handler也有一个日志级别。如果消息的日志级别小于handler的级别,handler将忽略改消息
Logger 可以有多个handler,而每个handler可以有不同的日志级别。利用这种方式,可以根据消息的重要性提供不同形式的处理
Copy LOGGING = {
'handlers' : {
'reboot' : {
"level" : 'DEBUG' ,
'class' : 'logging.StreamHandler' ,
'formatter' : 'simple' ,
}
}
}
过滤器---- Filters
Filter 用于对从logger传递给handler的日志记录进行额外的控制。
默认情况下,满足日志级别的任何消息都将被处理。通过安装 一个filter,你可以对日志处理添加额外的条件。例如,你可以安装一个filter,只运行处理来自特定源的ERROR消息
Filters还可以用户修改将要处理的日志记录的优先级。例如,如果日志记录满足特定的条件,你可以编写一个filter将日志记录从ERROR降为WARNING
Filters 可以安装在logger上或者Handler上; 多个filter可以串联起来实现多层filter行为
格式化----Formatters
最后,日志记录需要转换成文本。Formatter表示文本的格式。Fomatter通常由包行日志记录熟悉的python格式字符串组成;你也可以编写自定义的formatter来实现自己的格式
Copy LOGGINT = {
'formatters' : {
'reboot' : {
'format' : ' %(asctime)s - %(pathname)s : %(lineno)d [ %(levelname)s ] - %(message)s '
}
'simple' : {
'format' : ' %(asctime)s %(levelname)s %(message)s '
}
}
}
Format 日志小小格式
Django内置logger
django.request 处理与请求相关的日志,5xx响应爆出errror日志,4xx报出WARNING日志
django.db.backends 处理与数据库之间交互的日志
django.security.* 处理与安全相关的日志
django.db。backends。schemea处理数据库迁移时日志
更多参考
序列化和反序列化
在开发REST接口时,视图中做的最主要的三件事
将请求的数据(如:Json格式)转换为模型类对象(反序列化)
将模型类对象转换为响应的数据(如: Json格式)(序列化)
序列化
概念
将程序中的一个数据结构类型转化为其他格式(字典,xml,json等)。例如:将django中的模型类对象转换为json字符串,这个转换过程称之为序列化
序列化时机
当需要给前端响应模型数据时,需要将模型数据序列化成前端需要的格式
反序列化
概念
将其他格式(字典、Json、XML等)转换成程序中的数据,例如:将Json字符串转换成django模型类对象。这个过程称为反序列化
反序列化时机
当需要将用户发送的数据存储到数据库之前,需要反序列化
总结:
在开发REST接口时,在视图中需要做的最核心的事 是:
将数据库数据序列化为前端所需要的格式,并返回
将前端发送的数据反序列化为模型类对象,并保存到数据库中