关于“Python”的核心知识点整理大全56

 

目录

6. 链接到页面new_topic

topics.html

19.1.2 添加新条目

1. 用于添加新条目的表单

forms.py

2. URL模式new_entry

urls.py

3. 视图函数new_entry()

views.py

4. 模板new_entry

new_entry.html

5. 链接到页面new_entry

topic.html

19.1.3 编辑条目

1. URL模式edit_entry

urls.py

2. 视图函数edit_entry()

views.py

往期快速传送门👆(在文章最后):

感谢大家的支持!欢迎订阅收藏!专栏将持续更新!


{% extends "learning_logs/base.html" %}
{% block content %}
 <p>Add a new topic:</p>
1 <form action="{% url 'learning_logs:new_topic' %}" method='post'>
2 {% csrf_token %}
3 {{ form.as_p }}
4 <button name="submit">add topic</button>
 </form>
{% endblock content %}

这个模板继承了base.html,因此其基本结构与项目“学习笔记”的其他页面相同。在1处, 我们定义了一个HTML表单。实参action告诉服务器将提交的表单数据发送到哪里,这里我们将 它发回给视图函数new_topic()。实参method让浏览器以POST请求的方式提交数据。

Django使用模板标签{% csrf_token %}(见2)来防止攻击者利用表单来获得对服务器未经 授权的访问(这种攻击被称为跨站请求伪造)。在3处,我们显示表单,从中可知Django使得完 成显示表单等任务有多简单:我们只需包含模板变量{{ form.as_p }},就可让Django自动创建显 示表单所需的全部字段。修饰符as_p让Django以段落格式渲染所有表单元素,这是一种整洁地显 示表单的简单方式。

Django不会为表单创建提交按钮,因此我们在4处定义了一个这样的按钮。

6. 链接到页面new_topic

接下来,我们在页面topics中添加一个到页面new_topic的链接:

topics.html

{% extends "learning_logs/base.html" %}
{% block content %}
 <p>Topics</p>
 <ul>
 --snip--
 </ul>
 <a href="{% url 'learning_logs:new_topic' %}">Add a new topic:</a>
{% endblock content %} 

这个链接放在了既有主题列表的后面。图19-1显示了生成的表单。请使用这个表单来添加几 个新主题。

19.1.2 添加新条目

现在用户可以添加新主题了,但他们还想添加新条目。我们将再次定义URL,编写视图函数 和模板,并链接到添加新条目的网页。但在此之前,我们需要在forms.py中再添加一个类。

1. 用于添加新条目的表单

我们需要创建一个与模型Entry相关联的表单,但这个表单的定制程度比TopicForm要高些:

forms.py
from django import forms
from .models import Topic, Entry
class TopicForm(forms.ModelForm):
 --snip--
class EntryForm(forms.ModelForm):
 class Meta:
 model = Entry
 fields = ['text']
1 labels = {'text': ''}
2 widgets = {'text': forms.Textarea(attrs={'cols': 80})}

我们首先修改了import语句,使其除导入Topic外,还导入Entry。新类EntryForm继承了forms.ModelForm,它包含的Meta类指出了表单基于的模型以及要在表单中包含哪些字段。这里也 给字段'text'指定了一个空标签(见1)。

在2处,我们定义了属性widgets。小部件(widget)是一个HTML表单元素,如单行文本框、 多行文本区域或下拉列表。通过设置属性widgets,可覆盖Django选择的默认小部件。通过让 Django使用forms.Textarea,我们定制了字段'text'的输入小部件,将文本区域的宽度设置为80 列,而不是默认的40列。这给用户提供了足够的空间,可以编写有意义的条目。

2. URL模式new_entry

在用于添加新条目的页面的URL模式中,需要包含实参topic_id,因为条目必须与特定的主 题相关联。该URL模式如下,我们将它添加到了learning_logs/urls.py中:

urls.py
--snip--
urlpatterns = [
 --snip--
 # 用于添加新条目的页面
 url(r'^new_entry/(?P<topic_id>\d+)/$', views.new_entry, name='new_entry'),
] 

这个URL模式与形式为http://localhost:8000/new_entry/id/的URL匹配,其中id是一个与 主题ID匹配的数字。代码(?P\d+)捕获一个数字值,并将其存储在变量topic_id中。请 求的URL与这个模式匹配时,Django将请求和主题ID发送给函数new_entry()。

3. 视图函数new_entry()

视图函数new_entry()与函数new_topic()很像:

views.py
from django.shortcuts import render
--snip--
from .models import Topic
from .forms import TopicForm, EntryForm
--snip--
def new_entry(request, topic_id):
 """在特定的主题中添加新条目"""
1 topic = Topic.objects.get(id=topic_id)
2 if request.method != 'POST':
 # 未提交数据,创建一个空表单
3 form = EntryForm()
 else:
 # POST提交的数据,对数据进行处理
4 form = EntryForm(data=request.POST)
 if form.is_valid():
5 new_entry = form.save(commit=False)
6 new_entry.topic = topic 
 new_entry.save()
