欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Web应用程序1.3——用户输入数据

程序员文章站 2022-03-23 13:13:10
...

一、添加新主题

首先让用户添加新主题,创建基于表单的方法几乎与前面创建网页一样,定义一个URL,编写一个视图函数并编写一个模板。

一个人主要差别是需要导入含表单的模块forms.py。

1.用于添加主题的表单

在Django中,创建表单最简单的方法是使用ModelForm。该表单只含字段text,并不要让字段生成标签。

forms.py

from django import forms

from .models import Topic

class TopicForm(forms.ModelForm):
	class Meta:
		model=Topic
		fields=['text']
		labels={'text':''}

2.URL模式new_topic

urls.py


urlpatterns=[
   --snip
    #用于添加新主题的网页
    url(r'^new_topic/$',views.new_topic,name='new_topic'),]

这个URL模式将请求交给视图函数new_topic()

3.视图函数new_topic()

views.py

from django.shortcuts import render
from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse

from .models import Topic
from .forms import TopicForm

--snip--
def new_topic(request):
	"""添加新主题"""
	if request.method!='POST':
		#未提交数据:创建一个新表单
		form=TopicForm()
	else:
		#POST提交的数据,对数据进行处理
		form=TopicForm(request.POST)
		if form.is_valid():
			form.save()
			return HttpResponseRedirect(reverse('learning_logs:topics'))
			
	context={'form':form}
	return render(request,'learning_logs/new_topic.html',context)

    我们导入了HttpResponseRedirect类,用户提交主题后我们将使用这个类将用户重定向到网页topics。函数reverse()根据指定的URL模型确定URL,这意味着Django将在页面被请求是生成URL。

4.GET请求和POST请求
    创建Wed应用程序时,主要有两种请求:GET请求和POST请求。对于只从服务器读取数据的页面,使用GET请求;在用户需要通过表单提交信息时,通常使用POST请求。
    new_topic()将请求对象作为参数,用户初次请求该网页时,其浏览器发送GET请求,用户填写并提交表单时,其浏览器发送POST请求。如果是POST请求,我们先通过检查确定它们是否有效的。如果有效,save()方法保存到数据库保存页面,就可以离开这个页面了,在页面topics中,用户将在主题列表中看到刚输入的主题。

5.模板new_topic

new_topic.html

{% 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 %}来防止攻击者利用表单来获得对服务器未经授权的访问。{{form.as_p}}可以让Django自动创建显示表单所需的全部字段,修饰符as_p让Django以段落的格式渲染所有表单元素。

6.链接到页面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 %}

由于添加新主题的页面

Web应用程序1.3——用户输入数据

二、添加新条目

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

我们创建一个与模型Entry相关联的表单。

forms.py

from django import forms

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

新类EntryForm继承了forms.ModelForm。我们定义了属性widgets,小部件(widget)是一个HTML表单元素,如单行文本框、多行文本区域或下拉列表。通过设置属性widgets,可覆盖Django选择的默认小部件。通过让Django使用froms.Textarea,我们定制了字段‘text’的输入小部件,将文本区域的宽度设置为80列,而不是默认的40列。

2.URL模式new_entry

在用于添加新条目的页面的URL模式中,需要包含实参topic_id,因为条目必须与特定的主题相关联。

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<topic_id>\d+)捕获一个数字值,并将其储存在变量topic_id中。请求的URL与这个模式匹配时,Django将请求和主题ID发送给函数new_entry()

3.视图函数new_entry()

views.py

from django.shortcuts import render
--snip--

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

--snip--
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 HttpResponseRedirect(reverse('learning_logs:topic',
			                            args=[topic_id]))
			
	context={'topic':topic,'form':form}
	return render(request,'learning_logs/new_entry.html',context)

在调用save()时,我们传递了实参commit=False,让Django创建一个新的条目对象,并将其储存在new_entry中,但不将它保存在数据库中。

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>
  
  <p>Add a new entry:</p> 
  <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 %}

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>
  
{% endblock content %}

页面new_entry

Web应用程序1.3——用户输入数据

三、编辑条目

1.URL模式edit_entry

urls.py

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

2.视图函数edit_entry()

views.py

def edit_entry(request, entry_id):
	"""编辑既有条目"""
	entry = Entry.objects.get(id = entry_id) #获得用户要修改的条目对象和与该条目相关的主题
	topic = entry.topic
 
	if request.method != 'POST':
		""" 初次请求,使用当前条目填充表单"""
		form = EntryForm(instance = entry)
	else:
		""" POST提交的数据,对数据进行处理 """
		form = EntryForm(instance = entry, data = request.POST)
		if form.is_valid():
			form.save() 
			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)

3.模板edit_entry

edit_entry.html

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

{% block content %}

  <p><a href="{% url 'learning_logs:topic' topic.id %}">{{ topic }}</a></p>
  
  <p>Edit entry:</p> 
  <form action="{% url 'learning_logs:edit_entry' entry.id %}" method='post'>
	{% csrf_token %}
	{{ form.as_p }}
	<button name="submit">save changes</button>
  </form>
  
{% endblock content %}

4.链接到页面edit_entry

topic.html

--snip--
  {% 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>
 --snip--

每个条目都有一个用于对其进行编辑的链接

Web应用程序1.3——用户输入数据

相关标签: Django