看了刘江老师教程这么多天,卧槽,我才发现他也曾跻身于行伍之间,interesting

刘老师这波讲解很到位,告诉你如何编写单例视图的时候忽然告诉你,其实不用这么麻烦,我们有通用视图,那些总是要做相似的行为的视图,咱们就写一个好了,解放生产力不就是进步吗?

好的废话不说进入正题,先修改一波detail.html模板

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>detail</title>
</head>
<body>
<h1>{{ question.question_text }}</h1>
{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}
<form action="{% url 'polls:vote' question.id %}" 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="Vote">
</form>
</body>
</html>

解读一些这个html,

h1是一级标题,里面用了传入的question对象的question_text属性,在本实例之中得到的就是问题的名字

接下来用了判断,这里看就是关于报错信息的,如果有,则会出现一句加粗的提示,内容就是。。。报错信息

接下来是一个文本框,radio类型是单选按钮,label里面for属性表示的是关联哪个表单,这里我们看到input文本框的id和for的值是相同的,也就是为label和此处的input做了绑定,于是你就get到了此处显示的信息为:

问题名

选项1

选项2

按钮VOTE

回顾一下我们已有的有灵魂和躯体的家伙们(有views中定义且有对应路由渲染模板)index、detail、results

那么这个vote呢?vote这里它就是个灵魂,就是个贾维斯,我们不需要它有一个躯壳它就可以完成使命!也就是说它做逻辑业务

现在对views.py中的vote功能进行改写

def vote(request, question_id):
question = get_object_or_404(Question, pk=question_id)
try:
selected_choice = question.choice_set.get(pk=request.POST['choice'])
except (KeyError, Choice.DoesNotExist):
return render(request, 'polls/detail.html', {
'question': question,
'error_message': "You didn't select a choice.",
})
else:
selected_choice.votes += 1
selected_choice.save()
return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))

那么results就需要模板,在polls/templates/polls/下创建新的html文件results.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>{{ question.question_text }}</h1> <ul>
{% for choice in question.choice_set.all %}
<li>{{ choice.choice_text }} -- {{ choice.votes }} vote{{ choice.votes|pluralize }}</li>
{% endfor %}
</ul> <a href="{% url 'polls:detail' question.id %}">Vote again?</a>
</body>
</html>

注意这里返回的对象不再是HttpResponse对象而是进行了重定向,跳转到结果页面

当我们在detail提交表单就会跳转执行vote函数,紧接着vote通过判断被传入的id对数据库进行操作即votes属性(字段)+1,保存,跳转结果

为了解决冗余,引入通用视图

修改views.py

from django.shortcuts import render, get_object_or_404
from django.http import HttpResponse, Http404, HttpResponseRedirect
from django.template import loader
from django.urls import reverse
from django.views import generic from .models import Question, Choice # def index(request):
# return HttpResponse("hello world,you are at the polls index!")
class IndexView(generic.ListView):
template_name = 'polls/index.html'
context_object_name = 'latest_question_list' def get_queryset(self):
"""Return the last five published question."""
return Question.objects.order_by('-pub_date')[:5] class DetailView(generic.DetailView):
model = Question
template_name = 'polls/detail.html' class ResultsView(generic.DetailView):
model = Question
template_name = 'polls/results.html' def vote(request,question_id):
question = get_object_or_404(Question, pk=question_id)
try:
selected_choice = question.choice_set.get(pk=request.POST['choice'])
except (KeyError, Choice.DoesNotExist):
return render(request, 'polls/detail.html', {
'question': question,
'error_message': "You didn't select a choice.",
})
else:
selected_choice.votes += 1
selected_choice.save()
return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))
# Create your views here.

generic.ListView(显示一个对象列表)和DetailView(显示详细内容)是django两个通用视图类,这里在创建我们自己的视图的时候继承了这两个父类

由于DetailView需要从url中获取名为pk的主键值,所以在urls中修改了question_id为pk。

DetailView视图默认使用一个叫做<app name>/<model name>_detail.html的模板,而此处我们选哟用自己的模板,template_name这个属性就是告诉django我们的默认模板是什么,通过具体指定。

对于ListView视图来说默认模板我们用自己的和Detail雷同的方式,但是对于Listview视图来说默认传递信息的上下文变量是question_list,这里由于我们的页面index中设置的上下文变量叫做

latest_question_list,所以我们需要通过设置context_object_name属性来覆盖。

当你更改了views后,这时候需要对urls也重新配置

polls/urls.py

from django.urls import path
from . import views app_name = 'polls'
urlpatterns = [
path('', views.IndexView.as_view(), name='index'),
# ex:/polls/5
path('<int:pk>/', views.DetailView.as_view(), name='detail'),
# ex:/polls/5/results
path('<int:pk>/results/', views.ResultsView.as_view(), name='results'),
# ex:/polls/5/vote/
path('<int:question_id>/vote/', views.vote, name='vote'),
]

然后你就可以在你的投票界面愉快的玩耍了

试着点选项和Vote试试?


题外话,当你创建了app之后,你的8000端口进入页面就一直都是404,这是因为有了app之后服务器从localhost:8000后面开始寻找pysite/urls.py中的配置,它无法找到""这个对应的模板,解决的办法就是手动给pysite添加views和templates并在urls.py中设置""对应的视图和名字,然后比如我这个就是这样:

