欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

使用pycharm开发web——django2.1.5(五)表单和通用视图

程序员文章站 2022-04-29 18:05:34
看了刘江老师教程这么多天,卧槽,我才发现他也曾跻身于行伍之间,interesting 刘老师这波讲解很到位,告诉你如何编写单例视图的时候忽然告诉你,其实不用这么麻烦,我们有通用视图,那些总是要做相似的行为的视图,咱们就写一个好了,解放生产力不就是进步吗? 好的废话不说进入正题,先修改一波detail ......

看了刘江老师教程这么多天,卧槽,我才发现他也曾跻身于行伍之间,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,保存,跳转结果

使用pycharm开发web——django2.1.5(五)表单和通用视图

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

修改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'),
]

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

使用pycharm开发web——django2.1.5(五)表单和通用视图

试着点选项和vote试试?


 

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

使用pycharm开发web——django2.1.5(五)表单和通用视图