python(django(管理页面、概况、编写视图占位、编写一个真正的视图、抛出错误、视图使用模板系统、去除硬编码url、为url添加命名开空间、编写表单))

学习目标:

Python学习十八-Django、


学习内容:

1、介绍 Django 管理页面
2、django概况
3、django编写视图
4、django编写一个真正的视图
5、django抛出404错误
6、django视图使用模板系统
7、django去除模板中的硬编码 URL
8、django为 URL 名称添加命名空间
9、django编写一个表单


1、介绍 Django 管理页面

1、创建一个管理员账号
在pycharm中的terminal输入下列指令:

python manage.py createsuperuser

(base) F:\pycharm\project\Django\yyt>python manage.py createsuperuser
Username (leave blank to use 'administrator'): root
Email address: 812277079@qq.com
Password:
Password (again):
This password is too short. It must contain at least 8 characters.
Bypass password validation and create user anyway? [y/N]: y
Superuser created successfully.

2、启动开发服务器

python manage.py runserver

  • 打开浏览器,转到你本地域名的 “/admin/” 目录, – 比如 “http://127.0.0.1:8000/admin/”
    在这里插入图片描述
    3、进入管理站点页面
    利用刚才创建的用户和密码登录

可编辑的内容:组和用户,它们是由 django.contrib.auth 提供的,这是 Django 开发的认证框架
在这里插入图片描述

4、向管理页面中加入应用
前面我们创建了投票应用,把投票应用加入到管理页面

  • 告诉管理页面,问题 Question 对象需要被管理,打开 polls/admin.py 文件,编辑如下:
from django.contrib import admin
from .models import Question

admin.site.register(Question)

5、体验便捷的管理功能
管理页面注册了问题 Question 类,在页面中可以很方便的对该类进行操作了
在这里插入图片描述


2、django概况

  • Django 中的视图:一类具有相同功能和模板的网页的集合
  • 在 Django 中,网页和其他内容都是从视图派生而来。每一个视图表现为一个简单的 Python
    函数(或者说方法,如果是在基于类的视图里的话),Django 将会根据用户请求的 URL 来选择使用哪个视图(更准确的说,是根据 URL中域名之后的部分)
  • URL 模式中 URL 的基本格式,举个例子:/newsarchive///
  • Django 使用了 ‘URLconfs’ 来配置将 URL 和视图关联起来,URLconf 将 URL 模式映射到视图

3、django编写视图

根据之前创建的yyt项目(polls应用),进行一下一些编写
1、创建新的视图并且添加到polls.urls里面

  • 向 yyt项目的polls/views.py 里添加更多视图,这些视图有一些不同,因为他们接收参数
def detail(request,question_id):
    return HttpResponse('you are looking at question %s.'% question_id)


def results(request,question_id):
    response = 'you are looking at the results of question %s'
    return HttpResponse(response,question_id)


def vote(request,question_id):
    return HttpResponse('you`re voting on question %s' % question_id)
  • 把这些新视图添加进 polls.urls 模块里,只要添加几个 url() 函数调用
 urlpatterns = [
    path('',views.index, name='index'),
    path('<int:question_id>/',views.detail,name = 'detail'),
    path('<int:question_id>/results/',views.results,name = 'results'),
    path('<int:question_id>/vote/',views.vote,name = 'vate'),
]
  • 然后在浏览器,输入 “http://127.0.0.1:8000/polls/34/” ,Django 将会运行 detail()方法并且展示你在 URL 里提供的问题 ID,再试试 “/polls/34/vote/” 和 “/polls/34/vote/”,你将会看到暂时用于占位的结果和投票页
    在这里插入图片描述
  • 当请求网站的某一页面时,比如 “http://127.0.0.1:8000/polls/34/”,Django会载入yyt.urls模块,因为这在配置项 ROOT_URLCONF 中设置了,然后 Django 寻找名为urlpatterns 变量并且按序匹配正则表达式,在找到匹配项’polls/’,它切掉了匹配的文本(“polls/”),将剩余文本"34/",发送至 ‘polls.urls’ URLconf做进一步处理,在这里剩余文本匹配了 ‘<int:question_id>/’,使得我们 Django 以如下形式调用 detail():

question_id=34 由 <int:question_id> 匹配生成,尖括号“捕获”这部分URL,以关键字参数的形式发送给视图函数,’<int:question_id>/的 :question_id>部分定义了将被用于区分匹配模式的变量名,int: 则是一个转换器决定了应该以什么变量类型匹配这部分的 URL 路径

detail(request=<HttpRequest object>, question_id=34)

4、django编写一个真正的视图

  • 视图必须要做的只有两件事:返回一个包含被请求页面内容的 HttpResponse 对象,或者抛出一个异常,比如 Http404,至于你还想干些什么,随便你
  • Django 只要求返回的是一个 HttpResponse ,或者抛出一个异常

1、调用django的API接口,在views里面加入内容,展示数据库里以发布日期排序的最近 5 个投票问题,以空格分割:

from django.http import HttpResponse

from .models import Question


def index(request):
    latest_question_list = Question.objects.order_by('-pub_date')[:5]
    output = ', '.join([q.question_text for q in latest_question_list])
    return HttpResponse(output)

2、使用 Django 的模板系统创建一个视图,将页面的设计从代码中分离出来改变页面的样子

  • 在项目yyt中创建一个 templates 目录,Django 将会在这个目录里查找模板文件

项目的TEMPLATES配置项描述了Django如何载入和渲染模板,默认的设置文件设置了DjangoTemplates 后端,并将APP_DIRS设置成了 True,这将会让DjangoTemplates在每个INSTALLED_APPS文件夹中寻找 “templates” 子目录,这就是为什么尽管我们没有像在第二部分中那样修改 DIRS 设置,Django 也能正确找到polls 的模板位置的原因