使用pycharm开发web——django2.1.5(五)表单和通用视图的更多相关文章

  1. 使用pycharm开发web——django2.1.5(四)视图和模板相关

    刘老师说这块很重要..... 应该是很重要,大概看了一下,这里面关于views中函数作用,大概看来可能就是相应请求,传入数据和跳转,基本功能上貌似这些框架都差不多吧(其实我并没用过3个框架以上.... ...

  2. 使用pycharm开发web——django2.1.5(二)创建一个app并做一些配置

    这里我学习的呢是刘江老师的站,主要原因在于他这个版本新,还比较细节 网址先留一手,约等于在引用http://www.liujiangblog.com/ 开始正题: 1.在pycharm界面终端命令行里 ...

  3. 使用pycharm开发web——django2.1.5(一)入坑尝试第一步,基本搭建

    首先,接触python的人应该都会用pip 来安装需要的包吧(------>>>>)默认 在运行中使用python -m django --version来检查自己的djang ...

  4. 使用pycharm开发web——django2.1.5(三)创建models并进入交互界面shell做一些简单操作

    这里model可以认为是数据对象本身 相当于在写java代码时候model目录下创建的实体类,models.py 中可以包含多个实体类,感觉这个操作挺骚的 下面是polls app里面的models, ...

  5. SSM框架开发web项目系列(五) Spring集成MyBatis

    前言 在前面的MyBatis部分内容中,我们已经可以独立的基于MyBatis构建一个数据库访问层应用,但是在实际的项目开发中,我们的程序不会这么简单,层次也更加复杂,除了这里说到的持久层,还有业务逻辑 ...

  6. .net erp(办公oa)开发平台架构概要说明之表单设计器

    背景:搭建一个适合公司erp业务的开发平台.   架构概要图: 表单设计开发部署示例图    表单设计开发部署示例说明1)每个开发人员可以自己部署表单设计至本地一份(当然也可以共用一套开发环境,但是如 ...

  7. 一个web应用的诞生--数据表单

    下面把角色分为两种,普通用户和管理员用户,至少对于普通用户来说,直接修改DB是不可取的,要有用户注册的功能,下面就开始进行用户注册的开发. 用户表 首先要想好用户注册的时候需要提供什么信息:用户名.密 ...

  8. <玩转Django2.0>读书笔记:表单

    1. 表单字段 参考: 官方文档 Django表单字段汇总 2. 表单代码示例(forms.Form) # form.py代码 # 获取数据库数据 choices_list = [(i+1,v['ty ...

  9. vue 开发系列(八) 动态表单开发

    概要 动态表单指的是我们的表单不是通过vue 组件一个个编写的,我们的表单是根据后端生成的vue模板,在前端通过vue构建出来的.主要的思路是,在后端生成vue的模板,前端通过ajax的方式加载后端的 ...

随机推荐

  1. 数据结构实验之数组三:快速转置(SDUT 3347)

    Problem Description 转置运算是一种最简单的矩阵运算,对于一个m*n的矩阵M( 1 = < m < = 10000,1 = < n < = 10000 ),它 ...

  2. Asp.Net跨平台 Jexus 5.8.1 独立版

    在Linux上运行ASP.NET网站或WebApi的传统步骤是,先安装libgdiplus,再安装mono,然后安装Jexus.在这个过程中,虽然安装Jexus是挺简便的一件事,但是安装mono就相对 ...

  3. 1633:【例 3】Sumdiv

    #include<bits/stdc++.h> #define ll long long using namespace std; ; ll a,b,ans=,cnt; ll p[],c[ ...

  4. Devexpress GridControl中 repositoryItemCheckEdit作为选择列以及作为显示列的使用方法

    一.在gridcontrol列表控件中使用单选框作为选择列,这里有两种方式. 方式一:选择gridcontrol控件的Run Designer按钮,添加一列,设置该列的ColumnEdit为check ...

  5. 使用Android手机作为树莓派的屏幕

    在使用树莓派时,有时出于应急,身边没有屏幕,或者外出携带时也不方便带着屏幕走.如果能使用随身携带的智能手机当做其屏幕,则会方便许多.看看效果,一个树莓派+充电宝+手机,就会非常有用了. 满足以下条件即 ...

  6. vue实战_从头开始搭建vue工程

    写在前面:vue工程入口文件分析 /index.html,/src/main.js,/src/APP.vue /index.html文件示例: <!DOCTYPE html> <ht ...

  7. php-fpm脚本

    #! /bin/sh ### BEGIN INIT INFO # Provides: php-fpm # Required-Start: $remote_fs $network # Required- ...

  8. csp-s模拟109

    这场考试状态是极差,也因而无畏地打下了三个乱搞.然而这场确实挺乱搞.T1状压但我没优化而选择循环展开,T2打$bitset$随机化(考场上打的有问题不是随机但也能A),T3贪心骗分.但是因为状态实在太 ...

  9. JS -- Unexpected trailing comma

    Unexpected trailing comma 后面多了一个逗号

  10. ThinkPHP6.0学习之安装及问题解决

    ThinkPHP6.0学习之安装及问题解决 ThinkPHP6.0开发版已经上线了,我已经等了他很久了,现在写一个系列来记录Thinkphp6.0的使用,我们现在从安装开始学习吧. 首先我们要确定Th ...