Django学习笔记3用ModelForm创建基于表单的页面

xiaoxiao2021-02-28  34

用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 topic</button> </form> {% endblock content%}

{% csrf_token %}用来防止跨站请求伪造,form.as_p以段落的格式创建所有表格元素。

5.在topics页面添加链接到new_topic的链接 添加<a href="{% url 'learning_logs:new_topic' %}">Add a new topic:</a>即可

在一个特定主题下添加条目

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<topic_id>\d+)/', views.new_entry, name='new_entry')

匹配规则和re_path('topics/(?P<topic_id>\d+)/', views.topic, name='topic'),类似

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 entry</button> </form> {% endblock content %}

5.在显示特定主题的页面topic.html中添加链接到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> </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<entry_id>\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 changes</button> </form> {% endblock content %}

4.在显示特定主题的页面topic.html添加修改条目的链接

<p> <a href="{% url 'learning_logs:edit_entry' entry.id %}">edit entry</a> </p>

至此,完成修改条目功能。

转载请注明原文地址: https://www.6miu.com/read-2612558.html

最新回复(0)