Django学习笔记(一)
序章
Django框架的模型结构:MVC结构,分别是模型(Models),视图(Views),控制器(Controller)
MVC 以一种插件式的、松耦合的方式连接在一起。
- 模型(M)- 编写程序应有的功能,负责业务对象与数据库的映射(ORM)。
- 视图(V)- 图形界面,负责与用户的交互(页面)。
- 控制器(C)- 负责转发请求,对请求进行处理。
在Django中,采用MVC的一种变体MTV,即模型(Models),模板(Templates),视图(Views)
- M 表示模型(Model):编写程序应有的功能,负责业务对象与数据库的映射(ORM)。
- T 表示模板 (Template):负责如何把页面(html)展示给用户。
- V 表示视图(View):负责业务逻辑,并在适当时候调用 Model和 Template。
除了以上三层之外,还需要一个 URL 分发器,它的作用是将一个个 URL 的页面请求分发给不同的 View 处理,View 再调用相应的 Model 和 Template
(以上部分参考自菜鸟教程:Django 简介 | 菜鸟教程 (runoob.com))
一、创建一个项目
在python中安装django库:
pip install django
默认安装的是最新的发行版,现已更新至4.0+,和网络中的2.0+相比,3.0时增添了asgi作为wsgi的异步处理版本,支持asyncio等异步的库
创建项目文件:在控制台中输入
django-admin startproject <项目名>
则创建对应项目,并且项目结构如下(假定项目名称为
mysite
):mysite: # 项目文件夹 - mysite: # 配置文件夹 - __init__.py # 初始化文件,告诉 Python 该目录是一个 Python 包 - asgi.py # 异步服务器网关接口 - sttings.py # 配置文件 - urls.py # 路由文件,一份由 Django 驱动的网站"目录" - wsgi.py # 同步服务器网关接口 - manage.py # 一个实用的命令行工具,可让你以各种方式与该 Django 项目进行交互
运行项目:切换到
manage.py
文件对应的文件夹目录后,运行python manage.py runserver
,此时服务被默认部署在127.0.0.1:8000
,如需更改,则在前面的命令末尾加上运行的地址(ip和端口)此时会发现,运行报错:
DJANGO.CORE.EXCEPTIONS.IMPROPERLYCONFIGURED: SQLITE 3.9.0 OR LATER IS REQUIRED (FOUND 3.x.x).
,这说明默认的sqlite数据库的版本不支持当前的django框架版本,此时要想成功运行有以下三个选择:- 降低django版本,即在安装django的时候指定版本号
- 升级sqlite(win系统中较为复杂)
- 更换默认数据库
这里采用是第三种方法,更换默认数据库为mysql,需要安装python控制mysql的库并在配置文件中进行更改:
python 3.x中控制mysql的库为
pymysql
,安装这个库更改如下配置文件:
在
__init__.py中
加入:import pymysql pymysql.install_as_MySQLdb()
因为在python2.x中,控制mysql的库是mysqldb,但是3.x中不再使用这个库了,需要适配
在
settings.py
中,更改DATABASES项为:'default': { 'ENGINE': 'django.db.backends.mysql', # 固定配置 'HOST': '127.0.0.1', # mysql地址 'PORT': '3306', # 端口号 'NAME': 'django', # 库名(组名) 'USER': 'root', # 你的用户名,一般默认是root 'PASSWORD': '123456', # 你root账户的密码 'OPTIONS': {'init_command': "SET sql_mode='STRICT_TRANS_TABLES'", }, }
原来的默认配置是:
'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': BASE_DIR / 'db.sqlite3', }
可以注释掉
执行以下命令进行数据迁移:
python manage.py makemigrations
python manage.py migrate
重新运行项目,在浏览器输入对应部署网址后看到初始界面表示项目创建成功:
二、路由管理初步&请求响应——HelloWorld
在项目中输出一个“HelloWorld”,需要通过配置相应的路由和对应的方法来完成
在项目配置文件的目录中创建一个新文件
views.py
(固定名称),并进行如下配置:from django.http import HttpResponse def hello(request): # 接受一个请求 return HttpResponse("Hello world ! ") # 返回一个响应
在
urls.py
文件中进行配置,导入刚才创建的views文件并对urlpatterns列表进行添加:from . import views # 添加这条导入信息 ''' 这是原来的urlpatterns urlpatterns = [ path('admin/', admin.site.urls), ] ''' # 新的urlpatterns urlpatterns = [ path('admin/', admin.site.urls), path('hello/', views.hello), ]
此时开启服务器,并在浏览器网址栏输入
127.0.0.1:8000/hello/
,可以看到如下结果:关于路由配置:
path(route, view, kwargs=None, name=None)
方法:四个参数- route: 字符串,表示 URL 规则,与之匹配的 URL 会执行对应的第二个参数 view。
- view: 用于执行与正则表达式匹配的 URL 请求。
- kwargs: 视图使用的字典类型的参数。
- name: 用来反向获取 URL。
re_path(route, view, kwargs=None, name=None)
方法,四个参数同上,用来匹配使用正则表达式的URL
三、后台管理初步
通过
manage.py
创建超级管理员用户:python manage.py createsuperuser
然后依次输入用户名和密码即可,中间的邮箱可以略过
这里选择用户名为
admin
,同时设定了密码也是admin,系统提示密码和用户名过于相似而且太短(少于8位),而且密码太简单,但是下面选择y
表示仍然这样设置,则超级用户设置成功。运行服务,在浏览器输入
127.0.0.1:8000/admin/
即可打开后台管理的登录页面:输入用户名和密码,进入后台:
发现这里有一个用户,就是刚才创建的
admin
四、创建应用(APP)
APP是Django框架中功能模块实现的部分,我们根据需要的功能来创建和设置不同的APP来进行使用。APP中有模型(Models)和视图(Views),是需要我们重点关注的部分。
1. 通过manage.py
创建APP:python manage.py startapp <名称>
这里创建了一个名为article
的APP用来发布文章
此时,在我们的项目文件夹中出现了新的文件夹,就是刚创建的app的文件夹,因此整个项目的文件树变成了以下情况:
mysite: # 项目文件夹
- mysite: # 配置文件夹
- __init__.py # 初始化文件,告诉 Python 该目录是一个 Python 包
- asgi.py # 异步服务器网关接口
- sttings.py # 配置文件
- urls.py # 路由文件,一份由 Django 驱动的网站"目录"
- views.py # 在步骤二中创建的文件,表示视图,即用户看到的界面,也是URL对应的方法
- wsgi.py # 同步服务器网关接口
- article: # 刚刚创建的APP的文件夹
- __init__.py
- admin.py # APP的后台管理文件,如需通过后台向数据库中添加数据,可以进行操作
- apps.py # APP的启动类
- migrations # 数据库表、字段等变更的记录
- models.py # 持久层,对数据库进行操作
- tests.py # 单元测试
- views.py # 视图,与配置文件夹中的作用一样
- manage.py # 一个实用的命令行工具,可让你以各种方式与该 Django 项目进行交互
2. 在全局设置中注册APP:
找到配置文件夹,修改其中的settings.py
中INSTALLED_APPS
字段,并在列表中添加上我们创建的APP。这里可以打开article
文件夹下的apps.py
文件,看到里面有一个类叫做ArticleConfig
,里面保存了我们这个APP的配置,因此,我们在INSTALLED_APPS
列表中添加'article.apps.ArticleConfig',
就可以了(逗号也要添加进去)。
3. 创建一个简单的文章模型,并通过后台添加数据:
首先在article的
models.py
中写入以下内容并保存:class Article(models.Model): title = models.CharField(max_length=30) # 设置一个属性为标题,对应数据库中的字符型,最大长度为30 content = models.TextField() # 设置内容属性,对应数据库中的文本型
进行数据库更新:
python manage.py makemigrations
python manage.py migrate
进行后台注册:
在article的
admin.py
中添加以下内容:# 前面有文件自带的一些import信息,不用修改,直接添加以下内容即可 from .models import Article admin.site.register(Article)
打开后台,发现已经有了Article:
添加3个数据:
4. (可选)将后台改为中文界面:
将配置文件夹的settings.py
中的LANGUAGE_CODE
改为zh-hans
五、模板的创建和使用
模板(Template)是为了方便同质化网页的部署而使用的,比如一般的个人博客,其每篇文章的页面都可能用的是一个html模板,只是标题和显示的内容不同,这里的html文件就是模板。我们在Django中可以自己制作或放置模板,来进行网页的批量处理。
1. 模板文件夹的位置和创建模板:
我们首先可以查看配置文件夹中的setings.py
文件,找到TEMPLATES
,默认情况下,其中DIRS
为空列表,而APP_DIRS
为True
表示在寻找模板文件时,会去APP文件夹内的模板文件夹找。
当DIRS
为空时,项目文件夹中即使有templates
文件夹,也不会优先去这里找模板文件,会按照settings.py
中的注册顺序,从每个APP的templates
文件夹找,只要找到对应名称的文件就会返回。
此时,我们可以先在article文件夹下创建templates
,并创建一个模板article_detail.html
内容如下:
<html>
<head>
</head>
<body>
<!-- 这里用双大括号标出变量,因为传来的article_obj是一个对象,
有title和content两个属性,可以直接调用 -->
<h2>{{article_obj.title}}</h2>
<p>{{article_obj.content}}</p>
</body>
</html>
2. 视图配置和路由管理
视图配置:
在article文件夹的
views.py
中添加一个方法和对应的依赖:from django.shortcuts import get_object_or_404 # 这个函数如果能查到就获取,差不到就抛出404异常 from .models import Article def article_detail(request, article_id): article = get_object_or_404(Article, id=article_id) # 传入模型,数据库按传入的id进行查找 content = {} # 一个内容字典,字典的键对应的就是html模板中的变量名 content["article_obj"] = article return render(request, 'article_detail.html', content) # 传入request,模板,内容字典
路由管理:
在配置文件夹的
urls.py
中添加一条路由解析记录:from article.views import article_detail path('article/<int:article_id>', article_detail, name='article_detail'), # 路由是article/int的部分全都用一个方法处理 # article_id就是url中出现的数字 # name用来标记这个路由,是它的别名
运行服务:
如果没有这个数据:
3. 通过模板获取文章列表
在APP文件夹的
templates
目录下创建一个新的模板文件article_list.html
:<html> <head> </head> <body> {% for article in articles %} <li><a href="{% url 'article_detail' article.id %}">{{ article.title }}</a></li> {% endfor %} </body> </html>
其中,
{% for %}{% endfor %}
是Django的模板标签,可以将一个QuerySet遍历出来,如果这里不用for标签,直接,就会在页面上显示一个QuerySet的对象,而不是需要的列表。而
{% url %}
也是Django的模板标签,负责查找路由配置{% url
标签的第一个参数就是路由配置中path(或re_path)函数中的name参数对应的值,从而将链接指定为这个路由;剩下的参数则是可选的,根据路由中的参数,按顺序填写。上文代码块中的[ , , ...]}` 这表明了`{% url %} article.id
对应的就是其路由配置中article/<int:article_id>
的article_id
<li>
标签和<a>
标签都是html的基本标签
在APP文件夹下的
views.py
中添加一个新的方法如下:def article_list(request): articles = Article.objects.all() # 获取所有Article对象 content = {} content["articles"] = articles return render(request, 'article_list.html', content)
由此,html模板文件中的变量就是
articles
,这是查到的Article对象的查询集合(QuerySet)在配置文件夹的
urls.py
中配置路由如下:from article.views import article_list path('article/', article_list, name='article_list'),
运行服务,打开
127.0.0.1:8000/article/
:证明配置成功了
再看
{% url %}
标签:由此我们就可以发现,url标签的使用正是通过如上3步进行配置的,每一步都互相影响。
此外,这里选择使用看起来很复杂的
{% url %}
标签,而不是直接配置成<a href="article/{{ article,id }}"></a>
,是因为如果不用url标签,一旦路由配置中的对应项路由进行了修改,所有使用这个路由的地方都需要重新改变;而使用url标签就可以大大简化这个过程,进一步解耦合。
六、路由管理进阶——通过总路由管理每个APP的路由
创建APP的路由文件:
在article文件夹下创建urls.py
,并将总路由配置文件(配置文件夹下的urls.py
)中与article有关的部分剪切到APP的路由配置文件中,得到APP的路由配置如下:
from django.urls import path
from . import views # 这里是article的views
urlpatterns = [
# 此时这里的路由地址已经是"127.0.0.1:8000/article"了
path('', views.article_list, name='article_list'),
path('<int:article_id>', views.article_detail, name='article_detail'),
]
同时,将总路由配置文件改为:
from django.contrib import admin
from django.urls import path, include # include是为了管理APP中的路由,引入的函数
from . import views # 配置文件夹下的views
urlpatterns = [
path('admin/', admin.site.urls),
path('hello/', views.hello),
path('article/', include('article.urls')), # 表示只要路由是article/xxx的部分全都由article的urls进行处理
]
七、静态资源
在开发过程中,一般将:
- 图片
- CSS
- js
- 插件
当做静态文件处理。
静态文件的文件夹默认名称是static
,static
的标准目录格式是:
- static
- img
- CSS
- js
- plugins
一般会将static
放在对应的APP文件夹下,在html模板中引用对应位置的资源是,需要使用{% static %}
标签引用:
{% load static %} <!-- 如果下面用{% static %}标签,则在模板开头需要使用这个标签加载资源 -->
<img src="{% static 'img/1.png' %}" alt="">
静态文件的设置在配置文件夹下的settings.py
文件中有对应的配置。
八、请求和相应
这一部分主要是处理用户发来的请求并向用户返回响应的过程。
请求
请求的方式:GET/POST
在视图中获取请求:每个视图的函数的参数都是request,其中就包含了用户提交的所有请求信息。通过
reuqest.method
我们可以获取到用户请求的方式。GET请求:直接在URL上传递参数
在URL的末尾增加”?n1=xxx&n2=xx”,通过
request.GET
就可以获取到传递参数的字典POST请求会发送一个请求体,通过
request.POST
获得请求体的数据
响应
- 简单的响应——直接返回字符串
HTttpResponse(str)
,如果这里的字符串符合html格式,也会被自动变成对应的样式 - 结合htnml模板的响应——
render()
- 重定向响应——
redirect(new_url)
,收到这个响应的用户会对新的url发起请求
表单机制
在html中设置表单时,注意django的csrf_token机制,需要加上{% csrf_token %}
标签
<form method="post" action="/login/">
{% csrf_token %}
<input type="text" name="username" placeholder="用户名">
<input type="password" name="pwd" placeholder="密码">
<input type="submit" value="提交">
</form>
同时在对应的路由的视图函数中,可以根据请求方法的不同,做出不同的响应(如果只是GET,就返回登录页面;如果是POST,就解析提交的用户名和密码,进行验证,返回结果)
九、数据库操作
django自带了ORM,可以帮助我们对数据库操作,因此我们只要学习django的ORM就可以完成对数据库的操作了。
django可以对数据库的操作有:
- 创建、删除、修改表(table)
- 对表中的数据进行增删改查
创建和修改表、字段
在APP文件夹下的models.py
中进行修改,并进行数据库迁移的两条指令:
只要在这个文件中,写了继承了models.Model
的类,django就会帮我们在数据库中创建<app名_小写类名>
的表。如上文中写过的:
class Article(models.Model):
title = models.CharField(max_length=30) # 设置一个属性为标题,对应数据库中的字符型,最大长度为30
content = models.TextField() # 设置内容属性,对应数据库中的文本型
此时,因为我们的APP叫做article
,所以MySQL数据库中,就创建了article_article
的表,并创建了title
和content
字段。
如果此时需要删除旧字段,则直接在类中删去对应属性,并进行数据库迁移即可;如果需要添加新的字段,考虑到数据库可能原有数据,此时需要为新字段设置默认值或允许为空。
设置默认值:
data = models.TextField(default="hello")
允许为空:
data = models.TextField(null=True, blank=True)
注意:每次调整了models.py
后都需要执行两条数据库迁移的命令
表中数据的增删改查
先从models.py
中导入模型类,使用类方法进行增删改查,这里以上面的Article
为例
查询
获取所有数据
datas = Article.objects.all() # 得到的是一个QuerySet类型的对象 # 遍历这个对象,会得到<Article: Article object (1)> ...,即为实际查到的一行数据 # 每行数据显示的名称可以通过改变模型类中的__str__方法实现 # 获取数据的分量(不同字段的对应值),可以通过访问属性的方法实现 # 如: data.first().title first()方法是取出QuerySet的第一个数据
获取筛选后的数据
data = Article.objects.filter(id=1).first() # 因为即使只查到了返回的也是QuerySet还需要用first() # 这里限制了返回的对象的id为1
添加数据
Article.objects.create(title="four", content = "article four") # 直接添加一条新数据,没写到的字段必须是有默认值或者允许为空的
删除数据
删除指定数据
Article.objects.filter(id=1).delete() # 删除所有id为1的数据
删除所有数据
Article.objects.all().delete()
更新数据
更新所有数据的分量
Article.objects.all().update(title="None")
更新特定数据的分量
Article.objects.filter(id=1).update(title="None")