Python编程从⼊门到实践-第19章-⽤户账户
前⾔
  Web应⽤程序的核⼼是让任何⽤户都能够注册账户并能够使⽤它,不管⽤户⾝处何⽅。
  在本章中,你将创建⼀些表单,让⽤户能够添加主题和条⽬,以及编辑既有的条⽬。你还将学习Django如何防范对基于表单的⽹页发
起的常见攻击。
  然后,我们将实现⼀个⽤户⾝份验证系统。你将创建⼀个注册页⾯,供⽤户创建账户,并让有些页⾯只能供已登录的⽤户访问。接下
来,我们将修改⼀些视图函数,使得⽤户只能看到⾃⼰的数据。你将学习如何确保⽤户数据的安全。
⼀、让⽤户能够输⼊数据
  当前,只有超级⽤户能够通过管理⽹站输⼊数据。我们不想让⽤户与管理⽹站交互,因此我们将使⽤Django的表单创建⼯具来创建让
⽤户能够输⼊数据的页⾯。
1. 添加新主题
  创建基于表单的页⾯的⽅法⼏乎与前⾯创建⽹页⼀样:定义⼀个URL,编写⼀个视图函数并编写⼀个模板。⼀个主要差别是,需要导⼊
包含表单的模块forms.py。
(1) ⽤于添加主题的表单
表单:让⽤户输⼊并提交信息的页⾯
新建form.py,将其存储到models.py所在的⽬录中
from django import forms
from .models import Topic
class TopicForm(forms.ModelForm):
class Meta:
model = Topic
fields = ['text']
labels = {'text': ''}
使⽤ModelForm创建表单,它根据在第18章定义的模型中的信息⾃动创建表单。⼀个内嵌的Meta类,它告诉Django根据哪个模型创建表单,以及在表单中包含哪些字我们根据模型Topic创建⼀个表单,该表单只包含字段text。不为字段text⽣成标签。
(2) URL模式new_topic
urls.py
--snip--
urlpatterns = [
--snip--
"⽤于添加新主题的页⾯"
re_path(r'^new_topic/$', w_topic, name='new_topic')python入门教程app
]
(3) 视图函数new_topic()
函数new_topic()需要处理两种情形:刚进⼊new_topic⽹页(在这种情况下,它应显⽰⼀个空表单);对提交的表单数据进⾏处理,并将⽤户重定向到⽹页topics:
  创建Web应⽤程序时,将⽤到的两种主要请求类型是GET请求和POST请求。对于只是从服务器读取数据的页⾯,使⽤GET请求;在⽤户需要通过表单提交信息时,通常使⽤POST请求。根据请求的类型,我们可以确定⽤户请求的是空表单(GET请求),还是要求对填写好的表单进⾏处理(POST请求)。
