建议安装虚拟环境以适合不同版本的django网站开发(这里我介绍的是virtualenv和virtualenvwrapper):
virtualenv:
1、windows系统安装virtualenv:
pip install virtualenv
或者:
pip3 install virtualenv
2、创建虚拟环境:
virtualenv 虚拟环境名字
(默认会在你安装virtualenv的路径下创建一个虚拟环境)
3、进入虚拟环境:
(1)cd到你的虚拟环境所在的文件位置
(2)cd进入Script文件夹
(3)执行activate脚本
4、退出虚拟环境:
执行deactivate脚本
5、设置虚拟环境python解释器:
virtualenv -p C:[python.exe的路径][虚拟环境名称,例如hy.env]
virtualenvwrapper:
1、windows系统安装virtualenv:
pip install virtualenvwrapper -win
2、创建虚拟环境:
virtualenv 虚拟环境名字
3、进入虚拟环境:
work on 虚拟环境名字
4、退出虚拟环境:
deactivate
5、删除虚拟环境:
rmvirtualenv 虚拟环境名字
6、列出所有的虚拟环境
lsvirtualenv
7、进入虚拟环境所在目录
cdvirtualenv
8、设置环境变量:
高级系统设置->环境变量->系统环境变量WORKON_HOME
9、设置虚拟环境python解释器:
mkvirtualenv --python=C:\[python.exe的路径][虚拟环境名称,例如hy.env]
1、URL(uniform resource located,统一资源定位符)
protocol://hostname[:port]/path/[:parameters][?query]#fregment
protocol:访问协议
hostname:主机域名
port:端口(网站域名后面一般都存在着默认端口,如80、8000等)
path:路径
parameters:资源
query:查询字符串
fregment:锚点
注意:有部分网络URL登录后还存在着身份验证
2、web服务器和应用服务器及web应用框架
web服务器:负责处理Http请求,相应静态文件(常用的是Apach、Ngix以及微软的IIS)
应用服务器:负责处理逻辑(php、python代码)
web应用框架:一般使用了某种语言,是封装了常用的web功能的框架
win+R打开终端
1、(在终端中执行)下载django:pip install django==2.2(版本号)
2、查看本机Django版本(在终端中执行):python -m django --version
3、创建一个django项目,并运行(在终端中执行,也可以再pycharm中执行):
(1)创建一个project:django-admin startproject exercise(project名称)
注意:需要避免使用与内置的Python或Django组建来命名项目
project下的文件:
exercise(根目录文件):根目录只是您的项目的容器。它的名称对Django无关紧要
exercise(project内同名文件):目录是项目的实际Python包。它的名称是Python包名称,可以使用它来导入其中的任何内容
manage.py:一个命令行实用程序,可让您以各种方式与该Django项目进行交互
查看manage.py所有的功能(在终端中执行):
python manage.py help
settings.py:此Django项目的设置/配置。
urls.py:此Django项目的URL声明;Django支持的网站的“目录”
wsgi.py:兼容WSGI的Web服务器为您的项目提供服务的入口点。
(2)进入project:cd exercise(project名称)
(3)创建一个app:python manage.py startapp user(app名称)
注意:创建完app后,如果想要在项目中使用改app,请在settings.py的INSTALLED_APPS中插入以下语句
(以user为例):user.apps.UserConfig
用来在项目中激活app
(4)运行project:python manage.py runserver 8000(PORT,端口号)
如果想要更改服务器IP,则将其与端口号一起传递:python manage.py runserver 0.8000
0是0.0.0.0的快捷方式,该方式可以在指定的局域网中运行,但需要在settings.py中的ALLOWED_HOST=[’’]加入本机的IP地址,不加入的话在同一局域网下访问的用户将无法获取网页。
(5)更改settings.py中的部分设置:
更改时区(上海时区):time_zone = “Asia/Shanghai”
更改语言(中文):LANGUAGE = ‘zh-hans’
路由映射的设置:
项目文件中的urls.py:
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/',admin.site.urls),#这个是网站的站点,前期学习用不到
path('user/', include('user.urls'))#链接user这个app下的urls路由文件
]
注意:
include()会截断到目前为止匹配的URL的任何部分,并将剩余的字符串发送到包含的URLconf中以进行进一步处理
假设网页中我们传递的URL为 http://127.0.0.1:8000/user/welcome
那么在执行到include('user.urls')时会把http://127.0.0.1:8000/user/截断,并将welcome(剩余字符串)传递到user这个app下的urls.py文件中去匹配
user这个app下的urls.py:
from . import views #导入user这个app下的views视图文件
from django.urls import path
urlpatterns = [
path('', views.index_handler, name='index'), #访问views视图文件下的index_handler视图函数
path('welcome/', views.welcome_handler, name='welcome')
]
注意:
(1)在这里,127.0.0.1:8000/user/welcome和127.0.0.1:8000/user/分别对应视图函数welcome_handler和index_handler,这样的一个Host地址对应一个视图函数的对应关系我们把它称作"路由映射"
(2)这里的name属性使用来给url取一个名字,以后配合redirect和reverse做url反转时使用(为了执行URL反向)
user这个app下的views.py:
from django.http import HttpResponse #HttpResponse是一个直接将数据渲染到网页上的函数
def index_handler(request):
return HttpResponse("index")
def welcome_handler(request):
return HttpResponse('welcome')
DEBUG模式分析:
(Settings.py中的DEBUG=True,即开启DEBUG模式):
1、对项目或者是app的内容发生更改时(或摁下ctrl+s)时,Django文件将会自动重启项目
2、为Django项目打印调试信息,当项目发生BUG时会自动报错
3、在生产环境下,禁止开启DEBUG模式,为防止黑客等发现网页漏洞,
但必须在settings.py中设置ALLOWED_HOST=[],否则谁都无法访问页面
URL调度
1、Django处理一个请求的步骤:
(1)Django确定要使用的根URLconf模块。通常,这是ROOT_URLCONF(一个字符串,在settings.py中可以找到)设置的值,
但是如果传入HttpRequest对象具有urlconf属性(由中间件设置),则将使用其值代替 ROOT_URLCONF设置。
(2)jango加载该Python模块并查找变量 urlpatterns(必须是这个名字)。
这应该是一个序列的 django.urls.path()和/或django.urls.re_path()实例。
(3)Django按顺序遍历每个URL模式,并在第一个与请求的URL匹配的URL模式处停止。
(4)一旦其中一个URL模式匹配,Django就会导入并调用给定的视图,该视图是一个简单的Python函数(或基于类的视图).
将传递以下参数给视图函数:
·HttpRequest的实例
·如果匹配的URL模式未返回命名组,则来自正则表达式的匹配项将作为位置参数提供。
·关键字参数由与路径表达式匹配的任何命名部分组成,并由django.urls.path()或django.urls.re_path()的可选kwargs参数中指定的任何参数覆盖
例子:
project中urls.py中文件代码:
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('user/', include('user.urls'))
]
app中urls.py中文件代码:
from django.urls import path
from . import views
app_name = 'user'
urlpatterns = [
path('', views.index_handler, name='index'),
path('detail/<username>/<int:age>/<str:birthday>', views.detail_handler, name='detail'),
]
注意:app中urls.py文件在创建完app时不存在,需要自己手动添加,
其中的代码可以使用pycharm中常用代码快捷键自动填充
pycharm中常用代码快捷键的设置方法:
Files->Settings->search框中搜索Live template->点击右边的+->Live template->
Abbrevation:设置快捷键
Template Text:代码块
Define:适用语言
app中views.py中文件代码:
from django.shortcuts import render
from django.http import HttpResponse
# Create your views here.
def index_handler(request):
print(type(request))
return HttpResponse("Hello world")
def detail_handler(request, username, age, birthday):
text = "The boy named %s is %d year old because he is born at %s"
return HttpResponse(text % (username, age, birthday))
2、URL获取参数:
(1)要从URL捕获值,使用尖括号。例如上文中的path('detail/<username>/<int:age>/<str:birthday>', views.detail_handler, name='detail'),
(2)捕获的值可以选择包括转换器类型(默认的转换器是str)。例如,用于 <int:name>捕获整数参数。如果不包括转换器/,则匹配除字符之外的任何字符串。
(3)无需添加斜杠,因为每个URL都有该斜杠。例如detail,不是/detail。
(4)视图函数中的变量名必须和URL中定义的一样。
例如:
urls.py:
path('detail/<username>/<int:age>/<str:birthday>', views.detail_handler, name='detail'),
views.py:
def detail_handler(request, username, age, birthday):
URL传递默认参数:
urls.py:
path('detail/<username>/<int:age>', views.detail_handler, name='detail'),
网页上输入的URL:http://127.0.0.1:8000/user/detail/Mike/
在此处urls中未传递age,则我们可以使用赋值默认参数来自定义参数值
代码图下所示:
views.py:
def detail_handler(request, username, age=18):
将age的值默认赋值为18
URL路径传参类型转换器:
·str-匹配除路径分隔符之外的任何非空字符串'/'。如果表达式中不包含转换器,则为默认设置。
·int-匹配零或任何正整数。返回一个int。
·slug-匹配由ASCII字母或数字以及连字符和下划线字符组成的任何条形字符串。例如, building-your-1st-django-site。
·uuid-匹配格式化的UUID。为防止多个URL映射到同一页面,必须包含破折号,并且字母必须小写。
uuid的正则表达式(必须满足这个条件的字符串):regex = '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}'
例如,075194d3-6885-417e-a8a8-6c931e272f00。返回一个 UUID实例。
·path-匹配任何非空字符串,包括路径分隔符 '/'。这样,您就可以与完整的URL路径进行匹配,而不仅仅是与URL路径的一部分进行匹配str。
自定义路径转换器:
在项目或者app目录下创建一个converters.py(这个名字python可以简单的辨认)文件,在里面存放所有的converter(转换器)
自定义转换器需要以下元素:
1:regex类属性,作为一个正则表达式表示的字符串。
2:to_python方法,用于将匹配的字符串转换为应传递给视图函数的类型
如果无法转换给定值,则应抛出异常raise ValueErrorValueError
如果不匹配,因此将404响应发送给用户
3:to_url方法,用于将Python类型转换为要在URL中使用的字符串。to_url(self, value)
实例代码如下:
app中__init__.py文件代码:
from .converters import BirthdayConverter
app中converters.py文件代码:
from django.urls import register_converter, converters
class BirthdayConverter:
regex = '[0-9]{4}-[0-9]{2}-[0-9]{2}'
def to_python(self, value):
list = value.split('-')
return '.'.join(list)
def to_url(self, value):
list = value.split('.')
return '-'.join(list)
register_converter(BirthdayConverter, 'bc')#用于把BirthdayConverster注册到这个django项目中去,后面一个参数是该路径转换器的别名,即在外部使用时用的名字
app中urls.py中文件代码:
from django.urls import path
from . import views
from django.urls import register_converter
app_name = 'user'
urlpatterns = [
path('', views.index_handler, name='index'),
path('detail/<username>/<int:age>/<str:birthday>', views.detail_handler, name='detail'),
path('show/<bc:birthday>', views.show_handler, name='show')
]
app中views.py中文件代码:
from django.shortcuts import render, reverse
from django.http import HttpResponse
# Create your views here.
def show_handler(request, birthday):
print(reverse('user:show', kwargs={'birthday':birthday}))
return HttpResponse(birthday)
3、URL传递额外的参数:
path()函数可以使用可选参数的第三个方法,该参数应该是传递给view函数的额外关键字参数的字典。
urls.py文件中的代码:
from django.urls import path
from . import views
app_name = 'goods'
urlpatterns = [
path('', views.index_handler, name='index'),
path('choose', views.choose_handler, {'sex': 'boy'}, name='choose')
]
views.py文件中的代码:
from django.shortcuts import render
from django.http import HttpResponse
# Create your views here.
def index_handler(request):
return HttpResponse('goods')
def choose_handler(request, sex):
print(sex)
return HttpResponse('haha')
给include()添加额外参数:
若在include()添加额外参数,那么include指向的url的路径path每一项都会带有该参数
project中的urls.py中的代码:
from django.urls import include, path
urlpatterns = [
path('blog/', include('blog.urls'), {'blog_id': 3}),
]
blog这个app中的urls.py的代码:
from django.urls import path
from . import views
urlpatterns = [
path('archive/', views.archive),
path('about/', views.about),
]
等价于下面的代码:
project中的urls.py中的代码:
from django.urls import include, path
urlpatterns = [
path('blog/', include('blog.urls')),
]
blog这个app中的urls.py的代码:
from django.urls import path
from . import views
urlpatterns = [
path('archive/', views.archive, {'blog_id': 3}),
path('about/', views.about, {'blog_id': 3}),
]
URL传递查询字符串:
以http://127.0.0.1:8000/user/?username=Mike&age=18为例:
?后面的字符叫做查询字符串,多个查询字符串之间用&链接
查询字符串一般是通过get请求上传的,所以获取查询字符串用类似以下实例代码:
app中urls.py中文件代码:
from django.urls import path
from . import views
app_name = 'user'
urlpatterns = [
path('', views.index_handler, name='index'),
]
app中views.py中文件代码:
from django.shortcuts import render
from django.http import HttpResponse
# Create your views here.
def index_handler(request):
username = request.GET.get('username')
age = request.GET.get('age')
text = "The boy named %s is %s year old"
return HttpResponse(text % (username, age))
在urls.py中包括其他的UROConf:
例如:
项目文件下的urls.py中的代码:
from django.contrib import admin
from django.urls import path, include
from user import views as user_views
extra_patterns = [
path('add/', user_views.add_handler)
path('delete/', user_views.delete_handler)
path('update/', user_views.update_handler)
path('search/', user_views.search_handler)
]
urlpatterns = [
path('admin/', admin.site.urls),
path('user/', include('user.urls')),
path('goods/', include(extra_patterns)),
]
提示:
在此示例中,/goods/users/将由user_views.report()来渲染Django视图处理 。这可用于从URLconf中删除重复使用单个模式前缀的冗余。
如果全部写入urlpatterns(如下所示):
urlpatterns = [
path('admin/', admin.site.urls),
path('user/', include('user.urls')),
path('goods/add/', user_views.add_handler)
path('goods/delete/', user_views.delete_handler)
path('goods/update/', user_views.update_handler)
path('goods/search/', user_views.search_handler)
]
会造成goods代码被复写了多次,造成了URL前缀冗余。
我们可以通过只声明一次公共路径前缀(path('goods/', include(extra_patterns)),)并将不同的后缀分组来改善这一点
views视图函数:
只是一个Python函数,它接受Web请求并返回Web响应。
此响应可以是网页的HTML内容,重定向,404错误,XML文档或图像……
views视图函数必须有一个参数,且其名字必须为Request(网络端口运用后其返回值为HttpResponseBase类对象或其子类对象)
可以在app中views.py文件中使用以下代码查看他的种类:
from django.shortcuts import render
from django.http import HttpResponse
# Create your views here.
def index_handler(request):
print(type(request)) #会返回一个WSGI对象<class 'django.core.handlers.wsgi.WSGIRequest'>
return HttpResponse("Hello world")
URL的反向解析
Django提供了用于执行URL反转的工具,这些工具与需要URL的不同层相匹配:
(1)在模板中:使用url模板标记。
(2)在Python代码中:使用reverse()函数。
(3)在与Django模型实例的URL处理有关的更高级别的代码中:get_absolute_url()方法。
reverse和redirect
导包:from django.shortcuts import rende, redirect, reverse
1、reverse(URL反向解析处理器):根据name的值反向获取URL地址
也可以定义参数urlconf=直接写path路径(默认urlconf=None)
·在反转时有时需要传递参数:args=None 传递无关键字参数 kwargs=None 传递关键字参数
例如上述路径转换器中实例:
app中views.py中文件代码:
from django.shortcuts import render, reverse
from django.http import HttpResponse
# Create your views here.
def show_handler(request, birthday):
print(reverse('user:show', kwargs={'birthday':birthday}))
return HttpResponse(birthday)
app中urls.py中文件代码:
from django.urls import path
from . import views
from django.urls import register_converter
app_name = 'user'
urlpatterns = [
path('', views.index_handler, name='index'),
path('show/<bc:birthday>', views.show_handler, name='show')
]
·在反转时传递查询字符串:
此时不能使用拼接,只能手动传递
例如以下实例:
app中views.py中文件代码:
def show_handler(request, birthday):
url = reverse('user:index')+"?next=/" #手动的添加了查询字符串
return redirect(url)
运行后在网页中的得到的URL为:127.0.0.1:8000/user/?next=/
2、redirect(重定向):重定向URL路径
一般来说redirect和reverse是一起使用的
正则表达式:
通常用来检索、替换那些符合某个模式(规则)的文本
正则表达式基础:
符号 说明
\d 数字
\D 非数字
\w 数字、字母、下划线
\W 非数字、字母、下划线
\s 空格(包括制表符、换页符等等)
. 除了"\n"和"\t"的所有字符
* 出现次数>=0
+ 出现次数>=1
{n} 出现次数=n
{n,m} n<=出现次数<=m
^ 以……开头
$ 以……结尾
re_path():
如果路径和转换器语法不足以定义URL模式,则还可以使用正则表达式。为此,请使用 re_path()代替path()。
re_path()比path()多了一层正则判断
导包:
from django.urls import re_path
re_path()的使用:
repath(r"[含正则表达式的URL地址]", views.[视图函数], name=’[名字]’)
注意:这里的r是raw的缩写,表示原生字符串(不会转义)
re_path()中传递参数:
以下面的代码为例:
path(‘detail/int:age’, views.detail_handler, name=‘detail’),
可以将其改写成以下形式:
path(r’^detail/(?P[\d+])$’, views.detail_handler, name=‘detail’),
注意:(?P<变量名>)是用来定义变量的
(1)嵌套参数
正则表达式允许嵌套参数,而Django会解析它们并将其传递给视图。
反转时,Django将尝试填充所有外部捕获的参数,而忽略任何嵌套的捕获参数。
考虑以下URL模式,这些URL模式可以选择采用page参数:
(2)使用未命名的正则表达式组:
除了命名组语法(例如)(?P<year>[0-9]{4})外,您还可以使用较短的未命名组(例如)([0-9]{4})。
但是不建议特别使用此用法,因为这样可以更轻松地在匹配的预期含义和视图的参数之间意外引入错误。
注意:
任何未命名的组都会被忽略,只有命名的组才会传递给视图函数。
urlpatterns都是在首次访问时对每个正则表达式进行编译。这使系统运行异常迅速。
urlpatterns应该是一个序列的path() 和/或re_path()实例。
命名空间(应用命名空间和实例命名空间):
命名空间的概念:
URL名称空间允许您唯一地反向命名URL模式,即使不同的应用程序使用相同的URL名称。由于单个应用程序的多个实例将共享命名的URL,因此名称空间提供了一种区分这些命名的URL的方法。
1、回顾一下映射:
project的urls.py:
urlpatterns = [
path(‘user/’, include(‘user.urls’))
]
app的urls.py:
urlpatterns = [
path(’ ', views.index_handler, name=‘index’)
]
将URL(http://127.0.0.1:8000/user/)表示成对应的视图函数(index_handler)的过程叫做映射
2、应用命名空间:
在多个app文件中含有一样的URL映射,为防止反转URL发生混淆,采用应用命名空间
实例代码:
user.app下的urls.py文件:
urlpatterns = [
path(' ', views.index_handler)
]
goods.app下的urls.py文件:
urlpatterns = [
path(' ', views.index_handler)
]
在URL反转(reverse('index'))时在两个app下都有一个名字叫做index的URL映射,容易发生混淆
解决方案:
user.app下的urls.py文件:
app_name = 'user' #应用命名空间的定义
urlpatterns = [
path(' ', views.index_handler, name='index')
]
goods.app下的urls.py文件:
app_name = 'goods'
urlpatterns = [
path(' ', views.index_handler, name='index')
]
那么以后在反转URL时就可以使用应用命名空间来区分了:
reverse('user:index')
reverse('goods:index')
3、实例命名空间
一个app可以创建多个实例,多个实例URL映射到同一app,,为防止反转URL时应用命名空间发生混淆,采用实例命名空间
实例代码:
project下的urls.py:
urlpatterns = [
path('user/', include('robot.urls'), name='user'),
path('goods/', include('robot.urls'), name='goods'),
]
robot.app下的urls.py:
app_name = 'robot'
urlpatterns = [
path('login/', views.login_handler, name='login'),
path('register/', views.register_handler, name='register')
]
robot.app下的views.py:
from django.shortcuts import render, redirect, reverse
from django.http import HttpResponse
# Create your views here.
def index_handler(request):
return HttpResponse('goods')
def choose_handler(request, sex):
print(sex)
return HttpResponse('haha')
def login_handler(request):
username = request.GET.get('username')
if username:
return redirect(reverse('goods:index'))
else:
return redirect(reverse('goods:register'))
def register_handler(request):
return HttpResponse("register")
在URL反转(reverse('goods:index'))时可能会出现以下情况:
(1)网页URL:http://127.0.0.1:8000/goods/login/
执行以后的URL:http://127.0.0.1:8000/user/login/
(2)网页URL:http://127.0.0.1:8000/user/login/
执行以后的URL:http://127.0.0.1:8000/user/login/
解决方法:
project下的urls.py:
urlpatterns = [
path('user/', include('robot.urls', name='user'), namespace='user),
path('goods/', include('robot.urls', name='goods'), namespace='goods')
]
robot.app下的views.py:
def login_handler(request):
username = request.GET.get('username')
current_namespace = request.resolver_match.namespace #获取当前URL下的命名空间
text = "the current namespace is %s" % current_namespace
return HttpResponse(text)
引入namespace实例命名空间
错误处理:
当Django无法找到所请求URL的匹配项时,或引发异常时,Django会调用一个错误处理视图。
在Django中返回HTTP错误代码很容易。HttpResponse除了200(表示“ OK”)以外,还有许多常见HTTP状态代码的子类
补充:常见的错误码
错误码 含义
400 请求参数错误,Bad Request
403 没有权限访问相关信息
404 没有找到指定的URL
405 请求的method错误
500 服务器内部错误
502 部署异常,一般是Ngix启动,wsgi引发的问题
只需返回这些子类之一的实例而不是普通实例HttpResponse即可表示错误。例如:
urls.py中代码:
from django.urls import path, re_path
from . import views
app_name = 'user'
urlpatterns = [
path('', views.index_handler, name='index'),
path('detail/<username>/<int:age>/<str:birthday>', views.detail_handler, name='detail'),
path('show/', views.show_handler, name='show'),
]
views.py中代码:
from django.shortcuts import render, reverse, redirect
from django.http import HttpResponse, HttpResponseNotFound
# Create your views here.
def double_handler(request, page_number):
print(page_number)
return HttpResponse('success')
def show_handler(request):
try:
url = reverse('user:double', kwargs={
'username': 'John'
})
except:
return HttpResponseNotFound('<h1>404 Not Found</h1>')
return redirect(url)
由于404错误是迄今为止最常见的HTTP错误,因此有一种更简单的方法来处理这些错误:
from django.shortcuts import render, reverse, redirect
from django.http import HttpResponse, Http404
# Create your views here.
def double_handler(request, page_number):
print(page_number)
return HttpResponse('success')
def show_handler(request):
try:
url = reverse('user:double', kwargs={
'username': 'John'
})
except:
raise Http404('<h1>404 Not Found</h1>')
return redirect(url)
为了在Django返回404时显示自定义HTML,您可以创建一个名为404.html的HTML模板并将其放置在项目的tempaltes文件中。也可以在相对应的app下创建一个templates文件,把名为404.html的HTML模板放入其中。
注意:此时Settings.py中的DEBUG需要被设置为False,并且在ALLOWED{_HOST=[]必须设置IP,否则看不到效果
templates模板文件中的代码:
400.html(必须与错误的名称一致):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
你的数据在天上漫步呢!
</body>
</html>
urls.py文件中的代码:
path('detail/<username>/<int:age>/<str:birthday>', views.detail_handler, name='detail'),
网站中访问的URL:http://127.0.0.1:8000/user/detail/Mike/a2/2000
那么返回的网站渲染为: 你的数据在天上漫步呢!