当前位置: 首页 > news >正文

Django项目开发举例之用户界面视图模版(5)

1.创建视图

$ vi myapp/views.py 

#--------------------------------------------------------------------

from django.shortcuts import render

from django.http import HttpRespose


# Create your views here.


def index(request):

    return HttpResponse("Hello,word.You are in the myapp index. ")

#--------------------------------------------------------------------


2.创建应用URL

首先需要在myapp目录下创建urls.py文件,在文件中写入如下内容:

#--------------------------------------------------------------------

from django.conf.urls import url

from . import views

urlpatterns=[

    url(r'^$',views.index,name='index'),

]

#--------------------------------------------------------------------

url()函数具有四个参数:两个必需的regex和 view,以及两个可选的kwargsname

url()参数:regex

“regular expression(正则表达式)”的常用的一个缩写,是一种用来匹配字符串中模式的语法,在这里是URL模式。 Django从第一个正则表达式开始,依次将请求的URL与每个正则表达式进行匹配,直到找到匹配的那个为止。

请注意,这些正则表达式不会检索URL中GET和POST的参数以及域名。 例如,对于http://www.example.com/myapp/请求,URLconf 将查找myapp/对于http://www.example.com/myapp/?page=3请求,URLconf 也将查找myapp/

url()参数:view

当Django找到一个匹配的正则表达式时,它就会调用view参数指定的视图函数,并将HttpRequest对象作为第一个参数,从正则表达式中“捕获”的其他值作为其他参数,传入到该视图函数中。如果正则表达式使用简单的捕获方式,值将作为位置参数传递; 如果使用命名的捕获方式,值将作为关键字参数传递。

url()参数:kwargs

任何关键字参数都可以以字典形式传递给目标视图。 

url()参数:name

命名你的URL。 这样就可以在Django的其它地方尤其是模板中,通过名称来明确地引用这个URL。 这个强大的特性可以使你仅仅修改一个文件就可以改变全局的URL模式。


3.注册应用的URL到项目的URL中

$ vi testproject/urls.py

#--------------------------------------------------------------------

from django.conf.urls import include,url

from django.contrib import admin


urlpatterns = [

    url(r'^myapp/',include('myapp.urls')),

    url(r'^admin/', admin.site.urls),

]

#--------------------------------------------------------------------


这样在你的浏览器中浏览 http://127.0.0.1:8000/myapp/ , 你会看到 “Hello, world. You’re at the polls index.”


4.添加更多的视图

我们可以向views.py文件中增加以下代码:

#--------------------------------------------------------------------

def detail(request,quetion_id):

    return HttpResponse("you are looking at question %s."%question_id)


def results(request,question_id):

    response="you are looking at the result of question %s."

    return HttpResponse(response%question_id)


def vote(request,question_id):

    return HttpResponse("you are voting on question %s."%question_id)


#--------------------------------------------------------------------

然后向myapp/urls.py文件中增加以下代码:

#--------------------------------------------------------------------

from django.conf.urls import url

from . import views

urlpatterns=[

    url(r'^$',views.index,name='index'),

    url(r'^(?P<question_id>[0-9]+)/$',views.detail,name='detail'),

    url(r'^(?P<question_id>[0-9]+)/results/$',views.results,name='results'),

    url(r'^(?P<question_id>[0-9]+)/vote/$',views.results,name='vote'),

]

#--------------------------------------------------------------------

最后我们可以在浏览器中查看效果:

http://127.0.0.1:8000/myapp/34/

http://127.0.0.1:8000/myapp/34/results/

http://127.0.0.1:8000/myapp/34/vote/

工作原理是这样的:

当有人请求你的网站的一个页面时 —— 比如“/polls/34/”,Django将加载mysite.urls Python 模块,因为ROOT_URLCONF设置指定了它。它寻找名为urlpatterns 的变量并按顺序匹配其中的正则表达式。我们使用的include()函数来只是对其它URLconfs的简单引用。注意include()函数的正则表达式的末尾没有$(字符串结束符号)而是一个斜线。每当Django遇到include()时,它会截取与该点匹配的URL的前面部分,并将剩余的字符串发送到包含的URLconf以进行进一步处理。

我们来举例说明一下:

include()背后的想法是使URL变得即插即用。 因为投票应用拥有它自己的URLconf (myapp/urls.py),所以它可以被放在“/myapp/”路径下,或者“/fun_myapp/”路径下,或者“/content/myapp/”路径下,或者其他别的什么路径下,该应用仍然能够工作。

