博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Django 模板与表单
阅读量:4230 次
发布时间:2019-05-26

本文共 8588 字,大约阅读时间需要 28 分钟。

加载python shell

• 使用如下命令来调用Python shell:

(django_env) [root@localhost mysite]# python manage.py shell

• 使用上述命令而不是简单地键入“python”进入python环境

• 因为manage.py 设置了 DJANGO_SETTINGS_MODULE 环境变量,该环境变量告诉Django导入mysite/settings.py文件的路径

 

 

导入模型

• 导入前面编写的模型

>>> from polls.models import Question, Choice

• 查看所有的问题

>>> Question.objects.all()

<QuerySet []>

• 因为还没有创建任何问题,所以返回的是一个空查询集

 

创建Question

• Question模型中需要时间,可以使用django工具

>>> from django.utils import timezone

• 创建问题

>>> q = Question(question_text="你希望进入哪个公司工作?", pub_date=timezone.now())

>>> q.save()

• 保存这个对象到数据库中。 必须显示地调用save()

 

访问Question模型

• 一旦创建好了对象,就可以对其进行访问了

>>> q.id

1

>>> q.question_text

'你希望进入哪个公司工作?'

>>> q.pub_date

datetime.datetime(2018, 5, 18, 14, 50, 11, 282269, tzinfo=<UTC>)

 

修改Question对象

• 通过改变属性来改变字段的值,然后调用save()

>>> q.question_text = "你期待哪个公司给你发offer?"

>>> q.save()

• 查询结果

>>> Question.objects.all()

<QuerySet [<Question: Question object>]>

 

 

提供友好实例名称

 

• <Question object> 完全是这个对象无意义的表示。

接下来修复这个问题:修改polls/models.py

from django.db import models

class Question(models.Model):

        question_text = models.CharField(max_length=200)
        pub_date = models.DateTimeField('date published')
        def __str__(self):
                return self.question_text
class Choice(models.Model):
        question = models.ForeignKey(Question, on_delete=models.CASCADE)
        choice_text = models.CharField(max_length=200)
        votes = models.IntegerField(default=0)
        def __str__(self):
                return self.choice_text

 

• 修改完毕,重新加载

(django_env) [root@localhost mysite]# python manage.py shell

>>> from polls.models import Question, Choice

>>> Question.objects.all()

<QuerySet [<Question: 你期待哪个公司给你发offer?>]>

 

自定义方法

• 模型虽然与数据库具有映射关系,但是它也可以像普通的类一样进行方法的创建

import datetime

from django.db import models
from django.utils import timezone
class Question(models.Model):
        question_text = models.CharField(max_length=200)
        pub_date = models.DateTimeField('date published')
        def __str__(self):
                return self.question_text
        def was_published_recently(self):
                return self.pub_date >= timezone.now() - datetime.timedelta(days=1)

class Choice(models.Model):

        question = models.ForeignKey(Question,on_delete=models.CASCADE)
        choice_text = models.CharField(max_length=200)
        votes = models.IntegerField(default=0)
        def __str__(self):
                return self.choice_text
# polls/models.py ,前面的空格要符合语法格式,可使用tab键

 

数据库查询

• Django 提供了丰富的数据库查询 API

• 通过关键字查询

• 如果ID不存在,将引发一个异常

>>> from polls.models import Question, Choice

>>> Question.objects.get(id=1)

<Question: 你期待哪个公司给你发offer?>

>>> Question.objects.get(id=2)

……

polls.models.DoesNotExist: Question matching query does not exist.

 

• 通过主键查询数据是常见的情况,因此 Django 提供了精确查找主键的快捷方式

• 使用自定义方法

>>> Question.objects.get(pk=1)

<Question: 你期待哪个公司给你发offer?>

>>> q = Question.objects.get(pk=1)

>>> q.was_published_recently()

True

 

• Django通过灵活的双下划线实现属性查找

>>> Question.objects.filter(id=1)

<QuerySet [<Question: 你期待哪个公司给你发offer?>]>

>>> Question.objects.filter(question_text__startswith='你')

<QuerySet [<Question: 你期待哪个公司给你发offer?>]>

>>> from django.utils import timezone

>>> current_year = timezone.now().year

>>> Question.objects.get(pub_date__year=current_year)

<Question: 你期待哪个公司给你发offer?>

 

 

创建Choice对象

• 由于存在外键关系,django通过Question对象可以反向得到Choice对象集

>>> q.choice_set.all()

<QuerySet []>