在创建的 templates 目录里,新建一个文件 index.html,模板文件的路径应该是yyt/templates/index.html ,Django会找到对应的app_directories,你只需要使用polls/index.html 就可以引用到这一模板

在这里插入图片描述

  • 在polls应用视图中利用快捷函数重新编写index代码访问数据库,并且返回值到indx.html

快捷函数:render()

def index(request):
    q_all = Question.objects.all()
    context = {'q_all': q_all}
    return render(request, 'index.html', context)
  • 编写indx.html,遍历views视图返回的数据库
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
{% if q_all %}
<ul>
{% for i in q_all %}
    <li><a href="/polls/{{i.id}}/">{{i.question_text}}</a></li>
{% endfor %}
</ul>
{%else%}
<p>No polls are available.</p>
{%endif%}
</body>
</html>

在这里插入图片描述
点击第三个超链接:
在这里插入图片描述


5、django抛出404错误

1、尝试用 get() 函数获取一个对象,如果不存在就抛出 Http404 错误也是一个普遍的流程

  • 在views视图中编写detail方法
from django.http import Http404
from django.shortcuts import render

from .models import Question
# ...
def detail(request, question_id):
    try:
        question = Question.objects.get(pk=question_id)
    except Question.DoesNotExist:
        raise Http404("Question does not exist")
    return render(request, 'polls/detail.html', {'question': question})
  • 在templates中新建一个detail.html文件,输入如下:
{{ question }}
  • 随便输入一个question_id,显示如下:
    在这里插入图片描述
    2、一个快捷函数: get_object_or_404()
    django提供一个快捷函数抛出404错误

get_object_or_404()

from django.shortcuts import get_object_or_404, render

from .models import Question
# ...
def detail(request, question_id):
    question = get_object_or_404(Question, pk=question_id)
    return render(request, 'polls/detail.html', {'question': question})

6、django视图使用模板系统

detail视图返回的值到detail.html模板

  • 编写detail.html模板

for函数会遍历question.choice_set.all返回可迭代对象choice,choice可以在对象所在标签内使用

<!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 }}</li>
{% endfor %}
</ul>
</body>
</html>
  • 当在polls应用中点击index视图返回到index.html模板的question_text时,会跳转到detail视图返回的detail.html模板

点击第一个question_id为1:
在这里插入图片描述
直接输入一个不存在的question_id时会返回404:
在这里插入图片描述


7、django去除模板中的硬编码 URL

polls/index.html 里编写投票链接时,链接是硬编码的
1、因为在 polls.urls 的 url() 函数中通过 name 参数为 URL 定义了名字,可以使用 {% url %} 标签

<li><a href="/polls/{{ question.id }}/">{{ question.question_text }}</a></li>
替换成
<li><a href="{% url 'detail' question.id %}">{{ question.question_text }}</a></li>

2、如果想改变投票详情视图的 URL

  • 比如想改成 polls/specifics/12/ ,只需要在 polls/urls.py 里修改
path('specifics/<int:question_id>/', views.detail, name='detail'),

8、django为 URL 名称添加命名空间

django在根 URLconf 中添加命名空间,在 polls/urls.py 文件中加上 app_name 设置命名空间,就可以分辨重名的 URL

  • 举个例子:polls 应用有 detail 视图,可能另一个博客应用也有同名的视图,Django 可以知道 {% url %}标签对应应用的 URL
from django.urls import path

from .views import *
app_name = 'polls'
urlpatterns = [
    path('', views.index, name='index'),
    path('<int:question_id>/', views.detail, name='detail'),
    path('<int:question_id>/results/', views.results, name='results'),
    path('<int:question_id>/vote/', views.vote, name='vote'),
]
  • 可根据修改的polls/urls.py修改index.html
<li><a href="{% url 'polls:detail' i.id %}">{{ i.question_text }}</a></li>

9、django编写一个表单

改写templates中detail.html代码,实现一个简单的表单
1、利用html的相关标签实现表单

  • 每个单选按钮的 value 属性是对应的各个 Choice 的 ID
  • name 是 “choice”,选择单选按钮并提交表单提交时,发送一个 POST 数据choice=choice_id
  • forloop.counter 指示 for标签已经循环多少次
  • django针对内部 URL 的 POST 表单都应该使用 {% csrf_token %} 模板标签
  • 改写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>

或者

<!DOCTYPE html>
<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 }}</li><input type="radio" name="choice">-->
<!--{% endfor %}-->
<!--</ul>-->
<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 %}
    {% if choice.choice_text == '是' %}
    <input type="radio" name="choice" id="choice{{ forloop.counter}}" value="{{ choice.id }}" checked>
    {% else %}
    <input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}" >

    {% endif %}
    <label for="choice{{ forloop.counter }}">{{ choice.choice_text }}</label><br>
    {% endfor %}
    <input type="submit" value="Vote">
</form>
</body>
  • 改写vote视图,处理提交的数据,之前已经创建了vote视图的URLconf
  • request.POST 是一个类字典对象,让你可以通过关键字的名字获取提交的数据
  • reverse()调用将返回一个url地址:’/polls/3/results/’
from django.shortcuts import render, get_object_or_404
from django.http import HttpResponse,HttpResponseRedirect
from django.urls import reverse
from .models import Question, Choice


def results(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):
        # Redisplay the question voting form.
        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,)))
  • 编写result视图,对 Question 进行投票后, vote() 视图将请求重定向到 Question 的结果界面
def results(request, question_id):
    question = get_object_or_404(Question, pk=question_id)
    return render(request, 'polls/results.html', {'question': question})
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值