以下是如果一个使用者访问“/myapp/34/”,系统中将会发生的事:

  • Django发现匹配到了正则表达式'^myapp/'

  • 然后,Django将去掉匹配到的文本("myapp/")并将剩下的文本 —— "34/" —— 发送给‘polls.urls’ URLconf 做进一步处理,这时将匹配r'^(?P<question_id>[0-9]+)/$'并导致像下面这样调用detail()视图:

    detail(request=<HttpRequest object>, question_id='34')

question_id='34'部分来自(?P<question_id>[0-9]+)使用模式周围的括号“捕获”该模式匹配的文本,并将其作为参数发送到视图函数;?P<question_id> 定义一个名字,它将用于标识匹配的模式;[0-9]+是匹配一串数字的正则表达式。

因为URL模式是正则表达式,你如何使用它们没有什么限制。 不需要添加像.html这样繁琐的URL 

5.创建具有实际功能的视图

下面是一个新的index()视图,它显示系统中最新发布的5条questions记录,并用逗号分隔:

#--------------------------------------------------------------------

from django.shortcuts import render 

from django.http import HttpResponse

from .models import Question


# Create your views here.


def index(request):

    latest_question_list=Question.objects.order_by('pub_date')[:5]

    output=','.join([p.question_text for p in latest_question_list])

    return HttpResponse(output)

#--------------------------------------------------------------------

这里有一个问题:页面的设计被硬编码在视图中。 如果你想更改页面的外观,就得编辑这段Python代码。 因此,让我们使用Django的模板系统,通过创建一个视图能够调用的模板,将页面的设计从Python中分离出来。方法如下:

首先,在你的myapp目录下创建一个叫做 templates的目录。Django将在这里查找模板

你项目的TEMPLATES设置描述了Django将如何加载并渲染模板。默认的设置文件settings.py配置了一个DjangoTemplates后端,其中将APP_DIRS选项设置为True按照惯例,DjangoTemplates在 INSTALLED_APPS所包含的每个应用的目录下查找名为"templates"子目录。因此即使我们不去修改DIRS,Django也可以找到应用的模版。

在你刚刚创建的templates目录中,创建另外一个目录my app,并在其中创建一个文件index.html换句话讲,你的模板应该位于 myapp/templates/myapp/index.html由于app_directories 模板加载器按照上面描述的方式工作,在Django中你可以简单地用myapp/index.html引用这个模板。

我们可以直接将我们的模板放在polls/templates中(而不用创建另外一个polls子目录),但实际上这是个坏主意。Django将选择它找到的名字匹配的第一个模板文件,如果你在不同 的应用有相同名字的模板文件,Django将不能区分它们。我们需要将Django指向正确的模板,最简单的方式是使用命名空间。具体实现方式是,将这些模板文件放在以应用的名字来命名的另一个目录下。

现在我们将模版文件index.html放在myapp/templates/myapp/目录下,并向文件中加入我们想要的应用设计:

$ vi index.html

#--------------------------------------------------------------------

{% if latest_question_list %}

    <ul>

    {% for question in latest_question_list %}

        <li><a href="/myapp/{{ question.id }}/">{{ question.question_text }}</a></li>

    {% endfor %}

    </ul>

{% else %}

    <p>No myapp are available.</p>

{% endif %}

#--------------------------------------------------------------------

既然我们定义好了应用的模板现在我们来改写views.py文件将视图与设计进行分离:

#--------------------------------------------------------------------

from django.shortcuts import render 

from django.http import HttpResponse

from django.template import RequestContext, loader

from .models import Question


# Create your views here.


def index(request):

    latest_question_list=Question.objects.order_by('pub_date')[:5]

#   output=','.join([p.question_text for p in latest_question_list])

    template=loader.get_template('myapp/index.html')

    context=RequestContext(request,{

        'latest_question_list':latest_question_list,

    })

#   return HttpResponse(output)

    return HttpResponse(template.render(context))


#--------------------------------------------------------------------

我们可以输入网址:http://127.0.0.1:8000/myapp/看一看效果

进一步我们可以调用render来简化views.py中的代码

一般写代码的思路是载入一个模板、填充一个context 然后返回一个含有模板渲染结果的HttpResponse对象。现在我们可以利用render()函数来实现这个流程。重写views.py中index的定义:

