django学习

说到web后端框架,其主要是用于提供curd和restapi.有Java的Spring系列,还有现在比较火的Go,js也有一些用于web的库.而python有flask,django和fastapi(重点是提供api).

一点历史

官网

Django 最初被设计用于具有快速开发需求的新闻类站点,目的是要实现简单快捷的网站开发

以下是安装 Django 的推荐方式。

  1. 安装 pip。最简单的方式是使用 独立 pip 安装器。若你的系统早已安装 pip,你可能需要更新它,因为它可能过期了。如果它过期了,你会知道的,因为过期的用不了。
  2. 看一下 venv。这个工具提供了隔离的Python环境,比在系统内安装包更实用。它还允许在没有管理员权限的情况下安装包。贡献指南 介绍了如何创建一个虚拟环境。
1
python -m pip install Django

当然还要安装数据库和python关于控制数据库的库.

1
2
3
django-admin startproject myProject
ll
tree myProject

项目结构

可以看到Django项目还是很简练的,我个人认为Python的很多东西设计都很不错,虽然我对这门语言有点偏见.

manage.py 项目的入口文件

myProject 主目录下的同名子目录,为项目的核心目录,它里面包含配置文件和管理应用的文件。

myProject/__init__.py 每个子目录都会包含这样一个 __init__.py 文件,它是一个空文件,在需要的时候会引入目录下的对象。

myProject/settings.py 配置文件,里面包含对数据库的设置项、CSRF Token 的设置项、模板的设置项等全部设置。

myProject/urls.py 路由控制文件,处理客户端请求,分发到对应的视图函数去处理

myProject/wsgi.py 处理请求和响应.

开始

接下来直接开始

1
2
cd myProject
python3 manage.py startapp myApp

创建一个名为 myApp 的应用,注意实验环境里不可以创建名为 test 的应用,某些情况下它与 Python 模块冲突

在项目的主目录下出现了名为 myApp 的目录,这就是应用目录。

  • myApp/admin.py 用于控制后台管理的文件。
  • myApp/apps.py 用于管理应用本身的文件,包括应用的名字如何命名,默认就是 myApp 。
  • myApp/__init__.py 空文件。
  • myApp/migrations 这是用于记录数据库变更信息的目录,Django 中自带的数据库版本控制功能就体现在这个目录,在学习数据存储时会详细介绍。
  • myApp/models.py 创建映射类的文件。
  • myApp/tests.py 编写测试代码的文件。
  • myApp/views.py 创建视图函数的文件,视图函数用于处理客户端发来的请求。

配置应用

在项目的setting.py下增加myApp

1
2
3
4
5
6
7
8
9
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
"myApp"
]
1
python3 manage.py runserver

开启服务.默认8000端口 更改端口后面直接加端口号.

视图

1
2
3
4
5
6
# myApp/views.py
from django.shortcuts import render
from django.http import HttpResponse

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

映射到url

Examples:
Function views

  1. Add an import: from my_app import views

  2. Add a URL to urlpatterns: path(‘’, views.home, name=’home’)

    Class-based views

    1.Add an import: from other_app.views import Home

    2.Add a URL to urlpatterns: path(‘’, Home.as_view(), name=’home’)
    Including another URLconf

    1.Import the include() function: from django.urls import include, path

    2.Add a URL to urlpatterns: path(‘blog/‘, include(‘blog.urls’))

path函数

参数意义是否必须
routeroute 是一个匹配 URL 的准则(类似正则表达式)。当 Django 响应一个请求时,它会从 urlpatterns 的第一项开始,按顺序依次匹配列表中的项,直到找到匹配的项。必须
view当 Django 找到了一个匹配的准则,就会调用这个特定的视图函数,并传入一个 HttpRequest 对象作为第一个参数,被“捕获”的参数以关键字参数的形式传入。必须
kwargs任意个关键字参数可以作为一个字典传递给目标视图函数。可选
name为你的 URL 取名能使你在 Django 的任意地方唯一地引用它,尤其是在模板中。这个有用的特性允许你只改一个文件就能全局地修改某个 URL 模式。可选

模型

在创建的应用程序中有model

1
2
3
4
5
6
7
8
# myApp/models.py
from django.db import models

class Book(models.Model):
name = models.CharField(max_length=200)
author = models.CharField(max_length=100)
pub_house = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')

我觉得这里跟Java Bean有点像.模型是 django.db.models.Model 类的子类。每个模型有一些类变量,它们都表示模型里的一个数据库字段。

每个字段都是 Field 类的实例。比如字符字段是 CharField,日期字段被表示为 DateTImeField。这将告诉 Django 每个字段要处理的数据类型。

定义某些 Field 类实例需要参数。如上面的 max_length=100 中的 max_length。这个参数的用处不止于用来定义数据结构,也用于验证数据。

在setting中修改

1
2
3
4
5
6
7
8
9
10
11
# myProject/settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# 'myApp', 这一注释掉,不注释掉会因重复而报错
'myApp.apps.MyappConfig',
]

然后进行迁移

1
python manage.py makemigrations myApp

这样就创建了模型

Book模型

产生的文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Migration(migrations.Migration):

initial = True

dependencies = [
]

operations = [
migrations.CreateModel(
name='Book',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=200)),
('author', models.CharField(max_length=100)),
('pub_house', models.CharField(max_length=200)),
('pub_date', models.DateTimeField(verbose_name='date published')),
],
),
]

通过运行 makemigrations 命令,Django 会检测你对模型文件的修改,并且把修改的部分储存为一次迁移.

通过命令查看创建数据库的命令

1
python3 manage.py sqlmigrate myApp 0001

