Django 中URL和Views相关知识梳理(极简版)
提示:仅供梳理参考,很多相关的细节内容忽略。
1.URL
(1)URL匹配的规则是正则,关于正则不再赘述。
(2)URL优先级顺序:从urlpatterns的底部开始搜索,一直往上搜索,需要注意的是,并不是一搜到匹配的URL正则式就停止了,而是继续往上搜索,如果上面还有匹配的URL正则,则上面的有效,所以在urlpatterns中写url与views或者include的映射关系时,应该是细分的在上面,比较粗略的正则写下面,但如果采用'^ some RegEx$' 的精确的正则,就不存在优先级的问题。
(3)url带参:通过正则name group实现,比如'^fruit/(?P<fruit_name>[a-zA-Z]+)/',可以获取一个名为'fruit_name'的参数,该参数至少有一个字母,然后传递给相应的view函数,如:
1 2 3 4 | def someMethod(request,fruit_name,extra): #extra 解释见下面的(4) #something using fruit_name return render(request, 'demo.html' ,context_dict) |
该函数可以是FVB或者CVB,如果是CVB可直接传递至相应的template模板,如url('^someRegEx$',TemplateView.as_view(template_name='drinks/index.html'))
(4)url的optional extra:例如 url('^someRegEx$',views.someMethod,{'extra':'extra_data'}),最后一项就是optional extra,可选的参数,该参数随url中的参数一起,可以被传入views 中的函数或者CVB指明的模板。
(5)url的name:在映射url和view函数时候,经常带一个name,如 url('^apple/'这个url,因为如果^apple/'都要变,非常麻烦。
(6)如果是多个app,则每个app下的name不能一样,因为这样就是多个url对应一个name,反向代理,一个name对应哪个url?不确定。一个粗暴的方法就是每个name都加后缀,但也非常不方便。所以为了可以让每个app下的name 也可以相同,引入了namespace,但namespace必须与include一起使用,所以在reverse或者模板中就可以用“namespace:name"的方法来反向代理url。
(7)【用的情况比较少】如果多个url对应同一个app(必须用多个include+namespace,是使用app_name的前提),需要在该app的url中设置app_name,,这样可以通过app_name:name(该name是该app中urlpatterns中的name)来动态的捕捉到是通过哪个url进入的该app的url。如主urls.py中有
1 2 3 4 5 6 7 | <br>urlpatterns = [ path( 'admin/' , admin.site.urls), url( '^coffee-banners/' ,include( 'banners.urls' ,namespace = 'coffee-banners' )), url( '^food-banners/' ,include( 'banners.urls' ,namespace = 'food-banners' )) ] |
banners的urls.py为:
1 2 3 4 | app_name = 'banners_adverts' urlpatterns = [ url( '^$' ,views.index,name = 'index' ) ] |
banners的views.py:
1 2 | def index(request): return render(request, 'banners/index.html' ) |
banners的index.html为:
1 2 3 4 | { % extends '../base.html' % } { % block body_block % } { % url 'banners_adverts:index' % } { % endblock % } |
所以当通过/food-banners/进来时,{% url 'banners_adverts:index' %}显示的是/food-banners/如下图:
当通过/coffee-banners/进来时,{% url 'banners_adverts:index' %}显示的是/coffee-banners/如下图:
2.view
(1)view method request:是django.http.request.HttpRequest类的实例,在调用view method前,它包含了比如浏览器,Django的middleware类的一些信息。
(a)request.method(b)request.GET, request.POST(c)request.META(d)request.user。详见https://docs.djangoproject.com/en/3.1/ref/request-response/
(2)view method response:详见https://docs.djangoproject.com/en/3.1/ref/request-response/,三种生成view method response的方法,
(a)render(request,'demo.html',context_dict),该方法还有三个可选参数,'content_type',默认为'text/html',‘status'默认为200,'using',要么是'jinja2',要么'django'。(b)TemplateResponse(request,'demo.html',context_value),输入参数与render基本一样,多一个'charset'参数。
(c)
1 2 3 4 5 6 | from django.http import HttpResponse from django.template import loader,Context response = HttpResponse() t = loader.get_template( 'demo.html' ) c = Context(context_dict) response.write(t.render(c)) |
这是最灵活的一种方法,当视图方法的response需要高级选项时,这是一种推荐的方法。
(3)Response 的Status 和 Content-Type选项
(a) status:三位数,表示对给定的request回应的response的回应状态。比如,200是返回成功,404是未找到资源。
(b)Content-type: 是个'MIME(multipurpose Internet Mail Extensions)'的字符串类型,表面在response中的内容的类型,比如,’text/html',是一个标准的response的content type,'image/gif',表明返回的是一个GIF图像。
(c) buit-in response shortcuts and template for common HTTP Status: 404(Not Fount), 500(Internal Server Error), 400(Bad Request), and 403(Forbidden):
当django找不到页面,会自动触发404response,当django view 方法中抛出异常,会自动触发 500 response,但也可以显式地触发这些response,方法如下:
1 2 3 4 5 6 7 8 9 10 11 | Http status code python code sample 404 from django.http import Http404 raise Http404 500 raise Exception 400 from django.core.exceptions import SuspiciousOperation raise SuspiciousOperation 403 from django.core.exceptions import PermissionDenied raise PermissionDenied |
对于404 和500,它们还取决于 settings.py中的DEBUG的值。
也可以用定制的页面覆盖默认的这些错误代码对应的response页面。要创建一个定制的页面,必须建立个以错误代码命名的html文件,比如对于Http403错误,创建403.html放到TEMPLATES列表中的变量DIRS定义的路径下。(再一次注意,404.html和500.html仅在DEBUG=False时有效,因为为True的模式下,是要查找django项目内在的错误,所以提供了默认的带有Exception traceback 的错误页面,来方便调试,寻找错误) ,详见https://i.cnblogs.com/posts/edit-done;postId=13584840
(d)Buit-in response shortcuts for inline and streamed content
之前所有的response都建立在通过一个template来构建内容的基础上的,然而,还有很多情况,没有必要用template来输出response的内容,比如只需要一行输出'Nothing to see here",还有使用template来输出内容根本就不妥当的情况,比如redirect(Http301,Http302)
另外,比如一些response返回的是其他文本格式,如csv,详细的例子见https://docs.djangoproject.com/en/3.1/howto/outputting-csv/ , 或者pdf (from django.http import FileResponse , return FileResopnse(open('demo.pdf','rb'))).
例:该view 方法的response为下图:
1 2 3 4 5 6 7 | def index(request): response = HttpResponse(content_type = 'text/csv' ) response[ 'Content-Disposition' ] = 'attachment;filename=somefile.csv' writer = csv.writer(response) writer.writerow([ 'First row' , 'Foo' , 'Bar' ]) writer.writerow([ 'second row' , 'A' , 'B' , 'C' ]) return response |
(d)View method middleware
在大多数情况下,在request 和response中的数据都在view 方法中被添加,删除,更新,然而有时候需要对所有requests 和response进行一些操作,比如对所有response 进行强制性安全检查。这时候,用middleware就是个比较好的办法。
middleware 是request/response过程中的钩子框架,也就说,从发起request到返回response,request或response都要经历middleware,因此它可以轻松的改变Django 的输入输出,每个middleware 组件都负责一个特定的功能,比如AuthenticationMiddleware,它通过sessions将user和request联结了起来。
有关其机制的小demo见https://www.cnblogs.com/johnyang/p/13592340.html
(4)middleware flash messages:
使用条件:settings.py中MIDDLEWARE包含了django.contrib.messages.middleware.MessageMiddleware;INSTALLED_APPS有django.contrib.messages.value,在TEMPLATES的'OPTIONS'下有django.contrib.messages.context_processors.messages
(a)添加flash message
1 2 3 4 5 | from django.contrib import messages messages.add_message(request,message.DEBUG, 'the following sql statements were executed' ) #或者如下方式 messages.debug(request, 'The following sql statements were executed' ) |
需要注意的是,默认情况上面两个会被忽略,因为Django默认处理INFO层以上的信息,所谓层就是不同message对应的value,而DEBUG小于该值,所以默认被忽略,message-->value如下:
DEBUG-->10 (最低);INFO-->20;SUCCESS-->25;WARNING-->30;ERROR-->40(最高);
更改message level:
1 2 3 4 5 6 7 8 9 10 | #globally, settings.py from django.contrib.messages import constant as message_constants MESSAGE_LEVEL = message_constants.DEBUG #set default Djanog message level on a per request basis,in some method defined in views.py from django.contrib import messages def index(request): messages.set_level(request,messages.SUCCESS) messages.add_message(request,messages.INFO, 'it is info' ) return render(request, 'banners/index.html' ) |
(b)Access Flash messages
message的属性有'message': message中的实际文本;‘level':数字;’level_tag':字符代表,比如对于INFO,就是'info'。
可通过template来访问:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | { % extends '../base.html' % } { % block body_block % } <! - - { % url 'banners_adverts:index' % } - - > { % if messages % } <ul class = "messages" > { % for msg in messages % } <li> <div class = "alert alert-{{msg.level_tag}}" role = "alert" > {{msg.message}} < / div> < / li> { % endfor % } < / ul> { % endif % } { % endblock % } |
其中base.html是带有bootstrap的html,效果如下:
(5)CBV(class-based-views)
django.views.generic.View:所有其他CBV的父类,若创建一个继承该类的类,则可以自定义get(),post()方法来应对request的get和post方法。
django.views.generic.TemplateView:允许一个url,而不需要一个view方法,当然也可以通过在views.py中创建一个继承该类的类,然后设定类属性template_name,类方法get_context_data。
需要注意的是在urls.py中,都是需要CBV的as_view()方法
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix