一 什么是web框架
框架(framework),特指为解决一个开放性问题而设计的具有一定约束性的支撑结构,使用框架可以帮你快速开发特定的系统,简单地说,就是你用别人搭建好的舞台来做表演。对于所有的Web应用,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端。最简单的Web应用就是先把HTML用文件保存好,用一个现成的HTTP服务器软件,接收用户请求,从文件中读取HTML,返回。
二 MVC和MTV模型
著名的MVC模式:所谓MVC就是把web应用分为模型(M),控制器(C),视图(V)三层;他们之间以一种插件似的,松耦合的方式连接在一起。
模型负责业务对象与数据库的对象(ORM),视图负责与用户的交互(页面),控制器(C)接受用户的输入调用模型和视图完成用户的请求。
Django的MTV模式本质上与MVC模式没有什么差别,也是各组件之间为了保持松耦合关系,只是定义上有些许不同,Django的MTV分别代表:
Model(模型):负责业务对象与数据库的对象(ORM)
Template(模版):负责如何把页面展示给用户
View(视图):负责业务逻辑,并在适当的时候调用Model和Template
此外,Django还有一个url分发器,它的作用是将一个个URL的页面请求分发给不同的view处理,view再调用相应的Model和Template
三 django常用命令以及基本配置
1 # 查看django版本 2 $ python -m django --version 3 4 # 创建项目,名为mysite 5 $ django-admin startproject mysite 6 7 # Django项目环境终端 8 $ python manage.py shell 9 10 # 创建应用程序,确保和 manage.py 是同一目录 11 $ python manage.py startapp polls 12 13 14 #以下为常用命令 15 # 启动django 16 $ python manage.py runserver 17 $ python manage.py runserver 8080 18 $ python manage.py runserver 0.0.0.0:8000 19 20 # 运行创造模型变化迁移 21 $ python manage.py makemigrations 22 23 # 运行应用模型变化到数据库 24 $ python manage.py migrate 25 26 # 同步数据库 27 $ python manage.py syncdb 28 29 # 清空数据库(保留空表) 30 $ python manage.py flush 31 32 # admin创建管理员用户 33 $ python manage.py createsuperuser 34 35 # 修改用户密码 36 $ python manage.py changepassword username
注:自动重新加载 runserver,根据需要开发服务器自动重新加载Python代码为每个请求。您不需要重新启动服务器代码更改生效。然而,像添加文件某些操作不触发重新启动,所以你必须重新启动在这些情况下的服务器。
基本目录结构及作用
mysite/ # 项目的容器,名字随便起 manage.py # 命令行实用工具,以各种方式与该Django项目进行交互 mysite/ # 实际的Python项目 __init__.py # 空文件,导入不出错 settings.py # 这个Django项目配置 urls.py # 这个Django项目的URL声明; 一个Django驱动网站的“目录” wsgi.py # 一个入口点为WSGI兼容的Web服务器,以满足您的项目
配置文件
INSTALLED_APPS = [ 'django.contrib.admin', # 管理站点。 'django.contrib.auth', # 认证系统 'django.contrib.contenttypes',# 用于内容类型的框架 'django.contrib.sessions', # 会话框架 'django.contrib.messages', # 消息框架 'django.contrib.staticfiles', # 管理静态文件的框架 'blog.apps.BlogConfig', #是创建应用app的名字,如果项目创建了app则必须要添加app的名字 ]
数据库
# django支持sqlite,mysql, oracle,postgresql数据库 # django默认使用sqlite的数据库,默认自带sqlite的数据库驱动 , 引擎名称:django.db.backends.sqlite3 # 由于Django内部连接MySQL时使用的是MySQLdb模块,而python3中还无此模块,所以需要使用pymysql来代替 # 设置放置的与project同名的配置的 __init__.py文件中 import pymysql pymysql.install_as_MySQLdb() # 在settings 中修改DATABASES DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'dbname', # 数据库名称 'USER': 'root', # 用户名 'PASSWORD': 'xxx', # 密码 'HOST': '', # IP,留空默认localhost 'PORT': '', # 端口 } }
模板
# 在settings里修改,放html文件 TEMPLATE_DIRS = ( os.path.join(BASE_DIR,'templates'), )
静态文件
# 在settings里修改添加,放css,js,image等文件 # 创建static文件夹 STATIC_URL = '/static/' # 相当于别名 STATICFILES_DIRS = ( os.path.join(BASE_DIR,'static'), ) # 如引用Jquery文件,有俩种形式 1、 直接引入 2、 {% load staticfiles %} {% static '文件名' %} # 推荐使用第二种形式,第一条代码并处理引入文件代码的上方 # 再每个app里面我们可能会有多个文件配置信息,则可以相应的将文件夹放在app的文件夹下,并修改路径。
引入静态文件的注意点
# 注意1: # 为了后端的更改不会影响前端的引入,避免造成前端大量修改 STATIC_URL = '/static/' # 引用名 STATICFILES_DIRS = ( os.path.join(BASE_DIR,"statics"), # 实际名 ,即实际文件夹的名字 ) # django对引用名和实际名进行映射,引用时,只能按照引用名来,不能按实际名去找 # <script src="/statics/jquery-3.3.1.js"></script> # ------error-----不能直接用,必须用STATIC_URL = '/static/': # <script src="/static/jquery-3.3.1.js"></script> # 注意2(statics文件夹写在不同的app下,静态文件的调用): STATIC_URL = '/static/' STATICFILES_DIRS=( ('hello',os.path.join(BASE_DIR,"app01","statics")), ) # <script src="/static/hello/jquery-3.3.1.min.js"></script> # 注意3: STATIC_URL = '/static/' {% load staticfiles %} # <script src={% static "jquery-3.3.1.min.js" %}></script> # 注意4: 配置STATIC路径时,记得要最后一个元组后面加逗号,不然会影响渲染
四 Django URL(路由系统)
1 URL调度
URL配置(URLconf)就像Django 所支撑网站的目录。它的本质是URL模式以及要为该URL模式调用的视图函数之间的映射表;你就是以这种方式告诉Django,对于这个URL调用这段代码,对于那个URL调用那段代码。
django中的路由系统和其他语言的框架有所不同,在django中每一个请求的url都要有一条路由映射,这样才能将请求交给对一个的view中的函数去处理。其他大部分的Web框架则是对一类的url请求做一条路由映射,从而是路由系统变得简洁。
django最新版本url默认不支持正则,标准格式:
path('admin/', admin.site.urls),
如果需要使用正则,需要导入:re_path, 使用方法
from django.urls import path,re_path urlpatterns = [ path('admin/', admin.site.urls), re_path(r'^test-(d+)-(d+)/', views.test), path('index/', views.index), ]
如何动态构造:
urlpatterns = [ path('admin/', admin.site.urls), path('show_time/', views.show_time), #无名分组 re_path(r'article/(d{4})$', views.article_year), #有名分组:(?p<分组名>正则语法) ] # 参数说明 # 一个正则表达式字符串 # 一个可调用对象,通常为一个视图函数或一个指定视图函数路径的字符串 # 可选的要传递给视图函数的默认参数(字典形式) # 一个可选的name参数
需要注意: url多传了一个参数,那views函数得多接受一个参数
def show_time(requset): # return HttpResponse("Hello") t = time.ctime() return render(requset,"index.html",{"t":t}) #locals() # 对应接收值 def article_year(request,y): return HttpResponse(y) 对应该的index.html <h1>time:{{ t }}</h1>
2 name别名
name就是该views函数的别名
name别名要结合模板文件来用方便管理
urls.py urlpatterns = [ path("register",views.register,name="reg"), ] 在html文件中引入 <form action="{% url 'reg' %}" method="post">
3、路由分发
如果一个项目下有很多的app,那么在urls.py里面就要写巨多的urls映射关系。这样看起来很不灵活,而且杂乱无章。这时候就要根据不同的app来分发不同的url请求
首先,在urls.py里写入urls映射条目。注意要导入include方法
from django.contrib import admin from django.urls import path, re_path, include from blog import views urlpatterns = [ path('admin/', admin.site.urls), re_path(r'^blog/', include('blog.urls')), ]
这条关系的意思是将url为”blog/“的请求都交给blog下的urls去处理
其次,在blog下创建一个urls.py的文件,用来处理请求的url,使之与views建立映射
from django.urls import path, re_path, include from blog import views urlpatterns = [ re_path(r'article/(d{4})$',views.article_year), re_path(r'article/(?P<year>d{4})/(?P<month>d{2})',views.article_year_month), re_path(r'article/(?P<year>d{4})/(?P<month>d{2})/d+',views.article_year_month), re_path(r"register",views.register,name="reg"),
五、Django Views(视图函数)
http请求中产生两个核心对象:
http请求: HttpRequest对象
http响应: HttpRequest对象
1、概述
client端通过http请求——去url的路由找到相应的视图函数——触发视图函数——再去modes取数据——取到数据后——再通过创建模——views函数把响应对象——返回给client最终显示的内容
视图文件(views.py)在app目录下才有
通过相应的url请求来写不同请求的视图函数
from django.shortcuts import render, HttpResponse import time # Create your views here.
2、视图函数的编写
视图要结合url路由、models、模板文件在一起来用
def show_time(requset): # return HttpResponse("Hello") t = time.ctime() return render(requset,"index.html",{"t":t}) #locals()
3.视图函数的编写
def article_year(request,y): return HttpResponse(y) def article_year_month(request,year,month): return HttpResponse("year:%s month:%s"%(year,month))
4、请求和响应对象
Django 使用请求和响应对象在系统间传递状态。
当请求一个页面时,Django 创建一个 HttpRequest
对象包含原数据的请求。
然后 Django 加载适当的视图,通过 HttpRequest
作为视图函数的第一个参数。每个视图负责返回一个HttpResponse
目标。
A、HttpRequest对象
HttpRequest.scheme
一个字符串表示请求的方案(HTTP或HTTPS)通常
HttpRequest.path
一个字符串的完整路径的请求
HttpRequest.method
请求的HTTP方法。这是保证要大写 if request.method == 'GET': do_something() elif request.method == 'POST': do_something_else()
HttpRequest.GET
字典像包含所有给定的HTTP GET参数对象。
HttpRequest.POST
字典像包含所有给定的HTTP POST参数对象,提供请求包含表单数据。
HttpRequest.COOKIES
一个标准的Python字典,包含了所有的COOKIES,key和values都是字符串
HttpRequest.FILES
字典像对象包含所有上传的文件。 html 标签 <input type="file" name="" /> filename # 上传的文件名 content_type # 上传文件的类型 content # 上传文件的内容
HttpRequest.META
一个标准的Python字典包含所有可用的HTTP头。可用标题取决于客户端和服务器,但这里是一些例子:
CONTENT_LENGTH – 请求体的长度(一个字符串)。 CONTENT_TYPE – 请求体的类型。 HTTP_ACCEPT - 为响应–可以接受的内容类型。 HTTP_ACCEPT_ENCODING – 接受编码的响应 HTTP_ACCEPT_LANGUAGE – 接受语言的反应 HTTP_HOST – 客户端发送的HTTP主机头。 HTTP_REFERER – 参考页面 HTTP_USER_AGENT – 客户端的用户代理字符串。 QUERY_STRING – 查询字符串,作为一个单一的(分析的)字符串。 REMOTE_ADDR – 客户端的IP地址 REMOTE_HOST – 客户端的主机名 REMOTE_USER – 用户通过Web服务器的身份验证。 REQUEST_METHOD – 字符串,如"GET"或"POST" SERVER_NAME – 服务器的主机名 SERVER_PORT – 服务器的端口(一个字符串)。
B、HttpResponse对象
对于HttpRequest对象来说,是由django自动创建的,但是,HttpResponse对象就必须我们自己创建。每个view请求处理方法必须返回一个HttpResponse对象。
在HttpResponse对象上扩展的常用方法:
页面渲染: render()(推荐)<br> render_to_response(), 页面跳转: redirect("路径") locals(): 可以直接将函数中所有的变量传给模板
实例:
-----------------------------------url.py url(r"login", views.login), url(r"yuan_back", views.yuan_back), -----------------------------------views.py def login(req): if req.method=="POST": if 1: # return redirect("/yuan_back/") name="yuanhao" return render(req,"my backend.html",locals()) return render(req,"login.html",locals()) def yuan_back(req): name="苑昊" return render(req,"my backend.html",locals()) -----------------------------------login.html <form action="/login/" method="post"> <p>姓名<input type="text" name="username"></p> <p>性别<input type="text" name="sex"></p> <p>邮箱<input type="text" name="email"></p> <p><input type="submit" value="submit"></p> </form> -----------------------------------my backend.html <h1>用户{{ name }}你好</h1>
总结: render和redirect的区别: 1 if render的页面需要模板语言渲染,需要的将数据库的数据加载到html,那么所有的这一部分 除了写在yuan_back的视图函数中,必须还要写在login中,代码重复,没有解耦. 2 the most important: url没有跳转到/yuan_back/,而是还在/login/,所以当刷新后 又得重新登录.