from django.shortcuts import render
from django.http import HttpResponseRedirect
from django.urls import reserve
from .forms improt TopicForm
--snip--
def new_topic(request):
"""添加新主题"""
hod != 'POST':
# 未提交数据,创建⼀个新表单
form = TopicForm()
else:
# POST提交数据,对数据处理.我们使⽤⽤户输⼊的数据(它们存储在request.POST中)创建⼀个TopicForm实例
form = TopicForm(request.POST)
# is_valid()核实⽤户填写了所有必不可少的字段,且输⼊的数据与要求的字段类型⼀致
if form.is_valid():
# 表单中的数据写⼊数据库
form.save()
return HttpResponseRedirect(reserve('learning_logs:topics'))
context = {'form': form}
return render(request, 'learning_logs/new_topic', context)
函数reverse()根据指定的URL模型确定URL,这意味着Django将在页⾯被请求时⽣成URL。我们使⽤reverse()获取页⾯topics的URL,并将其传递给HttpResponseRedirect,后者将⽤户的浏览器重定向到页⾯topics。在页⾯topics中,⽤户将在主题列表中看到他刚输⼊的主题。
(4) 模板new_topic
{% extends 'learning_logs/base.html' %}
{% block content %}
<p>Add a new topic:</p>
<form action='{% url 'learning_logs:new_topic' %}' method='POST'>
{csrf_token}
{{form.as_p}}
<button name='submit'>Add topic</button>
</form>
{% endblock content %}
<form></form>⼀个HTML表单。实参action告诉服务器将提交的表单数据发送到哪⾥,这⾥我们将它发回给视图函数new_topic()。实参method让浏览器以POST请求的⽅式提交数据。
Django使⽤模板标签{% csrf_token %}来防⽌攻击者利⽤表单来获得对服务器未经授权的访问(这种攻击被称为跨站请求伪造)。模板变量{{ form.as_p }},就可让Django⾃动创建显⽰表单所需的全部字段。修饰符as_p让Django以段落格式渲染所有表单元素。Django不会为表单创建提交按钮,定义了⼀个按钮<button>。
(5) 页⾯topics添加⼀个 到页⾯new_topic的链接
2. 添加新条⽬
(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']
labels = {'text': ''}
widgets = {'text': forms.Textarea(attrs={'cols': 80})}
Meta类指出了表单基于的模型以及要在表单中包含哪些字段。 ⼩部件(widget)是⼀个HTML表单元素,如单⾏⽂本框、多⾏⽂本区域或下拉列表。通过设置属性widgets,可覆盖Django选择的默认⼩部件。通过让Django使⽤forms.Textarea,我们定制了字段'text'的输⼊⼩部件,将⽂本区域的宽度设置为80列,⽽不是默认的40列。
(2) URL模式new_entry
在⽤于添加新条⽬的页⾯的URL模式中,需要包含实参topic_id,因为条⽬必须与特定的主题相关联。
urls.py
--snip--
urlpatterns = [
# ⽤于添加新条⽬的页⾯
re_path(r'^new_entry/(?P<topic_id>\d+)/$', 'learning_log/new_entry.html', name='new_entry')
]
(3) 视图函数new_entry()
views.py
from django.shortcuts import render
from django.http import HttpResponseRedirect
from django.urls import reserve
from .models import Topic
from .forms import TopicForm, EntryForm
def new_entry(request, topic_id):
"""添加新条⽬"""
topic = (id=topic_id)
hod != 'POST':
# 没提交数据,建⽴⼀个空表单
python编程入门经典读后感form = EntryFrom()
else:
# POST提交数据,对数据处理自己的己急怎么组词
form = EntryFrom(data=request.POST)
if form.is_valid():
new_entry = form.save(commit=False)
pic = topic
new_entry.save()
return HttpResponseRedirect(reserve('learning_logs:topic', args=[topic_id]))
context = {'topic': topic,'form': form}
return render(request, 'learning_logs/new_entry.html', context)
new_entry()的定义包含形参topic_id,⽤于存储从URL中获得的值。我们使⽤topic_id来获得正确的主题。
调⽤save()时,我们传递了实参commit=False,让Django创建⼀个新的条⽬对象,但不将它保存到数据库中。我们将new_entry的属性topic设置为在这个函数开头从数据库中获取的主题,然后调⽤save(),这将把条⽬保存到数据库,并将其与正确的主题相关联。
调⽤reverse()时,需要提供两个实参:要根据它来⽣成URL的URL模式的名称;列表args,其中包含要包含在URL中的所有实参(当前topic_id)。调⽤HttpResponseRedirect()将⽤户重定向到显⽰新增条⽬所属主题的页⾯,⽤户将在该页⾯的条⽬列表中看到新添加的条⽬。
(4) 模板new_entry
new_entry.html
{% extends 'learning_logs/base.html' %}
{% block content %}
<p><a href="{% url 'learning_logs:topic' topic.id %}">{{ topic }}</a></p>
<form action="{% url 'learning_logs:new_entry' topic.id %}">textarea框的默认值怎么设置
{ csrf_token }
{{ form.as_p }}异步传输总线的叙述
<button name="submit">add entry</button>
于的用法
</form>
{% endblock content %}
(5) 在显⽰特定主题的页⾯中添加到页⾯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>
{% endbolock content%}
3. 编辑条⽬
(1) URL模式edit_entry
这个页⾯的URL需要传递要编辑的条⽬的ID。
urls.py
--snip--
urlpatterns = [
# ⽤于编辑条⽬的页⾯
re_path(r'^edit_entry/(?P<entry_id>\d+)$', views.edit_entry, name="edit_entry"),
]
(2) 视图函数edit_entry()
页⾯edit_entry收到GET请求时,edit_entry()将返回⼀个表单,让⽤户能够对条⽬进⾏编辑。该页⾯收到POST请求(条⽬⽂本经过修订)时,它将修改后的⽂本保存到数据库中:

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。