#--------------------------------------------------------------------

from django.shourtcuts import render


def index(request):

    latest_question_list=Question.objects.order_by('-pub_date')[:5]

    context={'latest_question_list':latest_question_list}

    return render(request,'myapp/index.html',context)


#--------------------------------------------------------------------

注意,一旦我们在所有的视图上都应用这个快捷函数,我们将不再需要导入 loaderRequestContextHttpResponse 

render()函数将请求对象作为它的第一个参数,模板的名字作为它的第二个参数,一个字典作为它可选的第三个参数。 它返回一个HttpResponse对象,含有用给定的context 渲染后的模板。

6.增加异常处理

    我们增加一个异常处理:如果没有找到所请求ID的Question,这个视图引发一个Http404异常。另外我们也来为detail视图增加一个自定义模版

我们在myapp/templates目录下创建一个detail.html文件,为了可以看到运行效果,文件内容简单如下:

#--------------------------------------------------------------------

{{question}}

#--------------------------------------------------------------------

接下来我们来重写views.py文件中的detail视图增加异常处理:

#--------------------------------------------------------------------

from django.http import Http404


def detail(request,question_id):

    try:

        question=Question.objects.get(pk=question_id)

    except Question.DoesNotExist:

        raise Http404("Question does not exist")

    return render(request,'myapp/detail.html',{'question':question})


#--------------------------------------------------------------------


对于异常处理思路是使用get()并在对象不存在时引发Http404。我们可以利用Django为此提供一个快捷方式get_object_or_404() 来实现这个过程,下面我们就重写一下detail视图:

#--------------------------------------------------------------------

from django.shortcuts import render,get_object_or_404


def detail(request,question_id):

    question=get_object_or_404(Question,pk=question_id)

    return render(request,'myapp/detail.html',{'question':question})

#--------------------------------------------------------------------

get_object_or_404() 函数将一个Django模型作为它的第一个参数,任意数量的关键字参数作为它的第二个参数,它会将这些关键字参数传递给模型管理器中的get() 函数。如果对象不存在,它就引发一个 Http404异常。

为什么我们要使用一个辅助函数get_object_or_404()而不是在更高层自动捕获ObjectDoesNotExist异常,或者让模型的API 引发 Http404而不是ObjectDoesNotExist

因为那样做将会使模型层与视图层耦合在一起。 Django最重要的一个设计目标就是保持松耦合。

还有一个get_list_or_404()函数,它的工作方式类似get_object_or_404()  —— 差别在于它使用filter()而不是get()如果列表为空则引发Http404


我们来自定义一下detail视图的模版:

#--------------------------------------------------------------------

<h1>{{ question.question_text }}</h1>

<ul>

{% for choice in question.choice_set.all %}

    <li>{{ choice.choice_text }}</li>

{% endfor %}

</ul>

#--------------------------------------------------------------------

模板系统使用点号查找语法来访问变量的属性。 {{ question.question_text }}这个例子中,Django首先在question对象上做字典查询。如果失败,Django会接着尝试属性查询 —— 在这个例子中,属性查询会成功。如果属性查询也失败,Django将尝试列表索引查询。

方法调用发生在{% for %}循环中:question.choice_set.all被解释为Python的代码question.choice_set.all(),它返回一个由Choice对象组成的可迭代对象,并将其用于{% for %}标签。

7.移除URL中的硬编码

首先我们看一下myapp/templates/index.html文件中的代码

#------------------------------------------------------------------------------------

<li><a href="/myapp/{{ question.id }}/">{{ question.question_text }}</a></li>

#------------------------------------------------------------------------------------

模板中编写一个指向Question的链接,这种硬编码、紧耦合的方法有一个问题,就是如果我们想在拥有许多模板文件的项目中修改URLs,那将会变得很有挑战性。 然而,因为你在polls.urls模块的url()函数中定义了name 参数,你可以通过使用{% url %}模板标签来移除对你的URL配置中定义的特定的URL的依赖:

#-------------------------------------------------------------------------------------

<li><a href="{% url 'detail' question.id %}">{{ question.question_text }}</a></li>

#-------------------------------------------------------------------------------------

它的工作原理是:

首先HTML文件在polls.urls模块里查找指定的URL的定义。你可以看到名为‘detail’的URL的准确定义:

url(r'^(?P<question_id>[0-9]+)/$',views.detail,name='detail'),

