Django学习笔记——第三天
第三天
内容补充
前面讲到了如何直接对数据库的操作
# 命令行 python manage.py shell
from blog.models import BlogArtiles
blogs=BlogArticles.objects.all() #获取数据库中所有数据项
它的类型 django.db.models.query.QuerySet
,你可以通过for 循环,对其每一项数据进行操作,如:
for blog in blogs:
print(blog.title)
print(blog.body)
print(blog.author.username)
print(blog.publish)
没错,打印的都是 BlogArticles 中定义的字段。
然后我又看到了一种写法
blog=BlogArticles.objects.get(id=1)
#这个id就是文章编号,就好比上面的 for 循环,第一遍对应 id=1
#同理对应字段对应格式
blog.title
blog.body
。。。
然后在上面我们定义的 titles.html 中,就能通过这样实现点击相应的标题跳转到对应的文章了。
你应该会想到万一 id 超过文章数量怎么办吧?加一个404页面就好了。而 django 中正好有get_object_or_404()
方法。用法如下:
from django.shortcuts import get_object_or_404,render#没错,这家伙和render是一伙的
blog=get_object_or_404(BlogArticles,id)
OK,再次编写一个视图函数对应blog的跳转。
def article(request,a_id):#多一个参数,url该如何配置?
blog=get_object_or_404(BlogArticles,id=a_id)
publish_time=blog.publish_time#嗯,作者就是这样写的,虽然可以直接传一个参数过去.
return render(request,"blog/article.html",{'blog':blog,'publis':publish_time})
按上次的思路,接下来便是 url 匹配,template 编写。我前端不行,这块代码直接在文末贴出来吧,以后都如此。
像我上面代码中注释的,该如何匹配?首先明确,希望 url 类似 ./blog/1/
。
直接说吧,(?P匹配形式)这里的 name 对应着视图函数中参数名,如(?P\d>) 用来匹配参数 id, a_id 在 def article(request,a_id)
这。
所以如下添加 url 路径
urlpatterns=[
url(r'^$',views.blog_title,name='blog_title'),
url(r'(?P<a_id>\d+)/$',views.article,name='blog_detail')
]
注意,传进的参数都是字符串,都是字符串。
(?Pregx):正则会匹配到括号括起的内容(regx要匹配的)作为参数传给视图函数,而 name 则指明是哪个参数。
返回 Response 写法
- 最原始的导入
HttpResponse
和Http404
,类似:
from django.http import HttpResponse,Http404
from django.template import loder#用于数据项加载 template
from .models import BlogArticles
def Func(request,id):
try:
blog=BlogArticles.objects.get(id=id)
except BlogArticles.DoesNotExist:
raise Http404("文章不存在。。。")
template=loder.get_template(模板文件)
data={'blog':blog,'publish':blog.publish_time}
return HttpResponse(template.render(data,request))
- 整个一个加载模板并传递参数的流程,挺繁琐的。那就用简单点的吧,像前几次文章中的,引入
render
和get_object_or_404
,我就不写了,你往前翻翻吧。
总结
对于 URL 设计思考
- 建议分多级路由进行 url 匹配,也便于管理
- include()的使用
1, 明确URLConf机制先从项目根 urls 即 mysite.urls 开始匹配urlpatterns
2, url(regx,include(‘app.urls’,namespace,app_name))
3, include还有一种用法,比如 /blog/python/,/blog/c++/,/blog/java/等类似前缀相同的情况下,可以定义一个 mypatterns,如下。
- include()的使用
mypatterns=[
url(r'^python/',视图),
url(r'^python/',视图),
...
]
urlpatterns=[
url(r'^blog/',include(mypatterns))
]
- url 中含有需要传入参数的情况
-
(?P<name> regxpattern)
的使用(可以有多个)。 - 从上一级 URLconf 匹配到的参数依旧会传到下一级(就是最终函数都能收到)。
-
- 视图中需要的参数不在url中时
- 通过
url(regx,view,data)
,额外的参数data允许以字典形式传入 - 如上形式也能传递给
include()
,但会传给include包含的每一个 urlconf的视图函数。如果某个视图不需要改参数,反而会报错。 - 避免data中参数名与url中匹配的参数名重名冲突。
- 通过
URL反解
为了解决这个问题,Django提供了一种解决方案,只需在URL中提供一个name参数,并赋值一个你自定义的、好记的、直观的字符串。
通过这个name参数,可以反向解析URL、反向URL匹配、反向URL查询或者简单的URL反查。
在需要解析URL的地方,对于不同层级,Django提供了不同的工具用于URL反查:在模板语言中:使用 url 模板标签。(也就是写前端网页时)
在Python代码中:使用 reverse() 函数。(也就是写视图函数等情况时)
在更高层的与处理Django模型实例相关的代码中:使用 get_absolute_url() 方法。(也就是在模型model中)
先说模板标签的吧,按我的理解分两种:
定义了别名 name,如{%url ‘别名’ 参数%}
<a href="{% url 'blog_detail' 2%}">
对应url(r'(?P<a_id>\d+)/$',views.article,name='blog_detail')
定义了命名空间 namespace 和别名 name,{%url ‘namespace:name’ 参数%}。为了区别同 name 而不同 namespace的匹配,namespace 可换成 app_name。
#可以在urls.py中定义
app_name=blog
#模板中
{%for blog in blogs%}
<li><a target="_blank" href="{%url 'blog:blog_detail' blog.id%}">{{blog.title}}</a></li>
{%endfor%}
#仍旧对应 url(r'(?P<a_id>\d+)/$',views.article,name='blog_detail')
注意模板中没有什么字符串方法之类的,这里 blog.id 可以直接写在字符串中
而 reverse()用法如下
####urls
from django.conf.urls import url,include
from app1 import views
urlpatterns = [
url(r'^art/', views.art3, name='blog'),
]
####views
def art3(request):
print(reverse('blog')) #在视图函数中对url进行反向解析
return HttpResponse("OK")
5.18补充
模板 titles.html
对应在 blog/templates/blog/titles.html
{%extends "base.html"%}
{%block title%}blog title{%endblock%}
{%block content%}
<div class="row text-center vertical-middle-sm"> <h1>My Blog</h1>
</div>
<div class="row">
<div class="col-xs-12 col-md-8">
<ul>
{%for blog in blogs%}
<li><a target="_blank" href="{%url 'blog:blog_detail' blog.id%}">{{blog.title}}</a></li>
{%endfor%}
</ul>
</div>
<div class="col-xs-6 col-md-4">
<h2>广告</h2>
<p>baiduyixia:www.baidu.com</p>
<img src="https://tse4.mm.bing.net/th?id=OIP.9zkKGHtU0FkbjYXV7DL4bQHaFE&pid=Api" width="200px">
</div>
</div>
{%endblock%}
articles.html
对应在 blog/templates/blog/article.html
{% extends "base.html" %}
{%block title%}blog article{%endblock%}
{%block content%}
<div class="row text-center vertical-middle-sm">
<h1>{{blog}}</h1>
</div>
<div class="row">
<div class="col-xs-12 col-md-3">
<h3>作者简介</h3>
<p>JosonLee</p>
<p>Python、大数据学习中。。。</p>
<img src="https://s1.ax1x.com/2018/05/18/C6Tw9I.png" alt="C6Tw9I.png" width="200px" height="150px" border="0" />
</div>
<div class="col-xs-9 col-md-7">
<p class="text-center"><span>{{blog.author.username}}</span><span style="margin-left: 20px">{{publish}}</span></p>
<div>{{blog.body}}</div>
</div>
<div class="col-xs-2 col-md-2">
<h2>广告</h2>
<p><a target="_blank" href="https://www.baidu.com">百度一下:</a><a target="_blank" href="https://blog.csdn.net/lzw2016"><span>lzw2016</span></a> </p>
<img src="https://tse4.mm.bing.net/th?id=OIP.9zkKGHtU0FkbjYXV7DL4bQHaFE&pid=Api" width="200px">
</div>
</div>
{%endblock%}
差不多一个博客基本框架搭建出来了,运行一下项目,你能看到如下图所示页面:
到现在为止,Django 基本的 MTV 模型大体上掌握了,下一阶段继续深入学习、掌握每个模块的用法吧。