django学习与实践
Django简介
Django是一个由Python写成的开放源代码的Web应用框架,它最初是被用来开发管理劳伦斯出版集团旗下的一些以新闻内容为主的网站,即CMS(内容管理系统)软件。 并于2005年7月在 BSD 许可证下发布。这套框架是以比利时的吉普赛爵士吉他手 Django Reinhardt 来命名的。由于 Django 的是在一个快节奏的新闻编辑室环境下开发的,它的目的是使常见的 Web 开发任务,快速和容易。
Django官网:https://www.djangoproject.com/
Django中文网:https://www.django.cn
Django的框架模式
-
Django采用了MTV设计模式
M Models 模型 T Templates 模板 V Views 视图
Django是一个Web应用框架,他是如何处理请求和响应的
URL ( urls.py )请求调度,当有缓存页面的时候直接返回内容。
视图函数( view.py )执行所请求的操作,通常包括读写数据库。
模型( models.py )定义了 Python 中的数据并与之交互。通常包含在一个关系数据库( MySQL、PostgreSQL SQLite 等),其他数据存储是可能的( XML、文本文件、LDAP、等)。
请求执行任务后,视图返回一个 HTTP 响应对象(通常是经过数据处理的一个模板)。可选的:视图可以保存一个版本的 HTTP 响应对象,返回携带一个时间戳,来告诉浏览器这个视图的更新时间。
模板通常返回 HTML 页面。Django 模板语言提供了 HTML 的语法及逻辑。
安装
第一行和第三行都可以随便使用
网络不好用第三行
pip install Django==2.1
#用国内的镜像网站,如下
pip install Django==2.1 -i https://pypi.douban.com/simple
导入Django模块
import django
print(django.get_version())
#结果:
2.1
基本配置
常用命令
查看django版本
python -m django --version
#结果
2.1
创建项目命令,项目名称是mysite
django-admin startproject mysite
创建应用程序命令,确保在manage.py文件时在同一个目录
#如果我们在项目外面,先要进入项目里
cd mysite
#windows使用dir查看当前在哪里,如果有manage.py就代表我们可以正确使用下面的命令
#创建应用程序
python manage.py startapp app01
启动django
python manage.py runserver
#默认端口是8000
#使用上面的命令就可以了,下面不经常用
#改端口
python manage.py runserver 8080
#改访问地址和端口
python manage.py runserver 0.0.0.0:8080
生成模型变化迁移文件
python manage.py makemigrations
运行模型迁移文件迁移到数据库中
python manage.py migrate
创建管理用户
python manage.py createsuperuser
user:输入:admin
email:不写也行
password:输入:admin123
验证password:输入:admin123
让你确认:输入:y
注:自动重新加载 runserver,根据需要开发服务器自动重新加载Python代码为每个请求。您不需要重新启动服务器代码更改生效。然而,像添加文件某些操作不触发重新启动,所以你必须重新启动在这些情况下的服务器。
基本目录结构及作用:
mysite/ # 项目的容器,名字随便起
manage.py # 命令行实用工具,以各种方式与该Django项目进行交互
mysite/ # 实际的Python项目
init.py # 空文件,导入不出错
settings.py # 这个Django项目配置
urls.py # 这个Django项目的URL声明; 一个Django驱动网站的“目录”
wsgi.py # 一个入口点为WSGI兼容的Web服务器,以满足您的项目
Django自带数据库,我们也可以选择不更改,项目开发中一般会更改使用的数据库,更改数据库配置在settings.py文件里
由于Django内部连接MySQL时使用的是MySQLdb模块
目前可以使用mysql来代替pymysql了
我们需要去下载mysql
pip install mysql
在settings中修改DATABASES
DATABASES = {
'default'{
'ENGINE':'django.db.backends.mysql',
'NAME':'你的数据库名称',
'USER':'你的用户名',
'PASSWORD':'你的密码',
'HOST':'127.0.0.1',
'PORT':'3306',
}
}
模板
也在settings里修改,主要放html文件
TEMPLATE_DIRS = (
os.path.join(BASE_DIR,'templates'),
)
静态文件
也在settings里修改,放css,js等文件
STATICFILES_DIRS = (
os.path.join(BASE_DIR,'static'),
)
路由系统
路由系统就像我们我们的书本的目录,书本的目录会告诉你那一页是什么,你翻到那一页就能看到相关的文字,路由系统就是,你对这个路由系统里的一个url地址发起了请求,路由系统会到对应的views函数去进行相关的处理,即这个url要用某个指定的views函数去处理。
来看下示例,django是怎么规定构造路由的
from app01 import views
urlpatterns = [
path(r'^login$',views.LoginView),
path(r'^register$',views.RegisterView),
]
from app1 import views
urlpatterns = [
url(r'^manage1/(\d)', views.manage1),
url(r'^manage2/(?P\w)/(?P\d)', views.manage2),
url(r'^manage3/(?P\w)', views.manage3,{'id':333}),]
注意:
url多传一个参数,那views对应的函数就要多接收一个参数
要不然会报错的
二级路由
如果映射url太多了,全写在一个urls.py文件里显得繁琐,所以出现了二级路由
就是项目的urls.py文件负责接收客户发过来请求它判断你传来的东西有没有它下面应用里的urls.py文件里有没有,如果有就告诉应用的的urls来接收,让它去处理,没有就给你报错
一级路由写法
项目的urls.py文件里
from django.urls import path, include
urlpatterns = [
path(r'app01/',include('app1.urls'))
]
Django是如何处理一个请求的
当用户请求从您的 Django 的网站页面,这是该系统遵循以确定哪些 Python 代码执行的算法:
Django 请求是 URL 配置模块配置。通常通过值 ROOT_URLCONF 设置,但如果传入 HttpRequest 对象具有 urlconf 属性(由中间件设置),它的值将代替的可以使用 ROOT_URLCONF 的设置。
Django 的负载是 Python 模块并寻找变量 urlpatterns。这是一个 django.conf.urls.url() 实例。
Django 的贯穿每个 URL 模式,从而,在所请求的 URL 匹配的第一个停止。
一旦某个正则表达式相匹配,就运行相对应的视图函数(或基于类的视图)。该视图被传递以下参数:
HttpRequest 对象。
如果匹配的正则表达式没有返回命名组,然后从正则表达式比赛是作为位置参数。
关键词参数是由由正则表达式匹配的任何命名组,由指定的可选参数的任何覆盖的 kwargs参数 django.conf.urls.url()。
如果没有正则表达式匹配,或者如果一个异常在这个过程中的任何一点时提出,Django的调用适当的错误处理视图。
官方示例
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),]
注意事项:
要捕获从URL中的值,用 括号括起来,会当参数传入views视图
没有必要添加一个斜体,因为每个URL都有。例如,它articles不是/articles.
在‘r’前面的每一个正则表达式是可选的,建议,它告诉python字符串是原始的,没有字符要转义
举例请求:
请求/articles/2005/03/将匹配列表中的第三项,Django将调用该函数。
views.month_archive(request,‘2005’,‘03’)
/articles/2005/3/ 不会匹配任何 URL 模式,因为在列表中的第三项中需要两位数字的月份。
/articles/2003/ 将匹配的列表,而不是第二个第一图案,因为该图案,以便测试,第一个是在第一测
试通过。随意利用顺序插入特殊情况是这样的。在这里,Django的将调用该函数
views.special_case_2003(request)
/articles/2003 不匹配任何这些模式,因为每个模式要求 URL 以斜线结束。
/articles/2003/03/03/ 将匹配的最终格局。Django 的将调用该函数。
views.article_detail(request,'2003', '03', '03')
命名组
上面的例子使用了简单的,非命名的正则表达式组(通过括号)来捕获URL的位,并通过他们的位置参数的视图,在更高级的用法,它可以使用命名正则表达式组成来捕获URL位,将它们作为关键字参数传递给视图。
例子:
from django.conf.urls import url
from .import views
urlpatterns = [
url(r'^articles/2003/$',views.special_case_2003),
url(r'^articles/(?P[0-9]{4})/$',views.year_archive),
url(r'^articles/(?P[0-9]{4})/(?P[0-9]{2})/$', views.month_archive),
url(r'^articles/(?P[0-9]{4})/(?P[0-9]{2})/(?P[0-9]{2})/$',views.article_detail),
]
这正好完成同样的事情,前面的例子,一个细微的差别:捕获的值传递给查看功能作为关键字参数,而不是位置参数。例如:
请求/articles/2005/03/会调用函数来代替,views.month_archive(request, year='2005',month='03')views.month_archive(request, '2005', '03')
请求/articles/2003/03/03/会调用该函数,views.article_detail(request, year='2003',month='03', day='03')
在实践中,这意味着你的 URLconf 稍微更明确,不容易参数顺序错误 - 你可以在你的意见'函数定义重新排序的参数。当然,这些优点来在简短的费用; 一些开发任务命名组的语法丑陋,太冗长。
匹配/分组算法
这里的URL配置解析器遵循算法,相对于正则表达式命名组与非命名组:
如果有任何命名参数,它会使用这些,而忽略非命名参数。
否则,它会通过所有非命名参数作为位置参数。
在这两种情况下,被赋予按任何额外的关键字参数传递额外的选项来查看功能也将被传递给视图请求/articles/2005/03/会调用函数来代替,views.month_archive(request,year=‘2005’,month=‘03’)
3> What the URLconf searches against
The URLconf searches against the requested URL, as a normal Python string. This does not include GET or POST parameters, or the domain name.
For example, in a request to https://www.example.com/myapp/, the URLconf will look for myapp/.
In a request to https://www.example.com/myapp/?page=3, the URLconf will look for myapp/.
该URL配置不看请求方法。换言之,所有的请求的方法,GET,POST 等将被路由到为相同的URL,相同的功能。
4> 捕获的参数总是字符串
每个捕获的参数发送到视图作为普通的 Python 字符串,无论什么样的匹配正则表达式匹配。
例如,在该URL配置行:
url(r'^articles/(?P[0-9]{4})/$', views.year_archive),
...的 year参数传递给 views.year_archive()将是一个字符串,
不是一个整数,即使 [0-9]{4} 将只匹配整数字符串。
5> 指定view的默认设置
一个方便的技巧是你的观点的论据指定默认参数。下面是一个例子的 RLconf 和看法:
urlconf
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^blogs/$',views.page),
url(r'blog/page(?P[0-9]+)/$',views.page),
]
views.py
def page(request,num='1'):
'''
处理语句块
'''
视图层
对逻辑负责处理用户的请求并返回相应,返回可以是HTML内容的网页,或者重定向,或者错误,或者字典
每个应用都有views.py文件
返回快捷键功能
render()
render(request,template_name,context=None,content_type=None,status=None,using=None)[source]
结合给定的模板与一个给定的上下文,返回一个字典HttpRespone在渲染文本对象
所需的参数
template_name 一个模板的使用或模板序列名称全称。如果序列是给定的,存在于第一个模板将被使用。
可选参数
context 一组字典的值添加到模板中,默认情况下这是一个孔子点
content_type MIME类型用于生成文档
status 为响应状态代码,默认值为200
using这个名字一个模板引擎将使用的模板
例子:
from django.shortcuts import render
def my_view(request):
return render(request,'myapp/index.html',{'fpp','bar',},content_type='application/xhyml+xml')
重定向
redirect()
redirect(to,permanent=False,*args,**kwargs)[source]
默认情况下,为临时重定向,通过permanent=True设置永久重定向
例子:
def my_view(request):
...
return redirect('/some/url/')
def my_view(request):
...
obj = MyModel.opbjects.get(...)
return redirect(object,permanent=True)
请求和响应对象
django使用请求和响应对象在系统间传递状态
当请求一个页面时,django创建一个HttpRequest对象包含原数据的请求,然后django加载适当的视图,通过HttpRequest作为视图函数的第一个参数,每个视图负责返回一个HttpResponse目标
HttpRequest对象
HttpRequest.scheme
一个字符串表示请求的计划方案(HTTP或者HTTPS)
通常HttpRequest.path
一个字符串的完整路径的请求
HTTPRequest.method
请求HTTP的方法,这里保证要大写
#伪代码
if request.method == 'GET':
'''
执行业务代码
返回结果
'''
return HttpResponse('结果')
#业务逻辑:如果请求来的是GET,你返回个GET字符串
#真代码
class GETView(objects):
def getview(self,request):
if request.method == 'GET':
return HttpResponse('GET')
if request.method == 'GET':
return HttpResponse('GET')
elif request.method == 'POST':
return HttpResponse('POST')
elif request.method == 'PUT':
return HttpResponse('PUT')
elif request.method == 'DELETE':
return HttpResponse('DELETE')
else:
return HttpResponse('来了老弟!')
字典包含所有给定的HTTP GET 参数对象
HttpRequest.GET
字典包含所有给定的HTTP POST 参数对象,提供请求包含表单数据
HttpRequest.POST
一个标准的python字典,包含所有的COOKIES,KEY和VALUES都是字符串
字典包含所有上传的文件
HttpRequest.FILES
语法:
HttpRequest.FILES
filename #上传的文件名
content_type #上传文件的类型
content #上传文件的内容
HttpRequest.META
一个标准的Python字典包含所有可用的HTTP头,可用标题取决于客户端和服务器。以下是例子
CONTENT_LENGTH | 请求体的长度(一个字符串 |
---|---|
CONTENT_TYPE | 请求体的类型 |
HTTP_ACCEPT | 为响应–可以接受的内容类型 |
HTTP_ACCEPT_ENCODING | 接受编码的响应 |
HTTP_ACCEPT_LANGUAGE | 接受语言的反应 |
HTTP_HOST | 客户端发送的HTTP主机头 |
HTTP_REFERER | 参考页面 |
HTTP_USER_AGENT | 客户端的用户代理字符串 |
QUERY_STRING | 查询字符串,作为一个单一的(分析的)字符串 |
REMOTE_ADDR | 客户端的IP地址 |
REMOTE_HOST | 客户端的主机名 |
REMOTE_USER | 用户通过Web服务器的身份验证 |
REQUEST_METHOD | 字符串,如"GET"或"POST" |
SERVER_NAME | 服务器的主机名 |
SERVER_PORT | 服务器的端口(一个字符串) |
HttpResponse对象
对于HttpRequest 对象来说,是由django自动创建的,但是,HttpResponse 对象就必须我们自己创建。每个 view 请求处理方法必须返回一个 HttpResponse 对象。
HttpResponse 类在 django.http.HttpResponse
字符串使用:
典型的用法是通过页面的内容,为一个字符串
for django.http import HttpResponse
response = HttpResponse("hello world")
response = HttpResponse("hello world",content_type="text/plain")
如果你想添加内容的增量
response = HttpResponse()
response.write("hello world")
response.write("你好")
#特性与方法:
HttpResponse.content
一个bytestring代表内容HttpResponse.charset
一个字符串的字符集表示的响应将编码
HttpResponse.status_code
HTTP状态代码为响应码
HttpResponse.streaming
这个属性永远为假,一般用于中间件
HttpResponse.closed
方法:
先写的代码,后写的注释
HttpResponse.__init__(content='',content_type=None,status=200,reason=None,charset=None)[source]
#实例化类自动执行的方法
HttpResponse.__setitem__(header,value)
#为给定值给定的标题名称,都是字符串
HttpResponse.__delitem__(header)
#删除标题的名称,不区分大小写
HttpResponse.__getitem__(header)
#获取给定标题名称。不区分大小写。
HttpResponse.has_header(header)
#检查是否具有给定名称的一个标题
HttpResponse.setdefault(header, value)
#设置一个标题,除非它已经设置。
HttpResponse.set_cookie(key, value='', max_age=None, expires=None, path='/', domain=None, secure=None, httponly=False)
#设置一个cookie。参数跟标准库的Cookie对象差不多
HttpResponse.set_signed_cookie(key, value, salt='', max_age=None, expires=None, path='/', domain=None, secure=None, httponly=True)
#加密cookice,可以用 HttpRequest.get_signed_cookie() 获取,当然你也可以加盐
HttpResponse.delete_cookie(key, path='/', domain=None)
#删除Cookie与给定键。
#HttpResponse子类:
class HttpResponseRedirect[source]
构造函数的第一个参数是必需的路径redirectto,这是一个完全合格的URL,一个合格的URL(https://www.baidu.com/搜索/),没有一个绝对的路径(例如:域搜索//),甚至是相对路径(如‘/’),
optionalconstructor参数。请注意,这将返回一个HTTP状态代码302。
class HttpResponsePermanentRedirect[source]
像httpresponseredirect,但它返回一个永久重定向(HTTP状态代码301)而不是“发现”的重定向(状态代码302)
class HttpResponseNotModified[source]
构造函数不带任何参数和NO含量应该被添加到这一反应。使用指定一个页面没有被modifiedsince用户的最后一个请求(状态代码304)。
class HttpResponseBadRequest[source]
就像HttpResponse但使用400状态码
class HttpResponseNotFound[source]
就像HttpResponse但使用404状态码
class HttpResponseForbidden[source]
就像HttpResponse但使用403状态码
class HttpResponseNotAllowed[source]
像HttpResponse,但使用405状态码。第一argumentto构造函数要求准许清单的方法(如(get,后])
class HttpResponseGone[source]
就像HttpResponse但使用410状态码
class HttpResponseServerError[source]
就像HttpResponse但使用500状态码
模板层
作为一个Web框架,Django需要模板,模板包含所需的HTML输出静态部分以及动态内容插入。
模板的执行
from datetime import datetime
def current_datetime(request):
now = datetime.datetime.now()
html = "it is now %s" % now
return HttpResponse(html)
from django import template
t = template.Templatge("my name is {{name}}")
c = template.Context({"name":"老王"})
print(t.render(c))
import datetime
from django import template
import DjangoDemo.settings
now = datetime.datetime.now()
fp = open(settings.BASE_DIR+"/templates/home/index.html")
t = template.Template(fp.read())
fp.close()
html = t.render(template.Context({'current_date':now}))
return HttpResponse(html)
from django.template.loader import get_template
from django.template import Context
from django.http import HttpResponse
import datetime
def current_datetime(request):
now = datetime.datetime.now()
t = get_template('current_datetime.html')
html = t.render(Content({'current_date':now}))
return HttpResponse(html)
reurn render_to_response("Account/login.html",data,context_instance=RequestContext(request))
模板语言
模板中也有自己的语言,该语言实现数据展示
{{item}}
{% for item in item_list %}
{{item}}
{% endfor %}
forloop.counter
forloop.first
forloop.last
{% if ordered_warranty %}
{% else %}
{% endif %}
母板:{% block title %}{% endblock %}
子板: {% extends"base.html" %}
帮助方法:
{{ item.event_start|date:"Y-m-d H:i:s"}}
{{ bio|truncatewords:"30" }}
{{ my_list|first|upper }}
{{ name|lower }}
自定义simple_tag
在app中创建templatetags模块
创建任意名字的.py文件
!/usr/bin/env python
coding:utf-8
from django import template
from django.utils.safestring import makesafe
from django.template.base import resolve_variable,Node,TemplateSyntaxError
register = template.Libary()
@register.simple_tag
def my_simple_time(a1,a2,a3):
return a1+a2+a3
@register.simple_tag
def my_input(id,arg):
result = " "%(id,arg)
return mark_safe(result)
在使用自定义simple_tag的html文件中导入之前创建任意名字的.py文件
{% load xx %}
//使用simple_tag
{% my_simple_time 123 %}
在settings中配置当前app,不然django无法找到自定义的simple_tag
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'app01',
)
Models层
Django提供了一个抽象层(Model)的构建和管理Web应用程序的数据
每个模型是一个python类,子类 django.db.models.model
模型中的每个属性代表数据库中的一个字段。
例子:
from django.db import models
class Person(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
参数与字段
models.AutoField
#自增=int(11),如果没有的化,默认会生成一个名称为id的列,如果要显示的自定义的一个自增列,必须将给列设置为主键,主键设置方式:primary_key=True
models.CharField
#字符串字符段,必须有max_length参数
models.BooleanField
#布尔类型=tinyint(1),不能为空,Blank=True
models.ComaSeparatedlntegerField
#用逗号分隔的数字=varchar,继承CharField,所以必须max_length参数
models.DateField
#日期类型 date,对于参数,auto_now=True则每次更新都会更新这个事件,auto_now_add则只是第一次创建添加,之后的更新不再改变
models.DateTimeField
#日期类型 datetime 同DateField参数一样
models.Decimal
#十进制小数类型=decimal,必须制定整数位max_digits和小数位decimal_places
models.EmailField
#字符串类型(正则表达式邮箱)=varchar,对字符串进行正则表达式
models.FloatField
#浮点类型=double
models.IntegerField
#整型
models.BigIntegerField
#长整型
integer_field_ranges = {
'SmallIntegerField': (-32768, 32767),
'IntegerField': (-2147483648, 2147483647),
'BigIntegerField': (-9223372036854775808, 9223372036854775807),
'PositiveSmallIntegerField': (0, 32767),
'PositiveIntegerField': (0, 2147483647),
}
models.IPAddressField
#字符串类型(ipv4正则表达式)
models.GenericIPAddressField
#字符串类型(ipv4和ivp6是可选的),参数protocol可以是:both、ipv、ipv6,验证时,会根据设置报错
models.NullBooleanField
#允许为空的布尔类型
models.PositivenlntegerField
#正integer
models.PositiveSmallIntegerField
#正smallinteger
models.SlugField
#减号、下划线、字母、数字
models.SmallInterField
#数字,数据库中的字段有:tinyint、smallint、int、bigint
models.TextField
#字符串=longtext
models.TimeField
#时间 HH:MM[:ss[.uuuuuuu]]
models.URLField
#字符串,地址正则表达式
models.BinaryField
#二进制
models.ImageField
#图片
models.FilePathField
#文件
null=True
#数据库中字段是否可以为空
blank=True
#django的Admin中添加数据是是否允许空值
primary_key=False
#主键,对AutoField设置主键后,就会代替原来的自增id列
auto_now
#自动创建,无论添加或修改,都是当前操作的时间
auto_now_add
#自动创建爱你,永远是创建时的时间
choices
#choices例子
GENDER_CHOICE = (
(u'M',u'Male'),
(u'F',u'Female'),
)
gender = models.CharField(max_length=2,choices=GENDER_CHOICE)
max_length
default
#默认值
verbose_name
#Admin中字段的显示名称
nameidb_column
#数据库中的字段名称
unique=True
#不允许重复
db_index=True
#数据库索引
editable=True
#在Admin里是否可编辑
error_messages=None
#错误提示
auto_created=False
#自动创建