注:我上次的django开发教程:点击这里
Python学习笔记 - 使用django模块开发网站(较详细)
下载 & 安装django
django是Python的第三方模块,需要下载安装。使用pip安装django非常简易1。
pip install django
新建项目
cmd窗口输入命令:
django-admin startproject Website
其中,Website
是django项目(project)的名字,可自行命名。
此时,Website文件夹中有以下文件/目录:
init.py 初始化文件,使得此目录可作为包使用
manage.py 管理django项目,接受命令行参数
Website2
管理项目配置
本部分除特别说明外,代码修改均在Website\settings.py内。
导入os模块
import os
将语言和时区调整为中国。
LANGUAGE_CODE = 'zh-Hans'
TIME_ZONE = 'Asia/Shanghai'
配置模板(即html文件,后面会讲到)和静态资源(后面会讲到)的路径.
TEMPLATES = {
# 前面默认配置略... ,
'DIRS': [
os.path.join(BASE_DIR, 'templates'),
],
# 后面的默认配置略... ,
}
# ......
STATIC_URL = '/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static')
]
其中,后一个static是静态资源文件路径,约定为static
允许访问
ALLOWED_HOSTS = ['*']
# 列表内存放允许访问的IPv4地址列表,'*'表示所有IP.
项目根目录输入cmd命令:python manage.py runserver
,浏览器访问http://127.0.0.1:8000/
,可看到django默认首页。
admin后台管理系统
不得不说,admin后台系统是django的一大特色。
Website\settings.py里面有一个列表
INSTALLED_APPS = [
'django.contrib.admin',
]
这是django项目应用程序(apps)的安装列表,django.contrib.auth
是django内置的admin后台管理系统。
浏览器访问http://127.0.0.1:8000/admin/
,3可看到admin登录界面。
使用如下命令创建一个超级用户:
python manage.py createsuperuser
提示输入即可4。
浏览器输入用户名 & 密码,即可看到主界面。
应用程序
使用cmd命令创建应用程序(app):
python manage.py startapp Application
其中,Application是应用程序名称,可自行命名。
Application\models.py中定义模型(model):
from django.db import models
class Info(models.Model):
"""创建一个Info模型类,继承自django.db.models.Model,用于管理信息。
django.db是django的数据库管理模块
field是字段的意思,一般地,字段拥有如下属性:
max_length 最大输入字符数 int
help_text 下方灰色提示文本 str
对于Charfield, max_length为必须参数,其它字段不然。
对于关于时间/日期的字段,有如下属性:
auto_time 自动写入修改时间 bool
auto_time_add 自动写入创建时间 bool"""
title = models.Charfield('标题', max_length=150)
body = models.Textfield('信息内容')
date = models.Datefield('发布日期', auto_time=True)
. class Meta:
"""必须命名为Meta.
这个子类用于命名,如果没有,则名字为父类名(即Info,
而且会出现特别"丢份儿"的Infos这种英语错误"""
# 单数名字
verbose_name = "网站信息"
# 复数名字
verbose_name_plural = "网站信息"
在写字段的时候,关于字段标题,我个人为了偷懒,常常不写第一个str参数,直接用参数名代替标题。比如标题 = models.Charfield(max_length=150)
, 信息内容 = models.Textfield()
如果要在admin后台管理它,还需要在Application\admin.py中添加这样的代码:
from . import models
# 注册模型类
admin.site.register(models.Info)
但是admin后台,比如你创建一个Info,就会有个啥"Info object (1)"之内的,很不美观。自定义admin界面:
from . import models
class InfoAdmin(admin.ModelAdmin):
# 显示的字段
list_display = ('title', 'body', 'date')
# 搜索器(过滤器)搜索的字段
search_fields = ('title', )
admin.site.register(models.Info, InfoAdmin)
当然,也可使用装饰器:
from . import models
@admin.site.register(models.Info)
class InfoAdmin(admin.ModelAdmin):
# 显示的字段
list_display = ('title', 'body', 'date')
# 搜索器(过滤器)搜索的字段
search_fields = ('title', )
可以修改网站名称
# 网站名称
admin.site.title_header = 'Django Website'
# admin首页标题
admin.site.index_title = 'Administration Center'
页面设计
django显示页面有如下步骤
页面访问请求
在urls.py中查找页面
查找到URL
执行对应的视图函数
未查找到URL
返回HTTP状态码404
这里我们以一个URL为/page/的页面为例。首先,在Website\urls.py中使用url函数注册:
from djamgo.core.urls import url
from . import views
urlpatterns = [
# 前面默认配置略... ,
url(r'page/', views.func)
]
这里的views.func就是视图函数。视图函数用于处理django的视图,在Website\views.py(须自行创建)中键入代码:
from django.shortcut import render
def func(request):
"""request有如下常用属性:
request.method str 访问方式,GET或POST
request.user django.contrib.auth.models.User 访问的用户
request.POST dict 所有POST参数
request.GET type 一个带有@property装饰器的方法,返回值是所有GET参数的字典
视图函数必须有返回值,且返回值必须为django的HttpResponse对象。常见的返回值类型有:
1. django.http模块内的HTTP对象
2. render渲染(其实就是使用)HTML页面
3. django重定向URL
render函数接受如下参数:
1. request访问,这是必须参数,只需要把函数形参request传入即可
2. html页面(模板),这是必须参数,str类型,HTML的文件名
3. 传入html的渲染参数,这是可选参数,后面将会讲到"""
return render(request, 'show.html')
然后我们看到,views.func
引用了show.html。创建templates\show.html,输入你想用的HTML界面。这里我就简单写一下,可能不太美观,请见谅。
<!DOCTYPE HTML>
<html>
<head>
<!--编码格式-->
<meta charset="UTF-8">
<!--网页标题-->
<title>Django | Page</title>
</head>
<body>
<!--1级标题-->
<h1>Django - Page页面</h1>
<!--普通段落-->
<p>
Welcome to Django website!
</p>
<p>
<!--超链接-->
I am <a href="/admin/">administrator</a>
</p>
</body>
</html>
登录界面
登录界面刚刚好就把登录和POST表单都讲了,正好偷懒。
使用login
函数登录,它需要一个User
模型,可以由authenticate
函数返回值得到。
使用authenticate
函数验证用户名和密码是否正确,参数为用户名和密码(均为str类型),如果密码正确,返回用户对应的User
模型,否则返回None
。
使用logout
函数退出登录。
对于一个模型(例如Model),先导入模块,使用Model.objects.all()
获取所有模型信息,Model.objects.filter()
使用过滤器,使用Model.objects.get()
获取指定条件的信息。
URL配置,Website\urls.py:
urlpatterns = [
# ... ,
url(r'login/', views.log_in)
]
视图函数,Website\views.py:
from django.contrib.auth import login, logout, authenticate
def log_in(request):
if request.method == 'GET':
# 访问页面时,GET请求。
return render(request, 'login.html')
else:
# HTML传回的POST表单。
user = request.POST.get('user', False)
pwd = request.POST.get('password', False)
if not user or not pwd:
# 如果未输入用户名或密码
return render(request, 'login.html')
# 返回重新输入
u = authenticate(username=user, password=pwd)
if u is None:
from django.http import HttpResponse as res
return res(request, '用户名或密码错误')
# 登录
login(u)
# 导入信息数据库
from Application.models import Info
# 重定向到首页,并传入请求信息
return render(request, 'homepage.html', {'req': request, 'data': Info.objects.all()})
# 关于Info.objects.all(),如果忘了,前面讲过的,请看前文
然后编写登录的HTML界面,templates\login.html
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<title>Django Web | Login</title>
</head>
<body>
<h1>Django Website - Login</h1>
<p>Please enter your personal information below</p>
<!--建立框形显示区域-->
<fieldset>
<!--框标题-->
<legend>Password Check</legend>
<!--form表单-->
<form action="" method="POST">
<!--django默认有CSRF跨站请求防护机制
因此需要CSRF令牌以通过CSRF防护
下面的这行语句,django将会自动处理并替换为CSRF令牌-->
{% csrf_token %}
用户名:<input type="text" name="user">
密码:<input type="password" name="password">
<!--按钮-->
<input type="submit" value="登录">
</form>
</fieldset>
</body>
</html>
然后还有前面视图函数里面的首页,templates\homepage.html
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<title>Django Web | Homepage</title>
</head>
<body>
<h1>Django Web - Homepage</h1>
<!--使用两对英文大括号以使用render传入的字典参数
django会自动渲染,即替换为相关实参-->
<p>Welcome, {{ req.user.username }}</p>
<!--也支持for循环,但变量不能以下划线开头-->
{% for obj in data %}
<fieldset>
<!--同样使用两对大括号引用参数-->
<legend>{{ obj.title }}</legend>
<!--使用if语句判断-->
{% if obj.body == "" %}
<textarea row=60 column=30 readonly>{{ obj.body }}</textarea>
<!--也可使用else-->
{% else %}
<textarea row=10 column=30 readonly>无内容</textarea>
{% endif %}
<!--一定注意这里有一个endif. 事实上,django模板中所有的{% xxx %}最后都有一个{% endxxx %},否则会报错-->
<!--也支持and, or, not关键字,以及嵌套, elif等-->
</fieldset>
{% empty %}
<!--当循环序列为空时执行的逻辑,可以有也可以没有-->
<p color="red">无数据</p>
{% endfor %}
<!--刚刚上面if才说的,必须有end-->
</body>
</html>
中间件
Website\settings.py内有一个列表MIDDLEWARE
,这就是中间件。
当用户访问一个页面或提交一个表单(form)时,会向服务器发送一个请求(request),请求先经过中间件的处理,再传给视图函数;视图函数处理后,先经过中间件的处理,再返还给客户端。如下图所示5。
自定义中间件可以为我们省去很多流程。比如,要判断一个用户是否已登录,按照老办法,每个视图函数都需要判断login_registed
,而如果自定义中间件,就可以大大简化代码。
中间件的本质是类。中间件可以有以下5个方法:
process_request
,当请求传入时触发。有1个参数,即request。此方法可以返回值,也可以不返回值。当此方法返回值时,就不再执行视图函数,而是将返回的HttpResponse对象传回客户端。
process_response
,当响应传回客户端时触发。有2个参数,request和response。此方法必须返回HttpResponse对象。如果函数内没有return,那么默认返回形参response;如果返回其它,则把返回值交给下一个执行的中间件,直至中间件全部执行完,传回客户端。
process_view
,当URL匹配成功,将执行视图函数之前时触发。有4个参数,request,view_func,view_args,views_kwargs。其中,request是请求信息,view_func是将要执行的视图函数,view_args,view_kwargs是传给视图函数的参数,view_args是tuple,view_kwargs是dict。该方法的返回值可有可无,如果没有返回值,则执行视图函数;如果有返回值,则跳过视图函数,将返回值作为响应(HttpResponse对象),传回客户端(相当于用process_view方法替代了视图函数)。
process_template_view
,当视图函数(或process_view方法)返回了render时触发。
process_exception
,当视图函数抛出异常时触发,如果有返回值,将返回值作为响应信息。
接下来,我们新建Application\middleware.py,编写验证登录的自定义中间件。
# 从设置中导入不需要登录验证的URL列表
from website.settings import LOGIN_UNNECESSARY as LU
class LoginMiddleware:
def process_requrst(self, request):
if request.user == None and request.path not in LU:
return render(request, 'login.html')
else:
print("用户 ", request.user.username, " 发送请求至", request.path)
def process_response(self, request, response):
print("URL服务器发送响应至用户", request.user.uaername, ",URL地址为", request.path)
def process_exception(self, request, exception):
print("ERROR 500, URL为", request.path)
return HttpResponse(request, "500 服务器错误")
然后在Website\settings.py内添加不需要登录验证的URL列表
LOGIN_UNNECESSARY = [
'/login/',
'/logout/',
]
然后在此文件中,添加中间件至最下面
MIDDLEWARE = [
# 前面默认配置略... ,
'Application.middleware.LoginMiddleware',
]
中间件的执行流程
- 中间件中,请求传入时,先按照Website\settings.py内MIDDLEWARE列表的顺序,从上往下依次执行中间件的
process_request
方法,如果都没有返回值,执行第2个步骤;如果有返回值,当遭遇第一个返回值时,将此返回值作为响应,从当前中间件开始,由下往上依次执行响应有关的中间件方法。 - 当第1步骤都没有返回值时,执行此步骤。从上往下执行中间件的
process_view
方法,当都没有返回值时,执行视图函数;当遭遇第一个返回值时,将此返回值作为响应,从当前中间件开始,从下往上依次执行响应有关的中间件方法。 - 当视图函数返回了render渲染时,从下往上依次执行中间件的
process_template_view
方法。 - 当视图函数执行结束时,从下往上依次执行中间件的
process_response
方法。对于其中任意一个中间件的该方法,它接受参数response(响应),而这个响应来自上一个执行的process_response方法的返回值(如果是第一个执行,则来自视图函数的返回值)。如果该没有返回值,则默认返回收到的参数response,即上一级传来的响应;如果有返回值,则把返回值作为响应传给下一级中间件,直至传到客户端。
另外,如果视图函数抛出异常,则从下往上依次执行中间件的process_exception
方法。
网站上线
两步搞定:
- 查看本机IP地址,CMD命令:
ipconfig
- CMD命令:
python manage.py runserver HOST:POST
,其中HOST是本机IPv4地址,POST是想使用的端口号,默认8000,一般大于1024
就这么简单。
编者技术有限,如有不足敬请指教!
The End of Compotision.
- 你也可以使用-i参数临时指定镜像源。 ↩︎
- Website是与项目名同名的目录,如果你的项目命名时命名不是Website(如python),那么此文件夹就命名为python。 ↩︎
- 如果保错,执行cmd命令:
python manage.py migrate
. ↩︎ - 输入密码时,不会显示出来,但是正常输入了的。 ↩︎