注:我上次的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

django网站python django网站开发教程_django


自定义中间件可以为我们省去很多流程。比如,要判断一个用户是否已登录,按照老办法,每个视图函数都需要判断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',
]

中间件的执行流程

  1. 中间件中,请求传入时,先按照Website\settings.py内MIDDLEWARE列表的顺序,从上往下依次执行中间件的process_request方法,如果都没有返回值,执行第2个步骤;如果有返回值,当遭遇第一个返回值时,将此返回值作为响应,从当前中间件开始,由下往上依次执行响应有关的中间件方法。
  2. 当第1步骤都没有返回值时,执行此步骤。从上往下执行中间件的process_view方法,当都没有返回值时,执行视图函数;当遭遇第一个返回值时,将此返回值作为响应,从当前中间件开始,从下往上依次执行响应有关的中间件方法。
  3. 当视图函数返回了render渲染时,从下往上依次执行中间件的process_template_view方法。
  4. 当视图函数执行结束时,从下往上依次执行中间件的process_response方法。对于其中任意一个中间件的该方法,它接受参数response(响应),而这个响应来自上一个执行的process_response方法的返回值(如果是第一个执行,则来自视图函数的返回值)。如果该没有返回值,则默认返回收到的参数response,即上一级传来的响应;如果有返回值,则把返回值作为响应传给下一级中间件,直至传到客户端。

另外,如果视图函数抛出异常,则从下往上依次执行中间件的process_exception方法。

网站上线

两步搞定:

  1. 查看本机IP地址,CMD命令:ipconfig
  2. CMD命令:python manage.py runserver HOST:POST,其中HOST是本机IPv4地址,POST是想使用的端口号,默认8000,一般大于1024

就这么简单。

编者技术有限,如有不足敬请指教!

The End of Compotision.


  1. 你也可以使用-i参数临时指定镜像源。 ↩︎
  2. Website是与项目名同名的目录,如果你的项目命名时命名不是Website(如python),那么此文件夹就命名为python。 ↩︎
  3. 如果保错,执行cmd命令:python manage.py migrate. ↩︎
  4. 输入密码时,不会显示出来,但是正常输入了的。 ↩︎