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 写法

  • 最原始的导入 HttpResponseHttp404,类似:
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))
  • 整个一个加载模板并传递参数的流程,挺繁琐的。那就用简单点的吧,像前几次文章中的,引入renderget_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,如下。
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中)

出自 http://www.liujiangblog.com/course/django/136

先说模板标签的吧,按我的理解分两种:

  • 定义了别名 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 模型大体上掌握了,下一阶段继续深入学习、掌握每个模块的用法吧。

posted @ 2018-05-16 20:58  不知道的痛  阅读(309)  评论(0编辑  收藏  举报