zoukankan      html  css  js  c++  java
  • django项目mysite 2

    一、表单form

    为了接收用户的投票选择,我们需要在前端页面显示一个投票界面

    polls/detail.html

    <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>
    • forloop.counter是DJango模板系统专门提供的一个变量,用来表示你当前循环的次数,一般用来给循环项目添加有序数标。
    • 由于我们发送了一个POST请求,就必须考虑一个跨站请求伪造的安全问题,简称CSRF(具体含义请百度)。Django为你提供了一个简单的方法来避免这个困扰,那就是在form表单内添加一条{% csrf_token %}标签,标签名不可更改,固定格式,位置任意,只要是在form表单内。这个方法对form表单的提交方式方便好使,但如果是用ajax的方式提交数据,那么就不能用这个方法了。

    vote视图函数(polls/views.py)处理

    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,)))

    request.POST是一个类似字典的对象,允许你通过键名访问提交的数据。本例中,request.POST[’choice’]返回被选择选项的ID,并且值的类型永远是string字符串,那怕它看起来像数字!

    request.POST[’choice’]有可能触发一个KeyError异常,如果你的POST数据里没有提供choice键值,在这种情况下,上面的代码会返回表单页面并给出错误提示。PS:通常我们会给个默认值,防止这种异常的产生,例如request.POST[’choice’,None]

    在选择计数器加一后,返回的是一个HttpResponseRedirect而不是先前我们常用的HttpResponse。HttpResponseRedirect需要一个参数:重定向的URL。这里有一个建议,当你成功处理POST数据后,应当保持一个良好的习惯,始终返回一个HttpResponseRedirect。这不仅仅是对Django而言,它是一个良好的WEB开发习惯。

    我们在上面HttpResponseRedirect的构造器中使用了一个reverse()函数。它能帮助我们避免在视图函数中硬编码URL。它首先需要一个我们在URLconf中指定的name,然后是传递的数据。例如'/polls/3/results/',其中的3是某个question.id的值。重定向后将进入polls:results对应的视图,并将question.id传递给它。

    当有人对某个问题投票后,vote()视图重定向到了问卷的结果显示页面。下面我们来写这个处理结果页面的视图(polls/views.py):

    from django.shortcuts import get_object_or_404, render
    
    
    def results(request, question_id):
        question = get_object_or_404(Question, pk=question_id)
        return render(request, 'polls/results.html', {'question': question})

    模板polls/templates/polls/results.html

    <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>

    二、 使用通用视图:减少重复代码

    改良URLconf

    打开polls/urls.py文件,将其修改成下面的样子:

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

    修改视图

    接下来,打开polls/views.py文件,删掉index、detail和results视图,替换成Django的通用视图

    class IndexView(generic.ListView):
        template_name = 'polls/index.html'
        context_object_name = 'latest_question_list'
    
        def get_queryset(self):
            """Return the last five published questions."""
            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.get('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,)))

    我们使用了两种通用视图ListViewDetailView(它们是作为父类被继承的)。这两者分别代表“显示一个对象的列表”和“显示特定类型对象的详细页面”的抽象概念。

    • 每一种通用视图都需要知道它要作用在哪个模型上,这通过model属性提供。

    • DetailView需要从url捕获到的称为"pk"的主键值,因此我们在url文件中将2和3条目的<question_id>修改成了<pk>

    默认情况下,DetailView通用视图使用一个称作<app name>/<model name>_detail.html的模板。在本例中,实际使用的是polls/detail.htmltemplate_name属性就是用来指定这个模板名的,用于代替自动生成的默认模板名。(一定要仔细观察上面的代码,对号入座,注意细节。)同样的,在resutls列表视图中,指定template_name'polls/results.html',这样就确保了虽然resulst视图和detail视图同样继承了DetailView类,使用了同样的model:Qeustion,但它们依然会显示不同的页面。(模板不同嘛!so easy!)

    类似的,ListView通用视图使用一个默认模板称为<app name>/<model name>_list.html。我们也使用template_name这个变量来告诉ListView使用我们已经存在的 "polls/index.html"模板,而不是使用它自己默认的那个。

    在教程的前面部分,我们给模板提供了一个包含questionlatest_question_list的上下文变量。而对于DetailView,question变量会被自动提供,因为我们使用了Django的模型(Question),Django会智能的选择合适的上下文变量。然而,对于ListView,自动生成的上下文变量是question_list。为了覆盖它,我们提供了context_object_name属性,指定说我们希望使用latest_question_list而不是question_list

    三、 静态文件

    除了由服务器生成的HTML文件外,WEB应用一般需要提供一些其它的必要文件,比如图片文件、JavaScript脚本和CSS样式表等等,用来为用户呈现出一个完整的网页。在Django中,我们将这些文件统称为“静态文件”,因为这些文件的内容基本是固定不变的,不需要动态生成。

    对于小项目,这些都不是大问题,你可以将静态文件放在任何你的web服务器能够找到的地方。但是对于大型项目,尤其是那些包含多个app在内的项目,处理那些由app带来的多套不同的静态文件是个麻烦活。

    但这正是django.contrib.staticfiles的用途:它收集每个应用(和任何你指定的地方)的静态文件到一个统一指定的地方,并且易于访问。

    在polls目录中创建一个static目录。Django将在那里查找静态文件,这与Django在polls/templates/中寻找对应的模板文件的方式是一致的。

    Django的STATICFILES_FINDERS设置项中包含一个查找器列表,它们知道如何从各种源中找到静态文件。 其中一个默认的查找器是AppDirectoriesFinder

    它在每个INSTALLED_APPS下查找static子目录,例如我们刚创建的那个static目录。admin管理站点也为它的静态文件使用相同的目录结构。

    static目录中新建一个polls子目录,再在该子目录中创建一个style.css文件

    良好的目录结构是每个应用都应该创建自己的urls、forms、views、models、templates和static,每个templates包含一个与应用同名的子目录,每个static也包含一个与应用同名的子目录。

    polls/static/polls/style.css

    li a {
        color: green;
    }

    在模板文件polls/templates/polls/index.html的头部引用

    {% load static %}
    
    <link rel="stylesheet" type="text/css" href="{% static 'polls/style.css' %}">

    {% static %}模板标签会生成静态文件的绝对URL路径。

    重启服务器,在浏览器访问http://localhost:8000/polls/,你会看到Question的超级链接变成了绿色

    添加背景图片

    polls/static/polls/目录下创建一个用于存放图片的images子目录,在这个子目录里放入`background.gif文件

     在css样式文件polls/static/polls/style.css中添加

    body {
        background: white url("images/background.gif") no-repeat;
    }

    重新加载http://localhost:8000/polls/(CTRL+F5或者直接F5),你会在屏幕的左上角看到载入的背景图片

    提示:

    {% static %}模板标签不能用在静态文件,比如样式表中,因为他们不是由Django生成的。 你应该使用相对路径来相互链接静态文件

    直接访问静态文件

     

    参考刘江的博客教程

  • 相关阅读:
    使用合理jQuery选择器查找DOM元素
    DOM对象和jQuery对象
    jQuery实现返回顶部
    行内元素,块级元素
    图片自适应缩放
    幽灵按钮
    background-attachment:fixed
    RegExp
    正则
    Date
  • 原文地址:https://www.cnblogs.com/xiao-apple36/p/11386224.html
Copyright © 2011-2022 走看看