Django-后端-Python

本文最后更新于:2020年10月28日 晚上

信息

一个python web框架,相较于flask而言体量更大更重

文档/网站

官网:https://www.djangoproject.com/
文档:https://docs.djangoproject.com/zh-hans/3.1/intro/install/

使用

安装

使用pip进行安装即可

1
pip install Django

验证安装

对应环境启动后,输出django版本号以测试是否安装成功

1
2
>>> import django
>>> print(django.get_version())

快速入门

基本

创建项目

cmdcd到一个建立项目的位置
使用startproject命令创建项目

1
django-admin startproject 项目名

注意:不要使用python内部字段来命名项目,这会引起冲突

在运行startproject生成项目后,会生成以下这些文件

1
2
3
4
5
6
7
8
项目名/  # 项目根目录。名字可以随改
manage.py # Django项目的命令行工具
项目名/ # 项目所需python包
__init__.py # 包标识
settings.py # 项目的配置文件
urls.py # 项目的URL声明,就像你网站的“目录”
asgi.py # 项目的运行在ASGI兼容的Web服务器上的入口
wsgi.py # 项目的运行在 WSGI 兼容的Web服务器上的入口

更多细节 - 链接:

创建应用

Django中,每一个应用都是一个Python包,并且遵循着相同的约定
Django自带一个工具,可以帮你生成应用的基础目录结构

项目和应用有什么区别?
应用:一个专门做某件事的网络应用程序——比如博客系统,或者公共记录的数据库,或者小型的投票程序
项目:则是一个网站使用的配置和应用的集合
项目可以包含很多个应用。应用可以被很多个项目使用

你的应用可以存放在任何Python path中定义的路径
可以在manage.py同级目录下创建应用。这样它就可以作为顶级模块导入。也可以在mysite中创建,作为一个子模块

创建一个应用(注意路径问题)

1
python manage.py startapp 应用名

这样以后,会创建一个以应用名命名的文件夹

1
2
3
4
5
6
7
8
9
应用名/
__init__.py
admin.py
apps.py
migrations/
__init__.py
models.py
tests.py
views.py

这个目录包含了这个应用的全部内容

添加创建的应用到配置文件中

然后在项目名/项目名/settings.py中的INSTALLED_APPS中将自己创建的应用添加进去

1
2
3
4
INSTALLED_APPS = [
......
'应用名'
]

这样做能更好的利用Django自带的配置,比如说自动加载模板
不添加也不会出什么问题

编辑视图

打开polls/views.py,把下面这些Python代码写入:

1
2
3
4
5
from django.http import HttpResponse


def index(request):
return HttpResponse("Hello, world.")

编辑URL映射

编辑应用URL映射

将一个URL映射到视图上,才能显示一个视图
在 应用的目录(不是项目) 中创建一个urls.py文件,并写入以下代码:

1
2
3
4
5
6
from django.urls import path
from . import views

urlpatterns = [
path('', views.index, name='index'),
]

path函数具有四个参数,两个必传:routeview,两个可选参数:kwargsname

  • route
    route是一个匹配URL的准则(类似正则表达式)
    当 Django 响应一个请求时,它会从urlpatterns的第一项开始,按顺序依次匹配列表中的项,直到找到匹配的项。

    注意:这些准则不会匹配GETPOST参数或域名

  • view
    Django找到了一个匹配的准则,就会调用这个特定的视图函数,并传入一个 HttpRequest对象作为第一个参数,被“捕获”的参数以关键字参数的形式传入

  • kwargs
    任意个关键字参数可以作为一个字典传递给目标视图函数

  • name
    URL取名能使你在Django的任意地方唯一地引用它,尤其是在模板中
    这个有用的特性允许你只改一个文件就能全局地修改某个URL模式

编辑项目URL映射

应用是依托于项目运行的,应用的URL映射关系应与项目URL映射绑定

在根URLconf文件中指定我们创建的应用名.urls模块
mysite/urls.py文件的urlpatterns列表里插入一个 include(), 如下:

1
2
3
4
5
6
7
from django.contrib import admin
from django.urls import include, path

urlpatterns = [
path('应用名/', include('应用名.urls')),
path('admin/', admin.site.urls),
]

函数include()允许引用其它URLconfs
每当Django遇到include()时,它会截断与此项匹配的URL的部分,并将剩余的字符串发送到URLconf以供进一步处理

