Django项目——使用表单添加一个主题的条目

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/chengqiuming/article/details/84727803

一 代码

1 learning_logs/forms.py

# -*- coding: utf-8 -*-
# 导入模块 forms 以及要使用的模型 Topic,Entry
from django import forms

from .models import Topic, Entry

'''
定义了一个名为 TopicForm 的类,它继承了 forms.ModelForm
最简单的 ModelForm 版本只包含一个内嵌的 Meta 类,它告诉 Django 根据哪个模型创建表单,以及在表单中包含哪些字段。
根据模型 Topic 创建一个表单,该表单只包含字段 text
'''
class TopicForm(forms.ModelForm):
    class Meta:
        model = Topic
        fields = ['text']
        # 让 Django 不要为字段 text 生成标签。
        labels = {'text': ''}

class EntryForm(forms.ModelForm):
    class Meta:
        model = Entry
        fields = ['text']
        # 这里也给字段 'text' 指定了一个空标签
        labels = {'text': ''}
        # 通过设置属性 widgets ,可覆盖 Django 选择的默认小部件。
        # 通过让 Django 使用 forms.Textarea ,我们定制了字段 'text' 的输入小部件,将文本区域的宽度设置为 80 列,而不是默认的 40 列。
        # 这给用户提供了足够的空间,可以编写有意义的条目。
        widgets = {'text': forms.Textarea(attrs={'cols': 80})}

2 learning_logs/urls.py

# -*- coding: utf-8 -*-

from django.conf.urls import url

from . import views

urlpatterns = [
    url(r'^$', views.index, name='index'),
    url(r'^topics/$', views.topics, name='topics'),
    url(r'^topics/(?P<topic_id>\d+)/$', views.topic, name='topic'),
    
    # 用于添加新主题的网页
    # 该URL 模式将请求交给视图函数 new_topic()
    url(r'^new_topic/$', views.new_topic, name='new_topic'),

    # 用于添加新条目的页面
    # 这个 URL 模式与形式为 http://localhost:8000/new_entry/ id / 的 URL 匹配,其中 id  是一个与主题 ID 匹配的数字。
    # 代码 (?P<topic_id>\d+) 捕获一个数字值,并将其存储在变量 topic_id 中。
    # 请求的 URL 与这个模式匹配时, Django 将请求和主题 ID 发送给函数 new_entry() 。
    url(r'^new_entry/(?P<topic_id>\d+)/$', views.new_entry, name='new_entry'),
    
    # Page for editing an entry.
    url(r'^edit_entry/(?P<entry_id>\d+)/$', views.edit_entry,
        name='edit_entry'),
]

3 learning_logs/views.py

# -*- coding: utf-8 -*-
from django.shortcuts import render
from django.http import HttpResponseRedirect, Http404
from django.core.urlresolvers import reverse
from django.contrib.auth.decorators import login_required

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

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

def topics(request):
    topics = Topic.objects.filter(owner=request.user).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)
    # Make sure the topic belongs to the current user.
    if topic.owner != request.user:
        raise Http404
        
    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 提交的数据 , 对数据进行处理
        # HttpResponseRedirect 类,用户提交主题后我们将使用这个类将用户重定向到网页 topics 。
        # 函数 reverse() 根据指定的 URL 模型确定 URL ,这意味着 Django将在页面被请求时生成 URL 。
        # 我们还导入了刚才创建的表单 TopicForm 。
        # 我们使用用户输入的数据(它们存储在 request.POST 中)创建一个 TopicForm 实例
        # 这样对象 form 将包含用户提交的信息。
        form = TopicForm(request.POST)
        # 函数 is_valid() 核实用户填写了所有必不可少的字段(表单字段默认都是必不可少的),
        # 且输入的数据与要求的字段类型一致(例如,字段 text 少于 200 个字符)。
        # 这种自动验证避免了我们去做大量的工作。
        if form.is_valid():
            new_topic = form.save(commit=False)
            new_topic.owner = request.user
            # 将表单中的数据写入数据库
            new_topic.save()
            # 使用 reverse() 获取页面 topics 的 URL ,并将其传递给 HttpResponseRedirect()
            # 后者将用户的浏览器重定向到页面 topics 。
            # 在页面 topics 中,用户将在主题列表中看到他刚输入的主题。
            return HttpResponseRedirect(reverse('learning_logs:topics'))

    context = {'form': form}
    return render(request, 'learning_logs/new_topic.html', context)


def new_entry(request, topic_id):
    """ 在特定的主题中添加新条目 """
    # 形参 topic_id ,用于存储从 URL 中获得的值。渲染页面以及处理表单数据时,都
    # 需要知道针对的是哪个主题,因此我们使用 topic_id 来获得正确的主题。
    topic = Topic.objects.get(id=topic_id)
    if topic.owner != request.user:
        raise Http404
    
    if request.method != 'POST':
        # 未提交数据 , 创建一个空表单
        form = EntryForm()        
    else:
        # POST 提交的数据 , 对数据进行处理
        form = EntryForm(data=request.POST)
        if form.is_valid():
            # 让 Django 创建一个新的条目对象,并将其存储到 new_entry 中,但不将它保存到数据库中。
            new_entry = form.save(commit=False)
            # 设置条目对象的属性 topic ,再将条目对象保存到数据库。
            new_entry.topic = topic
            new_entry.save()
            # 调用 reverse() 时,需要提供两个实参:要根据它来生成 URL 的 URL 模式的名称;
            # 列表 args ,其中包含要包含在 URL 中的所有实参。在这里,列表 args 只有一个元素 —— topic_id 。
            # 接下来,调用 HttpResponseRedirect() 将用户重定向到显示新增条目所属主题的页面,用户将在该页面的
            # 条目列表中看到新添加的条目。
            return HttpResponseRedirect(reverse('learning_logs:topic',
                                        args=[topic_id]))
    
    context = {'topic': topic, 'form': form}
    return render(request, 'learning_logs/new_entry.html', context)

4 learning_logs/templates/learning_logs/new_entry.html

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

{% block content %}

  <p><a href="{% url 'learning_logs:topic' topic.id %}">{{ topic }}</a></p>
    
  <p>添加新条目</p>
  <form action="{% url 'learning_logs:new_entry' topic.id %}" method='post'>
    {% csrf_token %}
    {{ form.as_p }}
    <button name='submit'>添加新条目</button>
  </form>
    
{% endblock content %}

5 learning_logs/templates/learning_logs/topic.html

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

{% block content %}

  <p>主题: {{ topic }}</p>

  <p>条目:</p>
  <p>
      <!---显示条目前添加链接,因为在这种页面中,执行的最常见的操作是添加新条目。-->
      <a href="{% url 'learning_logs:new_entry' topic.id %}">添加新条目</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 %}">编辑新条目</a>
      </p>
    </li>
  {% empty %}
    <li>
      There are no entries for this topic yet.
    </li>
  {% endfor %}
  </ul>

{% endblock content %}

二 测试

猜你喜欢

转载自blog.csdn.net/chengqiuming/article/details/84727803