1. 程式人生 > >Django專案——使用表單新增資料

Django專案——使用表單新增資料

一 程式碼 

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': ''}

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'),
]

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)

4 learning_logs/templates/learning_logs/new_topic.html

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

{% block content %}
  <p>新增新主題</p>

  <!--實參 action 告訴伺服器將提交的表單資料傳送到哪裡,這裡我們將它發回給檢視函式 new_topic() 。
      實參 method 讓瀏覽器以 POST 請求的方式提交資料。-->
  <form action="{% url 'learning_logs:new_topic' %}" method='post'>
    <!--來防止攻擊者利用表單來獲得對伺服器未經授權的訪問(這種攻擊被稱為 跨站請求偽造 )。-->
    {% csrf_token %}
    <!--顯示錶單,從中可知 Django 使得完成顯示錶單等任務有多簡單:
        我們只需包含模板變數 form.as_p ,就可讓 Django 自動建立顯示錶單所需的全部欄位。
        修飾符 as_p 讓 Django 以段落格式渲染所有表單元素,這是一種整潔地顯示錶單的簡單方式。-->
    {{ form.as_p }}
    <button name="submit">新增主題</button>
  </form>
    
{% endblock content %}

5 learning_logs/templates/learning_logs/topics.html

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

{% block content %}

  <p>學習筆記</p>

  <ul>
    {% for topic in topics %}
      <li>
        <a href="{% url 'learning_logs:topic' topic.id %}">{{ topic }}</a>
      </li>
    {% empty %}
      <li>No topics have been added yet.</li>
    {% endfor %}
  </ul>
  
  <a href="{% url 'learning_logs:new_topic' %}">新增主題</a>

{% endblock content %}

二 執行測試