2021-06-07

第19章 用户账户

19.1让用户输入数据

19.1.1 添加新主题
1.用于添加主题的表单
forms.py

from django import forms

from .models import Topic

class TopicForm(forms.ModelForm):#模块TopicForm继承forms.ModelForm
    class Meta:
        model =Topic #根据模型Topic创建表单
        fields = ['text']
        labels = ['text':'']#对字段text不生成标签
        

2.URL模式new_topic

#learning_logs/urls.py
from django.urls import path#导入path用于映射url到视图

from . import views#.:从当前文件夹导入views.py

app_name = 'learning_logs'
urlpatterns = [
    #主页
    path('',views.index,name='index'),#指定django要调用index函数
    #显示所有主题
    path('topics/',views.topics, name='topics'),
    #特定主题的详细页面
    path('topics/<int:topic_id>/',views.topic,name='topic'),
    #用于添加新主题的页面
    path('new_topic/',views.new_topic/,name='new_topic'),
    ]


app_name = 'learning_logs'

3.视图函数new_topic()
views.py

from django.shortcuts import render,redirect

from .models import Topic
from .forms import TopicForm

def index(request):
    return render(request, 'learning_logs/index.html')

def topics(request):
    topics = Topic.objects.order_by('date_added')
    context = {'topics': topics}    
    return render(request, 'learning_logs/topics.html', context)
    
def topic(request,topic_id):
    """显示单个主题及其所有的条目"""
    topic = Topic.objects.get(id=topic_id)
    entries = topic.entry_set.order_by('-date_added')
    context = {'topic':topic,'entries':entries}
    return render(request,'learning_logs/topic.html',context)
    
def new_topic(request):
    """添加新表单"""
    if request.method != 'POST':
        #未提交数据:创建一个新表单
        form = TopicForm()
    else:
        #POST提交的数据,对数据进行处理
        form =TopicForm(data=request.POST)
        if form.is_valid():
            form.save()
            return redirect(request,'learning_logs/new_topic.html',context)

4.GET请求和POST请求

创建Web应用程序时,将用到的两种主要请求类型是GET请求
和POST请求。对于只是从服务器读取数据的页面,使用GET
请求;在用户需要通过表单提交信息时,通常使用POST 请
求。处理所有表单时,都将指定使用POST方法。还有一些其
他类型的请求,但本项目没有使用。函数new_topic() 将请求对象作为参数。用户初次请求该页
面时,其浏览器将发送GET请求;用户填写并提交表单时,其
浏览器将发送POST请求。根据请求的类型,可确定用户请求
的是空表单(GET请求)还是要求对填写好的表单进行处理
(POST请求)。
❶处的测试确定请求方法是GET还是POST。如果请求方法不
是POST,请求就可能是GET,因此需要返回一个空表单。
(即便请求是其他类型的,返回空表单也不会有任何问题。)
❷处创建一个TopicForm 实例,将其赋给变量form ,再通过
上下文字典将这个表单发送给模板(见❼)。由于实例
化TopicForm 时没有指定任何实参,Django将创建一个空表
单,供用户填写。
如果请求方法为POST,将执行else 代码块,对提交的表单数
据进行处理。我们使用用户输入的数据(存储
在request.POST 中)创建一个TopicForm 实例(见❸),这
样对象form 将包含用户提交的信息。
要将提交的信息保存到数据库,必须先通过检查确定它们是有
效的(见❹)。方法is_valid() 核实用户填写了所有必不可
少的字段(表单字段默认都是必不可少的),且输入的数据与
要求的字段类型一致(例如,字段text 少于200字符,这是第
18章在models.py中指定的)。这种自动验证避免了我们去做大
量的工作。如果所有字段都有效,就可调用save() (见
❺),将表单中的数据写入数据库。
保存数据后,就可离开这个页面了。为此,使用redirect()
将用户的浏览器重定向到页面topics (见❻)。在页
面topics 中,用户将在主题列表中看到他刚输入的主题。
我们在这个视图函数的末尾定义了变量context ,并使用稍后
将创建的模板new_topic.html来渲染页面。这些代码不在if 代
码块内,因此无论是用户刚进入new_topic 页面还是提交的表
单数据无效,这些代码都将执行。用户提交的表单数据无效
时,将显示一些默认的错误消息,帮助用户提供有效的数据。

5.模板 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 %}

这个模板继承了base.html,因此其基本结构与项目“学习笔
记”的其他页面相同。在❶处,定义了一个HTML表单。实参
action 告诉服务器将提交的表单数据发送到哪里。这里将它
发回给视图函数new_topic() 。实参method 让浏览器以
POST请求的方式提交数据。
Django使用模板标签{% csrf_token %} (见❷)来防止攻击
者利用表单来获得对服务器未经授权的访问(这种攻击称为跨
站请求伪造 )。❸处显示表单,从中可知Django使得完成显
示表单等任务有多简单:只需包含模板变量{{ form.as_p
}} ,就可让Django自动创建显示表单所需的全部字段。修饰
符as_p 让Django以段落格式渲染所有表单元素,这是一种整
洁地显示表单的简单方式。
Django不会为表单创建提交按钮,因此我们在❹处定义了一
个。