如果你想把polls应用中detail视图的URL改成其它样子比如 myapp/specifics/12/,就可以不必在该模板(或者多个模板)中修改它,只需要修改 myapp/urls.py为

url(r'^specifics/(?P<question_id>[0-9]+)/$',views.detail,name='detail'),

就可以了。

8.使用命名空间区分应用间的URL

在真实的Django项目中,可能会有五个、十个、二十个或者更多的应用。 Django如何区分它们URL的名字呢? 例如,polls 应用具有一个detail 视图,相同项目中的博客应用可能也有这样一个视图。当使用模板标签{% url %}时,人们该如何做才能使得Django知道为一个URL创建哪个应用的视图?

答案是在你的主URLconf下添加命名空间。 在testproject/urls.py文件中,添加命名空间将它修改成:

#-------------------------------------------------------------------------------------

urlpatterns = [

    url(r'^myapp/',include('myapp.urls',namespace="myapp")),

    url(r'^admin/', admin.site.urls),

]

#-------------------------------------------------------------------------------------

另外我们还需要修改myapp应用的模板文件myapp/index.html指向具有命名空间的详细视图:

$ vi templates/myapp/index.html 

#-------------------------------------------------------------------------------------

<li><a href="{% url 'myapp:detail' question.id %}">{{ question.question_text }}</a></li>

#-------------------------------------------------------------------------------------




















相关文章:

  • Django项目开发举例之用户界面表单(6)
  • Django中Meta类详解
  • No python interpreter configured for the project
  • Django中各文件常用参数详解
  • Django-xadmin的使用
  • Linux定时任务Crontab命令详解
  • Oracle随机抽取数据
  • ORACLE输出结果到文件
  • 解决sqlplus中输错命令时的删除、光标键不能使用问题
  • BETWEEN AND的边界值问题
  • ORACLE数据库已知当前日期求上月5号和当月5号
  • ORACLE定时任务举例
  • Oracle sqlplus 常用格式化输出命令
  • SAS sid码安装点不匹配
  • Oracle 实用案例1:DECODE行转列
  • 「前端早读君006」移动开发必备:那些玩转H5的小技巧
  • 【划重点】MySQL技术内幕:InnoDB存储引擎
  • docker-consul
  • FastReport在线报表设计器工作原理
  • LeetCode18.四数之和 JavaScript
  • log4j2输出到kafka
  • SpingCloudBus整合RabbitMQ
  • 大主子表关联的性能优化方法
  • 浅谈Kotlin实战篇之自定义View图片圆角简单应用(一)
  • 数组大概知多少
  • Spring Batch JSON 支持
  • 阿里云API、SDK和CLI应用实践方案
  • 好程序员大数据教程Hadoop全分布安装(非HA)
  • ​LeetCode解法汇总1410. HTML 实体解析器
  • ​无人机石油管道巡检方案新亮点:灵活准确又高效
  • ​中南建设2022年半年报“韧”字当头,经营性现金流持续为正​
  • #前后端分离# 头条发布系统
  • #我与Java虚拟机的故事#连载08:书读百遍其义自见
  • $().each和$.each的区别
  • $.ajax()方法详解
  • (3)nginx 配置(nginx.conf)
  • (Redis使用系列) SpringBoot中Redis的RedisConfig 二
  • (第一天)包装对象、作用域、创建对象
  • (附源码)流浪动物保护平台的设计与实现 毕业设计 161154
  • (七)c52学习之旅-中断
  • (学习日记)2024.04.04:UCOSIII第三十二节:计数信号量实验
  • (转)AS3正则:元子符,元序列,标志,数量表达符
  • .NET Framework与.NET Framework SDK有什么不同?
  • .net 开发怎么实现前后端分离_前后端分离:分离式开发和一体式发布
  • .NET/C# 阻止屏幕关闭,阻止系统进入睡眠状态
  • .Net高阶异常处理第二篇~~ dump进阶之MiniDumpWriter
  • .Net各种迷惑命名解释
  • .net快速开发框架源码分享
  • /*在DataTable中更新、删除数据*/
  • @value 静态变量_Python彻底搞懂:变量、对象、赋值、引用、拷贝
  • [ 云计算 | AWS ] 对比分析:Amazon SNS 与 SQS 消息服务的异同与选择
  • [Asp.net mvc]国际化
  • [C# 网络编程系列]专题六:UDP编程
  • [C++] sqlite3_get_table 的使用
  • [CSS]CSS 字体属性