include()的理念是可以即插即用
因为应用有它自己的URLconf( polls/urls.py ),他们能够被放在 “/polls/“ , “/fun_polls/“ ,”/content/polls/“,或者其他任何路径下,这个应用都能够正常工作

用于开发的简易服务器

cmd中输入命令以使用开发服务器

1
>>>python manager.py runserver

启动后你会看到一些输出

1
2
3
4
5
6
7
8
9
10
11
Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).

You have 18 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.
October 26, 2020 - 16:25:10
Django version 3.1.2, using settings 'SXB_BaiduSEO_Web.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.

这个命令启动的是Django自带的用于开发的简易服务器,一个用纯Python写的轻量级的Web服务器
这个服务器内置在Django中是为了让你能快速的开发出想要的东西 (不需要进行配置生产级别的服务器(比如 Apache)方面的工作)

千万不要!!! 千万不要!!! 千万不要!!!将这个服务器用于和生产环境相关的任何地方

基础

更多视图

应用名/views.py 里添加更多视图

带参数视图

应用名/urls.py
1
2
3
4
5
6
7
8
9
from django.urls import path
from . import views

urlpatterns = [
......
# 新的url映射,映射到detail中
# url的一部分作为参数 _id 传入
path('<int:_id>/', views.detail, name='detail'),
]
应用名/views.py
1
2
3
def detail(request, _id):
# 获取url作为参数传入的_id
return HttpResponse("ID=" + _id)

HTML模板视图

  1. 首先,在应用目录中创建一个模板目录(文件夹)templates
    Django将会在这个目录里查找模板文件
  2. 在刚创建的templates目录里,再创建一个目录polls
  3. 然后在其中新建一个文件 index.html
    在完成上面的操作以后,你的模板文件的路径应该是 应用名/templates/应用名/index.html
  4. 写入index.html的模板代码
    应用名/templates/应用名/index.html
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <!DOCTYPE html>
    <html>
    <head><meta charset="utf-8"></head>
    <body>
    <ul>
    {% for question in questions %}
    <li>{{ question }}</li>
    {% endfor %}
    </ul>
    </body>
    </html>
  5. 视图引用HTML模板
    polls/views.py
    1
    2
    3
    4
    5
    6
    7
    8
    9
    from django.http import HttpResponse
    from django.template import loader


    def questions(request):
    questions = ['是什么','为什么', '怎么做']
    template = loader.get_template('BaiduSEO/index.html')
    context = {'questions': questions}
    return HttpResponse(template.render(context, request))
  6. 创建对应url映射
    应用名/urls.py
    1
    2
    3
    4
    urlpatterns = [
    ......
    path('questions/', views.questions, name='questions')
    ]
  7. 部署、访问、验证效果
为什么能够找到模板?

你项目的TEMPLATES 配置项描述了Django如何载入和渲染模板。
默认的设置文件设置了 DjangoTemplates 后端,并将 APP_DIRS 设置成了 True。这一选项将会让 DjangoTemplates 在每个 INSTALLED_APPS 文件夹中寻找 "templates" 子目录。这就是Django能正确找到应用模板位置的原因。

模板命名空间

虽然可以将模板文件直接放在应用名/templates文件夹中(而不是再建立一个应用名子文件夹),但是这样做不太好
Django会选择第一个匹配的模板文件,如果你有一个模板文件正好和另一个应用中的某个模板文件重名,Django没有办法区分它们
为了让Django选择正确的模板,最好的方法就是把他们放入各自的命名空间 中,也就是把这些模板放入一个和 自身 应用重名的子文件夹里

快捷函数render()

「载入模板,填充上下文,再返回由它生成的 HttpResponse 对象」是一个非常常用的操作流程
于是Django提供了一个快捷函数,来让代码变得更优美

应用名/views.py
1
2
3
4
5
6
7
from django.shortcuts import render


def index(request):
questions = ['是什么','为什么', '怎么做']
context = {'questions': questions}
return render(request, '应用名/index.html', context)

这样做就不再需要导入loaderHttpResponse

抛出404错误

写一个可能会报错的代码,在抓到异常后返回404

应用名/views.py
1
2
3
4
5
6
7
8
9
10
11
from django.http import Http404
from django.shortcuts import render


def detail(request, question_id):
try:
# 如果传入的数是0,那么会报错返回`404`
a = 10/question_id
except Exception:
raise Http404("Question does not exist")
return render(request, '应用名/id_zero.html', {'question': a})

