大家好,欢迎来到IT知识分享网。
一、Django构建项目
1.1 创建项目
命令: django-admin startproject 项目名
django-admin startproject django_demo01
django_demo01/ manage.py django_demo01/ __init__.py settings.py urls.py asgi.py wsgi.py
这些目录和文件的说明如下:
- manage.py 一个让你用各种方式管理 Django 项目的命令行工具。
- init.py 一个空文件,告诉 Python 这个目录应该被认为是一个 Python 包
- settings.py 项目的配置文件,有关于数据库、编码、时区等
- urls.py 项目的 url路由配置,即url路由与其函数的对应配置
- wsgi.py :作为你的项目的运行在 WSGI 兼容的Web服务器上的入口。
- asgi.py :作为你的项目的运行在 ASGI 兼容的 Web 服务器上的入口
1.2 启动项目
在该cmd目录下执行如下命令,可以启动项目:
python manage.py runserver
该命令后续可以增加参数,如:
python manage.py runserver 8081 python manage.py runserver 127.0.0.1:8888
在浏览器中访问提示的服务器网址:Starting development server at http://127.0.0.1:8000/ 中的
1.3 创建Django应用
cmd窗口中,进入最外层的mysite,在这个目录下,我们可以输入如下命令,创建一个新的子应用:
python manage.py startapp app01
创建完成后的文件目录结构如下:
─django_demo01 │ db.sqlite3 │ manage.py │ ├─app01 │ │ admin.py │ │ apps.py │ │ models.py │ │ tests.py │ │ views.py │ │ __init__.py │ │ │ └─migrations │ __init__.py │ └─django_demo01 │ asgi.py │ settings.py │ urls.py │ wsgi.py │ __init__.py │ └─__pycache__ settings.cpython-38.pyc urls.cpython-38.pyc wsgi.cpython-38.pyc __init__.cpython-38.pyc
- init.py 是一个空文件,表示当前目录news可以当作一个python包使用。
- tests.py 文件用于开发测试用例,在实际开发中会有专门的测试人员,这个事情不需要我们来
做。 - models.py 文件跟数据库操作相关。
- views.py 文件跟接收浏览器请求,进行处理,返回页面相关。
- admin.py 文件跟网站的后台管理相关。
- migrations 数据库迁移文件。
1.4 应用注册
INSTALLED_APPS = ( 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'app01', )
1.5 服务说明
能够打开一个django
的欢迎页面,是因为启动了django自带的一个简易web服务器,它是一个用纯 Python 写的轻量级的 Web 服务器。仅仅用于开发环境,不要在生产环境使用。
在这个服务器中,在需要的情况下会对每一次的访问请求重新载入一遍 Python 代码。所以你不需要为了让修改的代码生效而频繁的重新启动服务器。然而,一些动作,比如添加新文件,将不会触发自动重新加载,这时你得自己手动重启服务器。
二、Djnago请求
2.1 请求流程
2.2 urls.py配置
from django.contrib import admin from django.urls import path from app01 import views urlpatterns = [ path('admin/', admin.site.urls), path('firstRequest/', views.FirstRequest), ]
2.3 views.py
from django.shortcuts import render from django.http import HttpResponse # Create your views here. def FirstRequest(request): return HttpResponse("第一个Django请求成功")
2.4 启动服务
python manage.py runserver
2.5 浏览器发送请求
其中在views.py文件中,每一个请求方法需要有一个request参数,通过该参数可以获取请求相应信息。可以使用dir(request)查看详细。
[ 'COOKIES', 'FILES', 'GET', 'META', 'POST', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_current_scheme_host', '_encoding', '_get_full_path', '_get_post', '_get_raw_host', '_get_scheme', '_initialize_handlers', '_load_post_and_files' , '_mark_post_parse_error', '_messages', '_read_started', '_set_content_type_params', '_set_post', '_stream', '_upload_handlers', 'accepted_types', 'accepts', 'body', 'build_absolute_uri', 'close', 'content_params', 'content_type', 'csrf_processing_done', 'encoding', 'environ', 'get_full_path', 'get_full_path_info', 'get_host', 'get_port', 'get_signed_cookie', 'headers', 'is_secure', 'method', 'parse_file_upload', 'path', 'path_info', 'read', 'readline', 'readlines', 'resolver_match', 'scheme', 'session', 'upload_handlers', 'user' ]
2.6 开发第一个登录表单
- urls.py配置
from django.contrib import admin from django.urls import path from app01 import views urlpatterns = [ path('admin/', admin.site.urls), path('firstRequest/', views.FirstRequest), path('login/', views.login), ]
- views.py添加业务方法
def login(request): # 返回页面
html = ''' <html> <body> <form method="post"> 用户名:<input name = "username" type="text"></input></br> 密码:<input name = "password" type = "password"></input></br> <input type="submit" value="登录"></input> </form> </body> </html> ''' # return render(request, 'login.html') return HttpResponse(html)
- 浏览器发送请求测试
三、Django配置
3.1 settings介绍
django项目创建后,在主应用中,会有一个settings.py文件,这个就是该项目的配置文件
- settings文件包含Django安装的所有配置
- settings文件是一个包含模块级变量的python模块,所以该模块本身必须符合python规则,并且可以使用python的语法
- settings中的所有配置项的key必须全部大写
- settings中每一个配置项都有默认值,默认配置内容在django/conf/global_settings.py中可以查看到,项目中不需要导入该模块,django框架会自动获取
- settings中可以添加自定义的配置项
可以在global_settings
中进行查看
from django.conf import global_settings
3.2 应用settings文件
- manage.py启动
默认在manage.py中配置:
if __name__ == "__main__": os.environ.setdefault("DJANGO_SETTINGS_MODULE", "firstdjango.settings")
- 手动指定配置文件位置
cmd命令启动如下:
python manage.py runserver 0.0.0.0:8000 --settings=firstdjango.settings
- 服务器部署启动
在wsgi.py中配置:
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "firstdjango.settings")
3.3 常用配置项解析(重点)
import os """ 当前文件所在文件夹的上一级目录的绝对路径 切记2个 os.path.dirname """ #BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) BASE_DIR = Path(__file__).resolve().parent.parent # E:\Code_Learn\Python全栈工程师\Django\django_demo01 """ 用于加密session,一个随机的字符串 这样生成: from django.core.management import utils utils.get_random_secret_key() """ SECRET_KEY = 'django-insecure-yibecivjsju-iym&5fc!6x9)z$8!u=d7bwnpk6^tfythk)gzc)' # 调试模式,可以看到错误的所有相信信息,部署时一定要修改为False DEBUG = True """ 允许访问的域名设置 开发环境不用理会 运行环境,配置 DEBUG = False后, 如果允许所有域名访问,则设置 ALLOW_HOSTS = ['*'] 如果指定某些域名可以访问,则设置 ALLOW_HOSTS = ['*.baidu.com'] """ ALLOWED_HOSTS = [] """ 应用的配置, 如:'app01.apps.App01Config' 如果没有 App01Config,那么可以配置为 'app01' """ INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', # 只有 DEBUG = Ture 才有效 'app01' # 子应用必须配置,否则不起作用 ] """ 中间层配置 自己编写的 中间层 需要配置在最后 譬如: mymidlle.md.TestMiddleware """ MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ] # 配置基础的urls ROOT_URLCONF = 'django_demo01.urls' # 配置模板 TEMPLATES = [ {
'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR, 'templates')], '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', ], }, }, ] # 服务器部署的WSGI配置 WSGI_APPLICATION = 'django_demo01.wsgi.application' """ 数据库配置 mysql在python3的使用,需要在 __init__.py 中加入以下代码: import pymysql pymysql.install_as_MySQLdb() """ # DATABASES = {
# 'default': {
# 'ENGINE': 'django.db.backends.sqlite3', # 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), # } # } DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql', 'NAME': 'django_test1', 'USER': 'root', 'PASSWORD': '', 'HOST': '127.0.0.1', 'PORT': '3306', } } """ 用户密码验证 """ AUTH_PASSWORD_VALIDATORS = [ {
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', }, {
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', }, {
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', }, {
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', }, ] # 语言选择 , zh-Hans 为中文 LANGUAGE_CODE = 'en-us' # 时区 Asia/Shanghai 是中国时区 TIME_ZONE = 'UTC' # 国际化 USE_I18N = True # 本地化 USE_L10N = True # 使用时区,配套TIME_ZONE使用,必须设置为 False USE_TZ = False """ 静态文件的路径,默认是 static 如果在各自项目的static目录以外,还有目录存放静态文件,需要添加如下属性: STATICFILES_DIRS = ( os.path.join(BASE_DIR, "common_static1"), '/var/www/static/', ) """ STATIC_URL = '/static/'
3.4 程序中获取settings中的配置项
如果在项目代码中需要获取settings中的配置项,这样获取:
# 切记不要导入具体的settings模块的路径,会形成高耦合 # 这样的方式是不可取的:from mysite import settings from django.conf import settings d = settings.DEBUG
四、URL调度器(重点)
4.1 工作原理
django通过urlconf来映射视图函数,只区分路径,不区分http方法
- Django确定要使用的根URLconf模块,一般是在settings中的ROOT_URLCONF设置的值,但是如果传入 HttpRequest 对象具有一个urlconf 属性(由中间件设置),则其值将用于代替 ROOT_URLCONF设置。
- Django加载该URLconf模块并查找变量 urlpatterns,它是一个列表django.urls.path() 和 / 或django.urls.re_path()实例。
- Django按顺序遍历每个URL模式,并停在与请求的URL匹配的第一个URL模式,需要特别注意编写的顺序
- 一旦某个URL模式匹配,Django就会导入并调用给定的视图,该视图是一个简单的Python函数(或基于类的视图方法)。该视图通过以下参数传递:
- 一个HttpRequest实例。
- 如果匹配的URL模式没有返回任何命名组,则来自正则表达式的匹配作为位置参数提供。
- 关键字参数由路径表达式匹配的任何命名部分组成,并由可选的kwargs参数传给 django.urls.path()或django.urls.re_path()。
- 如果没有URL模式匹配,或者在此过程中的任何点发生异常,Django将调用适当的错误处理视图
4.2 简单示例
- 在子应用下创建urls.py,内容如下
urlpatterns = [ ]
- 在项目的应用中添加子应用urls.py配置
from django.contrib import admin from django.urls import path, include from app01 import views urlpatterns = [ path('admin/', admin.site.urls), path('firstRequest/', views.FirstRequest), path('login/', views.login), path('app01/', include('app01.urls')) ]
- 配置子应用urls.py
from django.contrib import admin from django.urls import path, include from app01 import views urlpatterns = [ path('admin/', admin.site.urls), path('firstRequest/', views.FirstRequest), path('login/', views.login), path('app01/', include('app01.urls')) ]
- 浏览器进行访问
http://127.0.0.1:8000/app01/login/
4.3 路由中的参数匹配
配置项目的urls.py
from django.contrib import admin from django.urls import path, include from app01 import views urlpatterns = [ path('admin/', admin.site.urls), path('firstRequest/', views.FirstRequest), path('login/', views.login), path('app01/', include('app01.urls')) ]
配置app01
的urls.py
from django.urls import path, include from . import views urlpatterns = [ path('login/', views.login), path('articles/2024/', views.articles_2024), path('articles/<int:year>/', views.articles_year), path('articles/<int:year>/<int:month>/', views.articles_year_month), path('articles/<int:year>/<int:month>/<slug:slug>/', views.articles_year_month_slug), path('articles/<str:str>/', views.str_test), path('articles/<path:path>/', views.path_test), path('articles/<uuid:uuid>/', views.uuid_test) ]
app01
的views.py
# 创建articles 2024处理函数 def articles_2024(request): return HttpResponse('articles 2024') def articles_year(request, year): return HttpResponse(f'article_year, year:{
year}') def articles_year_month(request, year, month): return HttpResponse(f'article_year_month, year:{
year},month:{
month}') def articles_year_month_slug(request, year, month, slug): return HttpResponse(f'article_year_month_slug, year:{
year}, month:{
month}, slug:{
slug}') def str_test(request, str): return HttpResponse(f'str_test: {
str}') def path_test(request, path): return HttpResponse(f'path_test: {
path}') def uuid_test(request, uuid): return HttpResponse(f'uuid_test: {
uuid}')
测试:
按照从上往下的顺序依次测试和匹配。
注意:测试uuid要注释掉str
笔记:
- 从URL中捕获值,请使用尖括号
- 捕获的值可以选择包含转换器类型。例如,用于 <int:name>捕获,前面的int指整数参数,name是参数的名称
- 没有必要添加一个前导斜杠,因为每个URL都有,例如,使用articles而不是/articles。
- 示例请求说明:
- /articles/2005/03/ 匹配列表中的第三个条目。Django会调用这个函数,views.month_archive(request, year=2005, month=3)
- /articles/2003/*会匹配列表中的第一个模式,而不是第二个模式,因为模式是按顺序测试的,而第一个模式是第一个要传递的测试。看看利用匹配顺序插入像这样的特殊情况。在这里,Django会调用这个函数 views.special_case_2003(request)
- /articles/2003*不匹配任何这些模式,因为每种模式都要求URL以斜线结尾,不过在浏览器访问时,会自动添加 / 。
- /articles/2003/03/building-a-django-site/ 将匹配最终模式。Django会调用这个函数 。views.article_detail(request, year=2003, month=3, slug=“building-a-django-site”)
路径转换器
- str:匹配任何非空字符串,不包括路径分隔符’/’。如果转换器不包含在表达式中,这是默认值。
- int:匹配零或任何正整数。返回一个int。
- slug:匹配由ASCII字母或数字组成的字符串,以及横线和下划线字符。例如, building-your-1st-django_site可以匹配,django_@site是不可以匹配的。
- uuid:匹配格式化的UUID。为防止多个URL映射到同一页面,必须包含破折号,并且字母必须是小写。例如,075194d3-6885-417e-a8a8-6c931e272f00。返回一个 UUID实例。
- path:匹配任何非空字符串,包括路径分隔符 ‘/’,可以匹配完整的URL路径,而不仅仅是URL路径的一部分str,使用时要谨慎,因为可能造成后续的所有url匹配都失效。
UUID的生成:
#获取uuid import uuid print(uuid.uuid1())
4.4 自定义路径转换器
转换器是一个包含以下内容的类:
- 一个regex类属性,作为一个re匹配字符串。
- to_python(self, value)方法,它处理匹配的字符串转换成要传递到视图函数的类型。
- to_url(self, value)方法,用于处理将Python类型转换为URL中使用的字符串。
定义方式如下:
- 新建一个converters.py文件,在文件中定义一个FourDigitYearConverter类:
class FourDigitYearConverter(object): regex = '[0-9]{4}' def to_python(self, value): return int(value) def to_url(self, value): return '%04d' % value
- 使用register_converter()方法在URLconf中注册自定义转换器类 :
from django.urls import path, include from . import views from .converters import FourDigitYearConverter from django.urls import register_converter register_converter(FourDigitYearConverter, 'yyyy') urlpatterns = [ # 自定义路径转换器path path('articles/<yyyy:year>/', views.articles_year) ]
4.5 使用正则表达式
使用正则表达式匹配路径,请使用 re_path()而不是path()
在Python正则表达式中,命名正则表达式组的语法是(?P<name>pattern),其中name是组的名称,并且 pattern是一些要匹配的模式
示例:
from django.urls import path, re_path from . import views # url() 是 re_path 的别名,不推荐使用 urlpatterns = [ re_path(r'^articles/(?P<year>[0-9]{4})/$', views.articles_year), re_path(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.articles_year_month()), re_path(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<slug>[\w-]+)/$', views.articles_year_month_slug) ]
注意事项:
- 匹配的URL会受到一些限制。例如,年份10000将不再匹配,因为年份整数限制为四位数字
- 无论正则表达式匹配什么类型,每个捕获的参数都以字符串的形式发送到视图
- 除了命名的组语法,例如(?P<year>[0-9]{4}),也可以使用较短的未命名组,例如([0-9]{4}),但是不建议这样使用,会引起未知的匹配
嵌套参数:
from django.urls import re_path urlpatterns = [ # 不推荐, 匹配 blog/page-3/ re_path(r'^blog/(page-(\d+)/)?$', blog_articles), # 推荐 ,匹配:comments/page-2/ 路径到 comments(request, page_numer) re_path(r'^comments/(?:page-(?P<page_number>\d+)/)?$', comments), ] def comments(request, page_number): return HttpResponse(f'comments:page_number:{
page_number}')
4.6 使用默认值
URLConf中:
from django.urls import path from . import views urlpatterns = [ path('blog/', views.do_page), path('blog/<int:num>/', views.do_page), ]
views中:
def do_page(request, num=1): print(num) return HttpResponse(f'do_page:num:{
num}')
4.7 错误处理
- handler400- 状态码400
- handler403- 状态码403
- handler404- 状态码404
- handler500- 状态码500
- 在 settings中修改配置:
DEBUG = False ALLOWED_HOSTS = ['*']
- 在主应用的urls中配置:
# app01是子应用 handler404 = "app01.views.page_not_found"
- 在app01应用的views中添加函数page_not_found:
def page_not_found(request, exception): return HttpResponse('自定义的404错误页面')
- 浏览器测试访问,找不到匹配的路由
4.8 引用其他URL调度器
- 多个 patterns
from django.urls import include, path extra_patterns = [ path('blog/', views.do_page), path('blog/<int:num>/', views.do_page), ] urlpatterns = [ path('', include(extra_patterns)) ]
- 使用include消除重复前缀
from django.urls import path from . import views urlpatterns = [ path('<page_slug>-<page_id>/history/', views.history), path('<page_slug>-<page_id>/edit/', views.edit), path('<page_slug>-<page_id>/discuss/', views.discuss), path('<page_slug>-<page_id>/permissions/', views.permissions), ] # 修改为: from django.urls import include, path from . import views urlpatterns = [ path('<page_slug>-<page_id>/', include([ path('history/', views.history), path('edit/', views.edit), path('discuss/', views.discuss), path('permissions/', views.permissions), ])), ]
举例子
from django.urls import path, include, re_path from . import views extra_patterns = [ # 使用默认值 path('blog/', views.do_page), path('blog/<int:num>/', views.do_page), ] urlpatterns = [ path('articles/', include([ path('2024/', views.articles_2024), path('<int:year>/', views.articles_year), path('<int:year>/<int:month>/', views.articles_year_month), ])) ]
- 传递捕获的参数
在主urls中配置:
urlpatterns = [ path('admin/', admin.site.urls), # 这里捕获username参数,类型为字符串 path('<username>/app01/', include('app01.urls')) ]
对应的 app01应用下的urls中配置:
urlpatterns = [ path('arg_test/', views.arg_test), ]
对应的app01应用下的views中编写函数:
def arg_test(request, username): # 编写对应的业务逻辑 return HttpResponse(f'username {
username}')
4.9 额外的参数
from django.urls import path from . import views urlpatterns = [ # 会传递给 views.param_test(request, user, password) path('param_test/', views.param_test, {
'user': 'root', 'password': '1234'}), ]
app01.views.py
def param_test(request, user, password): return HttpResponse(f'user {
user}, password {
password}')
4.10 URL反向解析
url调度器除了从用户发起请求,到匹配对应的view,还能在python程序中调用进行匹配,通过 path或re_path 中 的name属性进行解析
- 在模板中,使用url模板标签
- 在Python代码中(主要是views),使用 reverse() 函数
- 在模型实例中,使用 get_absolute_url() 方法
示例:
app01
的urls
中配置:
from django.urls import path from . import views urlpatterns = [ path('reverse/', views.reverse_test), path('articles/<int:year>/', views.year_archive, name='news-year-archive') ]
views.py
def reverse_test(request): return HttpResponseRedirect(reverse('news-year-archive', args=(6666,))) def year_archive(request, year): return HttpResponse(f"year_archive: year:{
year}")
测试:
2 在模板中测试
urls.py
from django.urls import path, include, re_path from . import views urlpatterns = [ path('do_html/', views.do_html), ]
- 模板中代码
<!--模板中: --> <a href="{% url 'news-year-archive' 2004 %}">url反向解析测试</a>
- views.py跳转到页面
def year_archive(request, year): return HttpResponse(f"year_archive: year:{
year}") def do_html(request): return render(request, 'redirect_test.html')
4.11 命名空间
主要用于配合第 10 点 url反向解析 使用,多个不同的urls文件中可能配置同名的 name,那么为了进行区分,给不同的urls进行不同的命名,切记同一个项目下命名空间不能重复!
通过在 url调度器的模块中,定义 app_name = ‘app01’ 来命名
from django.urls import path from . import views # 定义,一般命名空间和子应用名相同,便于记忆 app_name = "app01" urlpatterns = [ path('reverse/', views.reverse_test), path('do_html/', views.do_html), ... ] # 调用,一旦有了命名空间,调用时就必须使用app01: 前缀 def reverse_test(request): return HttpResponseRedirect(reverse('app01:news-year-archive', args=(6666,))) <a href="{% url 'app01:news-year-archive' 2004 %}">url反向解析测试</a>
命名空间可以进行嵌套:
# 在 urls 中配置如下: from django.urls import path from . import views # 定义命名空间,一般命名空间名和子应用名相同,便于记忆 app_name = 'app01' extra_patterns = ( [ path('app_name/', views.app_name, name='app_name'), ], # 此处就是嵌套的命名空间 'extra' ) urlpatterns = [ path('', views.IndexView.as_view(), name='index'), path('<int:pk>/', views.DetailView.as_view(), name='detail'), path('extra/', include(extra_patterns)), ... ] # 在模板中使用: <a href="{% url 'app01:extra:app_name' %}">点击链接</a>
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/126943.html