众所周知 Django 是一个 Web 全栈框架,那 Django 是一个 Web 全栈框架是怎么一回事呢 请随着小编来看看吧
注意:
此教程主要受众是对 Python 有一定了解的开发者
如果你对 Python 开发没有经验请看这里
准备工作
- 你需要安装好 Django 框架,直接使用pip就能够安装:
pip install -i https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple django
当你看到
Successfully installed ...
就已经安装成功了
- 创建一个新的 Django 项目
django-admin startproject myproject
这会创建一个名为 myproject 的项目
创建成功后没有提示 但是会出现一个新的文件夹
此时的目录结构:
myproject/
├── __myproject/
│ ├── __init__.py
│ ├── asgi.py # 存放ASGI配置
│ ├── settings.py # 存放项目全局配置
│ ├── urls.py # 存放全局URL配置
│ └── wsgi.py # 存放WSGI配置
├── manage.py # 用于管理整个项目
└── db.sqlite3 # 存储数据
- 修改设置
Django 的默认设置存在一些问题 需要手动进行修改
进入刚刚创建的文件夹
打开 myproject/settings.py
文件
往下找到 LANGUAGE_CODE 这个常量
其默认内容为 "en-us"
将其修改为 "zh-hans"
然后是 TIME_ZONE 这个常量
其默认内容为 "UTC"
将其修改为 "Asia/Shanghai"
至此你已经成功创建了一个新项目
开始开发
- 创建一个新的应用程序
进入你的项目根目录 你应该可以看到一个 manage.py
它是整个项目的管理工具 Django 开发过程中离不开它
执行指令
python manage.py startapp myapp1
这会创建一个名为 myapp1 的项目
此时 你应该可以看到项目根目录下有一个 myapp1 的文件夹这里面就是你的应用程序文件.
此时的目录结构:
myproject/
├── myproject/
│ ├── __init__.py
│ ├── asgi.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
│
├── myapp1/
│ ├── migrations/ # 存放数据库迁移文件
│ │ └── __init__.py
│ ├── __init__.py
│ ├── admin.py # 存放后台管理页面配置
│ ├── apps.py # 存放应用程序类
│ ├── models.py # 用于定义数据模型
│ ├── tests.py # 用于自动化测试
│ └── views.py # 编写视图
│
├── manage.py # 项目管理脚本
└── db.sqlite3 # SQLite数据库文件
- 安装应用程序
虽然你创建了应用程序 但是 Django 并不知道你创建了它 所以你需要对其进行安装
在项目根目录下打开 myproject/settings.py
修改 INSTALLED_APPS
它默认是一个列表 类似这样:
INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
]
在后方追加刚刚创建的应用程序
"myapp1.apps.Myapp1Config",
myapp1 就是你刚才创建的应用程序名
apps就是应用程序文件夹下的apps.py文件
Myapp1Config就是这个应用程序的类
追加后是这样的:
INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
"myapp1.apps.Myapp1Config",
]
此时 你已经成功安装了此应用程序
- 配置 url
你需要为应用程序配置 Django才能知道 url 对应的服务
打开 myproject/urls.py
里面有一个导入语句是这样的:
from django.urls import path
再增加一个函数导入 include()
修改后是这样
from django.urls import path, include
然后注册 url
在 urlpatterns 列表中追加
path("", include("myapp1.urls")),
原来是:
urlpatterns = [
path("admin/", admin.site.urls),
]
修改后是:
urlpatterns = [
path("admin/", admin.site.urls),
path("", include("myapp1.urls")),
]
这意思是把 myapp1 文件夹下的 urls.py 文件挂载到网站根目录下
- 编写视图
终于来到最重要的部分力(喜)
打开 myapp1 文件夹 你可以看到一个名为 views.py 的文件
编辑此文件 导入 django.http.HttpResponse
也就是加上一行导入语句:
from django.http import HttpResponse
导入完成后编写视图代码以处理请求
def index(request):
return HttpResponse("Hello, world!")
此函数中 request 这个参数是必须的
- 配置 url
对 还要配置一次 因为之前配置的是整个项目的 url 现在这个是此应用程序的 url
在应用程序文件夹下创建一个文件 urls.py
并在里面写入:
from django.urls import path
from . import views
urlpatterns = [
path("", views.index, name="index"),
]
你已经成功配置好了 url
- 启动你的网站
你可以通过运行 python manage.py runserver 14590
来运行一个开发环境服务器
它将开始监听14590端口
注意:
在生产环境中请勿这样操作 因为内置的开发环境服务器在面对同时大量的请求时会出现问题
生产环境中请使用 uwsgi 作为服务器
运行后在浏览器打开 http://localhost:14590
如果你可以看到 Hello,world! 那么你就成功了!
数据模型
介绍:
数据模型提供了一种简单的方法访问 SQL 数据库,你不需要写一行 SQL 语句就可以轻松操作数据库
迁移默认数据模型:
Django 中默认内置了一个数据模型,你需要先将其迁移之后才能开始写你自己的数据模型
使用 python manager.py migrate
迁移数据模型
当你看到显示一列 OK 的时候就迁移完成了
编写你自己的数据模型
- 创建一个新的应用程序
这里创建新应用程序来演示,当然你也可以在上文中创建的那个应用程序继续编写
创建应用程序过程不再赘述 不会的看上文
此时的目录结构:
myproject/
├── myproject/
│ ├── __init__.py
│ ├── asgi.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
│
├── myapp1/
│ ├── migrations/
│ │ └── __init__.py
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── models.py
│ ├── tests.py
│ └── views.py
│
├── myapp2/
│ ├── migrations/
│ │ └── __init__.py
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── models.py
│ ├── tests.py
│ └── views.py
│
├── manage.py
└── db.sqlite3
刚才创建的应用程序名为 myapp2 挂载在 mdm/ 目录下
全局urlpatterns 中是这样写的
urlpatterns = [
path("admin/", admin.site.urls),
path("", include("myapp1.urls")),
path("dmd/", include("myapp2.urls")),
]
- 编写数据模型
打开 myapp2/models.py 文件
创建一个名为 Person 的数据模型:
class Person(models.Model):
name = models.CharField(max_length=20, unique=True) # 名字 unique 代表 name 是唯一的,此表中不允许有两个相同的名字
identify = models.CharField(max_length=100, unique=True) # id
# 其他字段...
def __str__(self): # 建议写一个__str__方法,方便在admin中显示
return self.name
- 迁移数据模型
执行 python manage.py makemigrations
执行完成后执行 python manage.py migrate
迁移完成
- 编写视图
在 views.py 中写入以下代码
from django.http import HttpResponse, Http404
from .models import Person # 导入模型
def query(request): # 这个视图接收 name 参数,返回对应的 id
try:
content = Person.objects.get(name=request.GET.get('name'))
return HttpResponse(content.identify) # 返回 id
except Person.DoesNotExist: # 如果查询不到
raise Http404("Person does not exist")
def register(request): # 将名字录入数据库
if Person.objects.filter(name=request.GET.get('name')).exists(): # 如果名字已存在
return HttpResponse("Name already exists")
else:
person = Person(name=request.GET.get('name'), identify=request.GET.get('identify')) # 创建一个 Person 对象
person.save() # 保存到数据库
return HttpResponse("Register successfully")
def delete(request): # 删除名字
try:
person = Person.objects.get(name=request.GET.get('name'))
person.delete() # 删除对象
return HttpResponse("Delete successfully")
except Person.DoesNotExist: # 如果查询不到
raise Http404("Person does not exist")
配置 urls
这里不再赘述 直接放出修改的内容
from django.urls import path
from . import views
urlpatterns = [
path('query/', views.query, name='query'), # 查询视图
path('register/', views.register, name='register'), # 注册视图
path('delete/', views.delete, name='delete'), # 删除视图
]
测试
启动服务器
写入数据库:
访问 <地址>:<端口>/dmd/register/?name=xiaoming&identify=awa
当显示Register successfully的时候 就已经在数据库中添加了一个新条目 名字叫做"xiaoming" 他的id是"awa"
再次访问 <地址>:<端口>/dmd/register/?name=xiaoming&identify=qwq
观察到显示Name already exists 表示数据库已经存在相同名称的条目 写入失败
查询数据库:
访问 <地址>:<端口>/dmd/query/?name=xiaoming
观察到显示内容为之前注册的时候写的用户id
例如我在写入数据库的时候为xiaoming分配的id是awa 则查询时也会查到xiaoming的id是awa
访问 <地址>:<端口>/dmd/query/?name=xiaohong
观察到显示404错误页面 表示没有查询到对应条目
删除数据条目:
访问 <地址>:<端口>/dmd/delete/?name=xiaoming
观察到显示Delete successfully表示删除成功 数据库中对应条目已删除
再次访问 <地址>:<端口>/dmd/delete/?name=xiaoming
观察到到显示404错误页面 表示没有对应条目
再次访问 <地址>:<端口>/dmd/register/?name=xiaoming&identify=qwq
观察到返回Register successfully 表示注册成功
- 在管理页面中管理
Django 中内置了一个管理页面
默认在 <地址>:<端口>/admin
下
但是你还不能登录 因为你并没有账号
执行 python manage.py createsuperuser
来创建一个超级用户
创建后你就可以登录了
但在那之前 请先在管理面板中注册你在第4步时编写的数据模型
打开 myapp2/admin.py
写入
from django.contrib import admin
from .models import Person # 导入模型
admin.site.register(Person) # 注册模型到 admin 界面
此时你再启动服务器 打开管理页面 登录之后就可以在上面对数据进行修改了
前端
配置命名空间
打开 urls.py
定义一个 app_name 变量
其内容为 'myapp2'
建立模板
在myapp2文件夹下建立一个 templates文件夹 里面再套一个myapp2文件夹
在里面再新建一个index.html、results.html
这是用于存放模板文件(就是html!)
在myapp2文件夹下建立一个static文件夹 里面再套一个myapp2文件夹
用于存放静态文件 例如:css js 图片...
在下面新建一个 styles.css 文件用于存放你的层叠样式表
myapp2/
├── migrations/
│ └── __init__.py
├── templates/
│ └── myapp2/
│ └── index.html
│ └── result.html
├── static/
│ └── myapp2/
├── __init__.py
├── admin.py
├── apps.py
├── models.py
├── tests.py
└── views.py
打开刚才新建的 index.html 文件
写入:
{% load static %} <!-- 告诉 Django 在此页面中加载静态文件 -->
<!DOCTYPE html>
<html lang="hans">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Query ID</title>
<link rel="stylesheet" href="{% static 'myapp2/css/styles.css' %}"> <!-- static/css/styles.css -->
</head>
<body>
<form action="{% url 'myapp2:query' %}", method="get"> <!-- 提交表单到查询视图 -->
{{ form }}
<input type="submit">
</form>
</body>
</html>
打开刚才新建的 result.html 文件
写入
{% load static %}
<!DOCTYPE html>
<html lang="hans">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Query result</title>
<link rel="stylesheet" href="{% static 'myapp2/css/styles.css' %}"> <!-- static/css/styles.css -->
</head>
<body>
{% if success %}
<p>你查询的ID是: {{ identify }}</p> <!-- 显示查询的 ID -->
{% else %}
<p>没有找到你查询的ID: {{ name }}</p> <!-- 显示查询的 ID -->
{% endif %}
</body>
</html>
这里有些小伙伴就要问了:
如果我的 id 是 </p><script>hacker();</script><p>
那不就是代码注入了吗?
其实你完全不必担心
作为一个高级框架 Django 已经为你考虑好了各种各样的情况(比如代码注入)
如果你确实需要进行代码注入 可以变量后方加上safe过滤器
像这样
{{ identify | safe }}
将此字符串标记为安全的 这将允许代码注入 注意这可能导致跨站脚本攻击等问题 所以非必要请勿使用!
那么前端写好了 怎么渲染到用户浏览器上呢?
这里又要用到一个新的函数 render()
打开你的 views.py 文件 你可以发现 Django 已经帮你写好了导入语句 from django.shortcuts import render
当然 你还要对视图进行一些修改,我直接放出修改后的
from django.shortcuts import render
from django.http import HttpResponse, Http404
from django import forms
from .models import Person # 导入模型
class PersonQueryForm(forms.Form): # 创建一个表单类
name = forms.CharField(label='名称') # 定义一个字符字段,最大长度为20
def index(request): # 主页视图
return render(request, 'myapp2/index.html', {'form': PersonQueryForm}) # 渲染模板,传入表单实例
def query(request): # 这个视图接收 name 参数,返回对应的 id
try:
content = Person.objects.get(name=request.GET.get('name'))
return render(request, 'myapp2/result.html', {'success': True, 'name': content.name, 'identify': content.identify}) # 渲染模板,传入查询结果
except Person.DoesNotExist: # 如果查询不到
render(request, 'myapp2/result.html', {'success': False, 'name': request.GET.get('name')})
def register(request): # 将名字录入数据库
if Person.objects.filter(name=request.GET.get('name')).exists(): # 如果名字已存在
return HttpResponse("Name already exists")
else:
person = Person(name=request.GET.get('name'), identify=request.GET.get('identify')) # 创建一个 Person 对象
person.save() # 保存到数据库
return HttpResponse("Register successfully")
def delete(request): # 删除名字
try:
person = Person.objects.get(name=request.GET.get('name'))
person.delete() # 删除对象
return HttpResponse("Delete successfully")
except Person.DoesNotExist: # 如果查询不到
raise Http404("Person does not exist")
注意在 urls.py 中配置路径指向主页视图!
启动服务器 进行测试 观察到已经可以渲染页面
请试着自己写出注册页面和删除页面吧!
Cookie and session
很多时候 我们需要储存一些信息在用户的浏览器上 通常我们会使用 Cookie 或者 Session 来达成此目的
那么它们的区别是什么的?
Session 是较为安全的储存方式 其依赖于 Cookie
Session 的内容储存在服务端,而客户端只储存 sessionid 这样可以有效防止客户端通过 Cookie Editor 这样的插件来篡改储存的内容
Cookie...... 这还用我解释?
Session
在 Django 中,你可以很轻松的编辑 Session 中存储的内容 修改它就像修改一个字典一样!
还记得吗? 每个视图函数的第一个参数都是 request 而且必须有
这是一个神奇的东西 你可以在里面获取到关于请求的大部分内容 包括请求参数、Cookie... 当然也包括 Session
def index(request):
request.session["awa"] = "qwq" # 把名为 awa 的键的值设为 "qwq"
request.session.get("awa") # 获取 awa 键的值 如果没有返回 None
request.session["awa"] # 获取 awa 键的值 如果没有则抛出 KeyError
return Http404("砰!")
Cookie
Cookie 的配置比 Session 稍微麻烦点
你需要在回复中使用set_cookie方法才能写入cookie
def index(request):
response = HttpResponse("200 Success")
response.set_cookie('key', 'value', max_age=1000) # 设置一个 Cookie 它的键名为 'key' 它的值为 'value' 它的最大存活时间为1000秒
return response
def read_cookie(request):
request.COOKIES['key'] # 读取 key 这个键的值
request.COOKIES['key'] = 'value1' # 无法写入,cookie 只能用过 set_cookie 方法写入