6.链接到页面new_topic
topics.html

{% extends "learning_logs/base.html" %}

{% block content %}

  <p>Topics</p>

  <ul>
    {% for topic in topics %}
       <li>
		<a href="{% url 'learning_logs:topic' topic.id %}">{{topic}}</a>
	   </li>
    {% empty %}  
       <li>No topics have been added yet.</li>
    {% endfor %} 
  </ul>
  
  <a href="{% url 'learning_logs:new_topic' %}">Add a new topic</a>
  
{% endblock content %}

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

from django import forms

from .models import Topic,Entry

class TopicForm(forms.ModelForm):#模块TopicForm继承forms.ModelForm
    class Meta:
        model = Topic #根据模型Topic创建表单
        fields = ['text']
        labels = {'text':''}#对字段text不生成标签
        
class EntryForm(forms.ModelForm):
    class Meta:
        model = Entry
        fields = ['text']
        labels = {'text':' '}
        widgets = {'text':forms.Textarea(attrs={'cols'/:80})}
        

2.URL模式new_entry
urls.py

#learning_logs/urls.py
from django.urls import path#导入path用于映射url到视图

from . import views#.:从当前文件夹导入views.py

app_name = 'learning_logs'
urlpatterns = [
    #主页
    path('',views.index,name='index'),#指定django要调用index函数
    #显示所有主题
    path('topics/',views.topics, name='topics'),
    #特定主题的详细页面
    path('topics/<int:topic_id>/',views.topic,name='topic'),
    #用于添加新主题的页面
    path('new_topic/',views.new_topic,name='new_topic'),
    #用于添加新条目的标签
    path('new_entry/<int:topic_id>/',views.new_entry,name='new_entry'),
    ]


app_name = 'learning_logs'

3.视图函数new_entry()

from django.shortcuts import render,redirect

from .models import Topic
from .forms import TopicForm,EntryForm

def index(request):
    return render(request, 'learning_logs/index.html')

def topics(request):
    topics = Topic.objects.order_by('date_added')
    context = {'topics': topics}    
    return render(request, 'learning_logs/topics.html', context)
    
def topic(request,topic_id):
    """显示单个主题及其所有的条目"""
    topic = Topic.objects.get(id=topic_id)
    entries = topic.entry_set.order_by('-date_added')
    context = {'topic':topic,'entries':entries}
    return render(request,'learning_logs/topic.html',context)
    
def new_topic(request):
    """添加新表单"""
    if request.method != 'POST':#请求方法为POST
        #未提交数据:创建一个新表单实例
        form = TopicForm()
    else:
        #POST提交的数据,对数据进行处理
        form = TopicForm(data=request.POST)
        if form.is_valid():
            form.save()
            return redirect('learning_logs:topics')
     #显示空表单或指出表单数据无效
    context = {'form':form}
    return render(request,'learning_logs/new_topic.html',context)
    
def new_entry(request,topic_id):
    """在特定主题添加新条目"""
    topic = Topic.objects.get(id=topic_id)
    
    if request.method != 'POST':
        #为提交数据:创建一个空表单
        form = EntryForm()
    else:
        #POST提交的数据:对数据进行处理
        form =  EntryForm(data=request.POST)
        if form.is_valid():
            new_entry = form.save(commit=False)
            new_entry.topic = topic
            new_entry.save()
            return redirect('learning_logs:topic',topic_id=topic_id)
            
    #显示空表单或指出表单数据无效
    context ={'topic':topic,'form':form}
    return render(request,'learning_logs/new_entry.html',context)

4.模板new-entry

{% extends "learnings_logs/base.html" %}

{% block content %}
	<p><a href="{% url 'learnings_logs:topic' topic.id %}">{{ topic }}</a></p>

	<p>Add a new entry:</p>
	<form action="{% url 'learnings_logs:new_entry' topic.id %}"method='post'>
		{% csrf_token %}
		{{ form.as_p }}
		<button name='submit'>Add entry</button>
	</form>

{% endlock content %}

5.链接到页面new_entry

{% 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>
  {% for entry in entries %}
    <li>
      <p>{{ entry.date_added|date:'M d, Y H:i' }}</p>
      <p>{{ entry.text|linebreaks }}</p>
      <p>
        <a href="{% url 'learning_logs:edit_entry' entry.id %}">Edit entry</a>
      </p>
    </li>
  {% empty %}
    <li>There are no entries for this topic yet.</li>
  {% endfor %}
  </ul>

{% endblock content %}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值