7 return HttpResponseRedirect(reverse('learning_logs:topic',
 args=[topic_id]))
 context = {'topic': topic, 'form': form}
 return render(request, 'learning_logs/new_entry.html', context)

我们修改了import语句,在其中包含了刚创建的EntryForm。new_entry()的定义包含形参 topic_id,用于存储从URL中获得的值。渲染页面以及处理表单数据时,都需要知道针对的是哪 个主题,因此我们使用topic_id来获得正确的主题(见1)。

在2处,我们检查请求方法是POST还是GET。如果是GET请求,将执行if代码块:创建一 个空的EntryForm实例(见3)。如果请求方法为POST,我们就对数据进行处理:创建一个EntryForm 实例,使用request对象中的POST数据来填充它(见4);再检查表单是否有效,如果有效,就设 置条目对象的属性topic,再将条目对象保存到数据库。

调用save()时,我们传递了实参commit=False(见5),让Django创建一个新的条目对象,并 将其存储到new_entry中,但不将它保存到数据库中。我们将new_entry的属性topic设置为在这个 函数开头从数据库中获取的主题(见6),然后调用save(),且不指定任何实参。这将把条目保 存到数据库,并将其与正确的主题相关联。

在7处,我们将用户重定向到显示相关主题的页面。调用reverse()时,需要提供两个实参: 要根据它来生成URL的URL模式的名称;列表args,其中包含要包含在URL中的所有实参。在这 里,列表args只有一个元素——topic_id。接下来,调用HttpResponseRedirect()将用户重定向到 显示新增条目所属主题的页面,用户将在该页面的条目列表中看到新添加的条目。

4. 模板new_entry

从下面的代码可知,模板new_entry类似于模板new_topic:

new_entry.html
{% extends "learning_logs/base.html" %}
{% block content %}
1 <p><a href="{% url 'learning_logs:topic' topic.id %}">{{ topic }}</a></p>
 <p>Add a new entry:</p>
2 <form action="{% url 'learning_logs:new_entry' topic.id %}" method='post'>
 {% csrf_token %}
 {{ form.as_p }}
 <button name='submit'>add entry</button>
 </form>
{% endblock content %} 

我们在页面顶端显示了主题(见1),让用户知道他是在哪个主题中添加条目;该主题名也 是一个链接,可用于返回到该主题的主页面。

表单的实参action包含URL中的topic_id值,让视图函数能够将新条目关联到正确的主题(见 2)。除此之外,这个模板与模板new_topic.html完全相同。

5. 链接到页面new_entry

接下来,我们需要在显示特定主题的页面中添加到页面new_entry的链接:

topic.html
{% extends "learning_logs/base.html" %}
{% block content %}
 <p>Topic: {{ topic }}</p>
 <p>Entries:</p>
 <p>
 <a href="{% url 'learning_logs:new_entry' topic.id %}">add new entry</a>
 </p>
 <ul>
 --snip—
 </ul>
{% endblock content %}

我们在显示条目前添加链接,因为在这种页面中,执行的最常见的操作是添加新条目。图19-2 显示了页面new_entry。现在用户可以添加新主题,还可以在每个主题中添加任意数量的条目。 请在一些既有主题中添加一些新条目,尝试使用一下页面new_entry。

19.1.3 编辑条目

下面来创建一个页面,让用户能够编辑既有的条目。

1. URL模式edit_entry

这个页面的URL需要传递要编辑的条目的ID。修改后的learning_logs/urls.py如下:

urls.py
--snip--
urlpatterns = [
 --snip--
 # 用于编辑条目的页面
 url(r'^edit_entry/(?P<entry_id>\d+)/$', views.edit_entry,
 name='edit_entry'),
] 

在URL(如http://localhost:8000/edit_entry/1/)中传递的ID存储在形参entry_id中。这个URL 模式将预期匹配的请求发送给视图函数edit_entry()。

2. 视图函数edit_entry()

页面edit_entry收到GET请求时,edit_entry()将返回一个表单,让用户能够对条目进行编 辑。该页面收到POST请求(条目文本经过修订)时,它将修改后的文本保存到数据库中:

views.py
from django.shortcuts import render
--snip--
from .models import Topic, Entry
from .forms import TopicForm, EntryForm
--snip--
def edit_entry(request, entry_id):
 """编辑既有条目"""
1 entry = Entry.objects.get(id=entry_id)
topic = entry.topic
 if request.method != 'POST':
 # 初次请求,使用当前条目填充表单
2 form = EntryForm(instance=entry)
 else:
 # POST提交的数据,对数据进行处理
3 form = EntryForm(instance=entry, data=request.POST)
 if form.is_valid():
4 form.save()
5 return HttpResponseRedirect(reverse('learning_logs:topic',
 args=[topic.id]))
 context = {'entry': entry, 'topic': topic, 'form': form}
 return render(request, 'learning_logs/edit_entry.html', context)

关于“Python”的核心知识点整理大全37-CSDN博客

关于“Python”的核心知识点整理大全25-CSDN博客

关于“Python”的核心知识点整理大全12-CSDN博客

往期快速传送门👆(在文章最后):

感谢大家的支持!欢迎订阅收藏!专栏将持续更新!