>>> q.choice_set.create(choice_text='阿里巴巴', votes=0)

<Choice: 阿里巴巴>

>>> q.choice_set.create(choice_text='华为', votes=0)

<Choice: 华为>

>>> c = q.choice_set.create(choice_text='菜鸟', votes=0)

>>> c.question

<Question: 你期待哪个公司给你发offer?>

>>> q.choice_set.all()

<QuerySet [<Choice: 阿里巴巴>, <Choice: 华为>, <Choice: 菜鸟>]>

>>> q.choice_set.count()

3

 

 

 

视图

 

• 在Django中,网页的页面和其他内容都是由视图来传递的(视图对WEB请求进行回应)

• 每个视图都是由一个简单的Python函数(或者是基于类的视图的方法)表示的

• Django通过检查请求的URL(准确地说,是URL里域名之后的那部分)来选择使用哪个视图

 

Question详情视图

• 编写一个视图,显示单个Question的具体内容,不显示该议题的当前投票结果,而是提供一个投票的表单

# polls/views.py

def detail(request, question_id):

    return HttpResponse("你正在查看的问题是:%s。" % question_id)

 

 

Question结果视图

• 编写视图,显示特定的Question的投票结果

def result(request, question_id):

    response = "你正在查看问题[%s]的结果。"

    return HttpResponse(response % question_id)

 

投票功能视图

• 编写视图,处理对Question中Choice的投票

def vote(request, question_id):

    return HttpResponse("您正在为[%s]投票。")

 

编写URLCONF

• 将视图和polls.urls模块关联

• 当客户端向你的网站请求一个页面 ( 例如 “/polls/34/”)时,Django将加载mysite.urls  Python模块

• 因为它被指向ROOT_URLCONF设置, 它寻找名为 urlpatterns 的变量并按顺序匹配其中的正则表达式

• 在‘^polls/’找到匹配后,它将取消匹配的文本 (“polls/”),并发送剩余的文本 ( “34/” )到'polls.urls'URLconf进行进一步处理

 

• 编辑polls/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.result, name='result'),
        url(r'^(?P<question_id>[0-9]+)/vote/$', views.vote, name='vote'),
]

 

模板

概述

前面的例子,HTML是硬编码在python代码中的。

这会带来不少问题:

– 任何页面的改动会牵扯到Python代码的改动

– 写后台Python代码与设计HTML是不同的工作,更专业的Web开发应该将两者分开

– 程序员写Python代码同时页面设计者写HTML模板会更高效,而不是一个人等待另一个人编辑同样的文件

 

为了解决硬码的这些问题,可以模板:

– 网站的设计改动会比Python代码改动更频繁,所以如果我们将两者分离开会更方便

– 页面设计者和HTML/CSS程序员不应该编辑Python代码,他们应该与HTML打交道

– 使用Django的模板系统分离设计和Python代码会更干净更易维护

 

创建模板工作目录

• 默认的设置文件settings.py配置了一个DjangoTemplates后端,其中将APP_DIRS选项设置为True

• DjangoTemplates在 INSTALLED_APPS所包含的每个应用的目录下查找名为"templates"子目录

• 模板应该位于polls/templates/polls/目录下

[root@localhost mysite]# mkdir -p polls/templates/polls

 

 

更新index视图

• 修改polls/views.py的index函数

from django.shortcuts import render

from . models import Question
def index(requrest):
        latest_question_list = Question.objects.order_by('-pub_date')[:5]
        context = {'latest_question_list': latest_question_list}
        return render(request, 'polls/index.html', context)
 

 

编写模板

• 创建模板文件polls/templates/polls/index.html,模板语言后续有详细介绍 {具体啥时候俺也不知道 T_T}

{% if latest_question_list %}

<ul>

{% for question in latest_question_list %}

<li><a

href="/polls/{

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

{% endfor %}

</ul>

{% else %}

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

{% endif %}

 

当模板系统遇到变量名里有小数点时会按以下顺序查找:

– 字典查找,如foo["bar"]

– 属性查找,如foo.bar

– 方法调用,如foo.bar()

– 列表的索引查找,如foo[bar]

 

模板中可以使用的元素有:

– 变量,使用 {

{ variable }} 的格式

– 标签/指令,使用 {% ... %}的格式

– 字符串:{ } 之外的任何东西,都当做字符串处理

 

错误处理

• 当请求一个不存在的对象时,django将会抛出异常

例如访问 127.0.0.1:8000/polls/2/

 

 

