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

用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\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 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/

Django学习笔记3 用ModelForm创建基于表单的页面_第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>

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

你可能感兴趣的:(web开发,python,Django)