模板

默认的设置文件设置了 DjangoTemplates 后端,并设置 APP_DIRS = True。这一选项将会让 DjangoTemplates 在每个 INSTALLED_APPS 文件夹中寻找 templates 子目录。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]

在views.py中添加视图

1
2
3
4
5
6
7
8
9
10
11
12
13
from django.shortcuts import render
from django.http import HttpResponse
from myApp.models import Book
# Create your views here.

def index(requst):
return HttpResponse("Hello World")

def detail(request):
book_list = Book.objects.order_by('pub_date')[:5]
context = {'book_list':book_list}
return render(request,"myApp/detail.html",context)

再进行视图绑定

使用MTV模式实现数据库增删改

首先设计界面.

myApp/templates/myApp/detail.html 里,添加一个表单。

1
2
3
4
5
6
7
<form action="" method="post" name="addBook">
{% csrf_token %}
<p><span>书名:</span><input type="text" name="name" /></p>
<p><span>作者:</span><input type="text" name="author" /></p>
<p><span>出版社:</span><input type="text" name="pub_house" /></p>
<input type="submit" value="添加" />
</form>
  • 上面的模板是输入相应的书名、作者和出版社后,点击添加,将数据存储到数据库并刷新页面显示出来。
  • 我们设置表单的 action="/addBook/",并设置 method="post"。使用 method="post"(与其相对的是 method="get")是非常重要的,因为这个提交表单的行为会改变服务器端的数据,无论何时,当你需要创建一个改变服务器端数据的表单时,请使用 method="post"。这不是 Django 的特定技巧,这是优秀的网站开发技巧。
  • 由于我们创建一个 POST 表单(它具有修改数据的作用),所以我们需要小心跨站点请求伪造。 但你不必太过担心,因为 Django 已经拥有一个用来防御它的非常容易使用的系统。 简而言之,所有针对内部 URL 的 POST 表单都应该使用 {% csrf_token %} 模板标签

在根 URLconf 中添加命名空间。在 myProject/urls.py 文件中稍作修改,加上 app_name 设置命名空间:

1
2
3
4
5
6
7
8
9
10
from django.contrib import admin
from django.urls import path
from myApp import views

app_name = 'myApp' # 添加这一行
urlpatterns = [
# path('admin/', admin.site.urls),
path('', views.detail, name='detail'),
path('addBook/', views.addBook, name='addBook'),
]

现在回到 myApp/templates/myApp/detail.html 更改 action

1
<form action="/addBook/" method="post" name="addBook"></form>

创建 addBook 函数来实现我们添加书籍的功能。

将下面的代码添加到 myApp/views.py:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# myApp/views.py
from django.http import HttpResponseRedirect
from django.urls import reverse

def addBook(request):
if request.method == 'POST':
temp_name = request.POST['name']
temp_author = request.POST['author']
temp_pub_house = request.POST['pub_house']

from django.utils import timezone
temp_book = Book(name=temp_name, author=temp_author, pub_house=temp_pub_house, pub_date=timezone.now())
temp_book.save()

# 重定向
return HttpResponseRedirect(reverse('detail'))

在 myProject/urls.py 里添加 URL 地址映射:

1
2
# myProject/urls.py
path('addBook/', views.addBook, name='addBook'),

简单说明:

  • request.POST 是一个类字典对象,可以通过关键字的名字获取提交的数据。 这个例子中,request.POST['name'] 以字符串形式返回name的值。request.POST 的值永远是字符串。
  • 在添加书籍之后,代码返回一个 HttpResponseRedirect 而不是常用的 HttpResponseHttpResponseRedirect 只接收一个参数:用户将要被重定向的 URL。
  • 你应该在每次处理 POST 数据时,都返回HttpResponseRedirect。这也不是 Django 的特定技巧,这是优秀的网站开发的实践。
  • 在这个例子中,我们在 HttpResponseRedirect 的构造函数中使用 reverse() 函数。这个函数避免了我们在视图函数中硬编码 URL。它需要我们给出想要跳转的视图的名字和该视图所对应的 URL 模式中需要给该视图提供的参数。reverse() 调用后将返回这样一个字符串:/detail/

删除书籍功能实现起来也很简单。

首先,在 myApp/detail.html 中设计我们的模板。

1
2
3
4
5
6
7
8
9
10
{% for book in book_list.all %}
<tr>
<td>{{ book.name }}</td>
<td>{{ book.author }}</td>
<td>{{ book.pub_house }}</td>
<td>{{ book.pub_date }}</td>
<td><a href="{% url 'delBook' book.id %}">删除</a></td><!--只添加这一行-->
</tr>
{% endfor %}
</table>

可以看出,只需要在每个书籍后面添加一个删除的按钮。删除时也传递了需要删除的图书的 id

接着,配置 url,只需在 myProject/urls.py 中添加这一行:

1
2
# myProject/urls.py
path('delBook/<int:book_id>', views.deleteBook, name='delBook'),

这里 <int:book_id> 是接收传递的参数 book_id

最后设计视图函数:

1
2
3
4
5
6
7
# myApp/views.py
def deleteBook(request, book_id):
bookID = book_id
Book.objects.filter(id=bookID).delete()

# 重定向
return HttpResponseRedirect(reverse('detail'))

这个视图中,获取到 book 的 id,根据 id 来删除指定书籍。最后跟上面的添加书籍函数相同,使用重定位刷新页面。

参考资料

官网这个是中文版的,很详细.

蓝桥云在线平台.

-------------本文结束感谢您的阅读-------------
感谢阅读.

欢迎关注我的其它发布渠道