• 一种常见的习惯是使用get()并在对象不存在时引发 Http404。 Django为此提供一个快捷方式

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, 'polls/detail.html', {'question': question})

 

 

编写投票详情模板

• 创建polls/templates/polls/detail.html

<h1>{

{ question.question_text }}</h1>

<ul>

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

<li>{

{ choice.choice_text }}</li>

{% endfor %}

</ul>

 

• 没有发生异常时的页面

127.0.0.1:8000/polls/1/

 

• 异常发生时的页面

127.0.0.1:8000/polls/2/

 

 

detail表单

表单说明

• 在detail网页模板中,我们为Question对应的每个Choice都添加了一个单选按钮用于选择。 每个单选按钮的value属性是对应的各个Choice的ID。

• 每个单选按钮的name是“choice”。 这意味着,当选择一个单选按钮并提交表单提交时,它将发送一个POST数据choice=#,其中#为选择的Choice的ID

 

 

编写表单

• 更新投票详细页面的模板detail.html

<h1>{

{ question.question_text }}</h1>

{% if error_message %}<p><strong>{

{ error_message }}</strong></p>{%

endif %}

<form action="/polls/{

{ question.id }}/vote/" method="post">

{% csrf_token %}

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

<input type="radio" name="choice" id="choice{

{ forloop.counter }}"

value="{

{ choice.id }}" />

<label

for="choice{

{ forloop.counter }}">{
{ choice.choice_text }}</label><br />

{% endfor %}

<input type="submit" value="投票" />

</form>

 

 

• forloop.counter指示for标签已经循环多少次

• 由于我们创建一个POST表单(它具有修改数据的作用),所以我们需要小心跨站点请求伪造

• Django已经拥有一个用来防御它的非常容易使用的系统

• 简而言之,所有针对内部URL的POST表单都应该使用{% csrf_token %}模板标签

 

 

 

vote视图

• 修改vote函数,使之可以真正投票

def vote(request, question_id):

question = get_object_or_404(Question, pk=question_id)

try:

choices = question.choice_set.get(pk=request.POST['choice'])

except(KeyError, Choice.DoesNotExist):

return render(request, 'polls/detail.html', {

'qustion': question,

'error_message': '您没有做出任何选择',

})

else:

choices.votes += 1

choices.save()

return redirect('result', question_id=question_id)

 

• request.POST 是一个类似字典的对象,可以通过关键字的名字获取提交的数据

• request.POST['choice'] 以字符串形式返回选择的Choice的ID。request.POST 的值永远是字符串

• 如果在POST数据中没有提供request.POST['choice'],choice将引发一个KeyError

 

修改result视图函数

• 修改vote函数,使之可以真正投票

def result(request, question_id):

question = get_object_or_404(Question, pk=question_id)

return render(request, 'polls/results.html', {'question': question})

 

 

创建results模板文件

• 创建polls/templates/polls/results.html模板文件

<h1>{

{ question.question_text }}</h1>

<ul>

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

<li>{

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

{% endfor %}

</ul>

<a href="/polls/">投票首页</a>

-------------------------------------------------------------------------------------------------------------

看完该篇文是不是都学会了呀,布置一个完成投票系统的任务给大家!要求如下:

  1. 为投票应用增加表单,使用户可以完成投票操作
  2. 修改投票的视图函数
  3. 修改模板文件
  4. 使投票应用成为真正可用的程序

转载地址:http://ghiqi.baihongyu.com/

你可能感兴趣的文章
探索一家神秘的公司
查看>>
PDF转Word完全免费?这么好的事情我怎么不知道????
查看>>
数据解读---B站火过蔡徐坤的“鬼畜“区巨头们
查看>>
Squid代理服务器搭建亿级爬虫IP代理池
查看>>
JupyterNotebook‘s Magic
查看>>
在Linux 上部署Jenkins和项目
查看>>
Python+requests+unittest+excel实现接口自动化测试框架
查看>>
那些年我们听过的互联网公司的套路?
查看>>
谈谈python里面那些高级函数
查看>>
40行代码带你免费看《海贼王-和之国》篇章
查看>>
搭建炫酷的服务器监控平台
查看>>
垃圾分类:人机搭配,干活不累
查看>>
Nginx
查看>>
Memcached,session共享
查看>>
Tomcat,varnish
查看>>
SVN, 制作RPM包
查看>>
HTML 标签说明
查看>>
CSS 基本语法
查看>>
10.shell基础
查看>>
为人处世小技巧
查看>>