用ModelForm创建基于表单的页面
之前创建了两个页面,分别是主页index、主题页topics和单个主题详情页topic,
下面,创建基于表单的页面,使得用户可以添加主题。
1.首先创建/learning_logs/forms.py
文件
from django import forms
# 从models.py导入Topic类
from .models import Topic
class TopicForm(forms.ModelForm): # TopicForm继承forms.ModelForm
class Meta:
model = Topic # 根据模型Topic创建表单model
fields = ['text'] # 表单只包含text字段
labels = {'text': ''} # 不要为labels生成标签
2.在/learning_logs/urls.py中添加:
# web page used to add new topics
path('new_topic/', views.new_topic, name='new_topic'),
这个规则匹配localhost:port/new_topic/
的访问,并且调用views.py
中的new_topic
函数,同时为该url命名为new_topic
3.创建视图函数new_topic()
首先要在原来的基础上import
以下:
from django.http import HttpResponseRedirect
from django.urls import reverse
from .forms import TopicForm
def new_topic(request):
"""add new topic"""
if request.method != 'POST':
# didn't submit data: create a new form
form = TopicForm # TopicForm is imported from ./form.py
else:
# data submitted through post: process the data
form = TopicForm(request.POST)
if form.is_valid():
form.save()
# redirect user to topics page
return HttpResponseRedirect(reverse('learning_logs:topics'))
context = {'form': form}
return render(request, 'learning_logs/new_topic.html', context)
如果请求!=POST,那么可能是GET请求;就创建一个新的表单,并且存放在上下文context
中,然后通过render返回给new_topic.html
,显示给用户一个空表单,
如果请求是POST,我们就要使用存储在request.POST中的用户填写的数据来创建一个TopicForm实例form,它包含了用户填写的信息,
通过form.is_valid()
可以检查信息的有效与否,然后存储到数据库。
接下来,可以离开页面,先用reverse来获取名称为topics
的页面的url,再重定向至topics
页面。
4.创建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 topicbutton>
form>
{% endblock content%}
{% csrf_token %}
用来防止跨站请求伪造,form.as_p
以段落的格式创建所有表格元素。
5.在topics
页面添加链接到new_topic
的链接
添加Add a new topic:
即可
在一个特定主题下添加条目
1.在form.py中添加类EntryForm
先import
from .models import Topic, Entry
class EntryForm(forms.ModelForm):
class Meta:
model = Entry
fields = ['text']
labels = {'text': ''}
widgets = {'text': forms.Textarea(attrs={'cols': 80})}
2.在urls.py中添加新规则
# web page used to add new entries
re_path('new_entry/(?P\d+)/' , views.new_entry, name='new_entry')
匹配规则和re_path('topics/(?P
类似
3.编写视图函数new_entry()
在views.py中添加:
from .forms import TopicForm, EntryForm
def new_entry(request, topic_id):
"""add a new entry in a specific topic"""
topic = Topic.objects.get(id=topic_id)
if request.method != 'POST':
# no data submitted; create a new form
form = EntryForm()
else:
# data submitted through post; process data
form = EntryForm(data=request.POST)
if form.is_valid():
# create a new entry instance,
# and store it in new_entry, but not in database yet(commit=False)
new_entry = form.save(commit=False)
# add topic attr & set it
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)
4.编写模板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 entrybutton>
form>
{% endblock content %}
5.在显示特定主题的页面topic.html中添加链接到new_entry的链接
{% extends 'learning_logs/base.html' %}
{% block content %}
<p>Topic: {{ topic }}p>
<p>Entriesp>
<p>
<a href="{% url 'learning_logs:new_entry' topic.id %}">add new entrya>
p>
<ul>
{% for entry in entries %}
<li>
<p>{{ entry.date_added|date:'M d, Y H:i' }}p>
<p>{{ entry.text|linebreaks }}p>
li>
{% empty %}
<li>
There are no entries for this topic yet.
li>
{% endfor %}
ul>
{% endblock content %}
访问 http://localhost/port/topics/1/
让用户能够编辑已有条目
1.在urls.py
中添加规则
re_path('edit_entry/(?P\d+)/' , views.edit_entry, name='edit_entry'),
2.创建视图函数edit_entry()
在views.py
中添加:
def edit_entry(request, entry_id):
"""edit an existing entry"""
entry = Entry.objects.get(id=entry_id)
topic = entry.topic
if request.method != 'POST':
# first request; fill the form with old info
form = EntryForm(instance=entry)
else:
# POST request; process the data
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)
注意上面的instance
这里首先传入data=request.POST
参数,这里是将用户的信息提交,而将用户信息提交到数据库中哪一行,则需要通过instance参数将对象entry传入,这样当用户更改信息后,点击提交则可以将更改后的信息保存到数据库中相应的行,如果没有instance参数,则会创建一条新的数据在数据库中.
3.创建模板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 changesbutton>
form>
{% endblock content %}
4.在显示特定主题的页面topic.html
添加修改条目的链接
<p>
<a href="{% url 'learning_logs:edit_entry' entry.id %}">edit entrya>
p>
至此,完成修改条目功能。