配套的htmlurl映射写好了以后就能查看情况了

去除模板中的硬编码URL

应用名/template/应用名/free_url.html
1
<li><a href="/polls/{{ question.id }}/">点我</a></li>

硬编码和强耦合的链接,对于一个包含很多应用的项目来说,修改起来是十分困难的。
然而,因为你在polls.urlsurl()函数中通过name参数为URL定义了名字,你可以使用 {% url %} 标签代替它

应用名/template/应用名/free_url.html
1
<li><a href="{% url 'detail' question.id %}">{{ question.question_text }}</a></li>

这个标签的工作方式是在应用名/urls.pyURL定义中寻具有指定名字的条目

应用名/urls.py
1
path('<int:question_id>/', views.detail, name='detail')

这个name参数,就是{% url %}用来引用的key,最终得到的值是前面的路由信息

如果你想改变投票详情视图的URL,比如想改成应用名/specifics/12/,你不用在模板里修改任何东西(包括其它模板),只要在polls/urls.py里稍微修改一下就行

应用名/urls.py
1
2
# added the word 'specifics'
path('specifics/<int:question_id>/', views.detail, name='detail'),

URL命名空间

在一个真实的Django项目中,可能会有五个,十个,二十个,甚至更多应用
Django如何分辨重名的URL呢?
答案是:在根URLconf中添加命名空间。在 应用名/urls.py 文件中稍作修改,加上 app_name 设置命名空间

应用名/urls.py
1
2
3
4
5
6
7
8
from django.urls import path
from . import views


app_name = 'well' # 添加命名空间
urlpatterns = [
......
]

在模板需要使用{% url %}时,带上命名空间

应用名/template/应用名/free_url.html
1
<li><a href="{% url 'well:detail question.id'%}">{{ question }}</a></li>

表单处理

视图中的request参数(HttpRequest对象)可供使用的内容

属性 描述
path 请求页面的全路径,不包括域名
method 请求中使用的HTTP方法的字符串表示。全大写表示。
GET 包含所有HTTP GET参数的类字典对象
POST 包含所有HTTP POST参数的类字典对象
REQUEST 为了方便,该属性是POST和GET属性的集合体
有特殊性,先查找POST属性,然后再查找GET属性。
强烈建议使用GET and POST,因为这两个属性更加显式化,写出的代码也更易理解。
COOKIES 包含所有cookies的标准Python字典对象。Keys和values都是字符串。
FILES 包含所有上传文件的类字典对象。
FILES中的每个Key都是<input type="file" name="" />标签中name属性的值.
FILES中的每个value 同时也是一个标准Python字典对象,包含下面三个Keys:
    filename: 上传文件名,用Python字符串表示
    content-type: 上传文件的Content type
    content: 上传文件的原始内容
注意:只有在请求方法是POST,并且请求页面中<form>enctype="multipart/form-data"属性时FILES才拥有数据。否则,FILES 是一个空字典。
META 包含所有可用HTTP头部信息的字典
    CONTENT_LENGTH
    CONTENT_TYPE
    QUERY_STRING: 未解析的原始查询字符串
    REMOTE_ADDR: 客户端IP地址
    REMOTE_HOST: 客户端主机名
    SERVER_NAME: 服务器主机名
    SERVER_PORT: 服务器端口
META 中这些头加上前缀 HTTP_ 为 Key, 冒号(:)后面的为 Value, 例如:
    HTTP_ACCEPT_ENCODING
    HTTP_ACCEPT_LANGUAGE
    HTTP_HOST: 客户发送的HTTP主机头信息
    HTTP_REFERER: referring页
    HTTP_USER_AGENT: 客户端的user-agent字符串
    HTTP_X_BENDER: X-Bender头信息
session 唯一可读写的属性,代表当前会话的字典对象。只有激活Django中的session支持时该属性才可用。
raw_post_data 原始HTTP POST数据,未解析过。 高级处理时会有用处。
方法 描述
__getitem__(key) 返回GET/POST的键值,先取POST,后取GET。
如果键不存在抛出KeyError
这是我们可以使用字典语法访问HttpRequest对象。
例如:request["foo"]等同于先request.POST["foo"]然后 request.GET["foo"]的操作。
has_key() 检查request.GETrequest.POST中是否包含参数指定的Key。
get_full_path() 返回包含查询字符串的请求路径
is_secure() 如果请求是安全的,返回True,就是说,发出的是HTTPS请求。

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!