zoukankan      html  css  js  c++  java
  • 使用pycharm开发web——django2.1.5(五)表单和通用视图

    看了刘江老师教程这么多天,卧槽,我才发现他也曾跻身于行伍之间,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中设置""对应的视图和名字,然后比如我这个就是这样:

  • 相关阅读:
    UIButton添加倒计时
    AFNetworking+Python+Flask+pyOpenSSL构建iOS HTTPS客户端&服务器端
    js脚本都可以放在哪些地方
    js实现整数转化为小数
    JavaBean自动生成get和set方法
    servlet与Javabean之间的区别
    搞不懂SSH与JAVA+Servlet+javabean有什么关系
    启动 Eclipse 弹出“Failed to load the JNI shared library jvm.dll”的解决方法!
    win8安装sql2008及设置登陆名问题
    jdbc的配置及jdbc连接常用数据库(mysql、sqlserver、Oracle)
  • 原文地址:https://www.cnblogs.com/lovely-lisk/p/11069629.html
Copyright © 2011-2022 走看看