Django專案——讓使用者擁有自己的資料
阿新 • • 發佈:2018-12-08
一 使用 @login_required 限制訪問
1 限制對 topics 頁面的訪問
learning_logs/views.py程式碼修改如下:
''' login_required() 的程式碼檢查使用者是否已登入,僅當用戶已登入時, Django 才執行 topics() 的程式碼。 如果使用者未登入,就重定向到登入頁面。 ''' @login_required def topics(request): ''' 使用者登入後, request 物件將有一個 user 屬性,這個屬性儲存了有關該使用者的資訊。 程式碼 Topic.objects.filter(owner=request.user) 讓 Django 只從資料庫中獲 取 owner 屬性為當前使用者的 Topic 物件。 ''' topics = Topic.objects.filter(owner=request.user).order_by('date_added') context = {'topics': topics} return render(request, 'learning_logs/topics.html', context)
2 settings.py中增加如下內容:
# 讓 Django 知道到哪裡去查詢登入頁面。
# 如果未登入的使用者請求裝飾器 @login_required 的保護頁面,
# Django 將重定向到 settings.py 中的 LOGIN_URL 指定的 URL
LOGIN_URL = '/users/login/'
二 將資料關聯到使用者
1 修改模型Topic
# -*- coding: utf-8 -*- from django.db import models # 匯入了 django.contrib.auth 中的模型 User from django.contrib.auth.models import User class Topic(models.Model): """ 使用者要學習的主題 """ text = models.CharField(max_length=200) date_added = models.DateTimeField(auto_now_add=True) # 在 Topic 中添加了欄位 owner ,它建立到模型 User 的外來鍵關係。 owner = models.ForeignKey(User) def __unicode__(self): """ 返回模型的字串表示 """ return self.text
三 只允許使用者訪問自己的主題
在 views.py 中,對函式 topics() 做如下修改: ''' login_required() 的程式碼檢查使用者是否已登入,僅當用戶已登入時, Django 才執行 topics() 的程式碼。 如果使用者未登入,就重定向到登入頁面。 ''' @login_required def topics(request): ''' 使用者登入後, request 物件將有一個 user 屬性,這個屬性儲存了有關該使用者的資訊。 程式碼 Topic.objects.filter(owner=request.user) 讓 Django 只從資料庫中獲 取 owner 屬性為當前使用者的 Topic 物件。 ''' topics = Topic.objects.filter(owner=request.user).order_by('date_added') context = {'topics': topics} return render(request, 'learning_logs/topics.html', context)
四 保護使用者的主題
1 修改views.py
@login_required
def topic(request, topic_id):
# 顯示單個主題及其所有的條目
topic = Topic.objects.get(id=topic_id)
# 確認請求的主題屬於當前使用者.收到主題請求後,在渲染網頁前檢查該主題是否屬於當前登入的使用者。
# 如果請求的主題不歸當前使用者所有,我們就引發 Http404 異常,讓 Django 返回一個 404 錯誤頁面。
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)
五 保護頁面 edit_entry
'''
頁面 edit_entry 收到 GET 請求時, edit_entry() 將返回一個表單,讓使用者能夠對條目進行編輯。
頁面收到 POST 請求(條目文字經過修訂)時,它將修改後的文字儲存到資料庫中
'''
@login_required
def edit_entry(request, entry_id):
""" 我們獲取使用者要修改的條目物件,以及與該條目相關聯的主題。在請求方法為 GET 時將執行的 if 程式碼塊中,我們使用實
參 instance=entry 建立一個 EntryForm 例項。
這個實參讓 Django 建立一個表單,並使用既有條目物件中的資訊填充它。使用者將看到既有的資料,並能夠編輯它們。
處理 POST 請求時,我們傳遞實參 instance=entry 和 data=request.POST ,讓 Django 根據既有條目物件建立一個表單例項,
並根據 request.POST 中的相關資料對其進行修改。然後,我們檢查表單是否有效,如果有效,就呼叫 save() ,且不指定任何實參。
接下來,我們重定向到顯示條目所屬主題的頁面,使用者將在其中看到其編輯的條目的新版本。"""
entry = Entry.objects.get(id=entry_id)
topic = entry.topic
# 然後檢查主題的所有者是否是當前登入的使用者,如果不是,就引發 Http404 異常。
if topic.owner != request.user:
raise Http404
if request.method != 'POST':
# 初次請求,使用當前條目填充表單
form = EntryForm(instance=entry)
else:
# POST 提交的資料,對資料進行處理
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)
六 將新主題關聯到當前使用者
@login_required
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():
# 首先呼叫 form.save() ,並傳遞實參 commit=False ,
# 這是因為我們先修改新主題,再將其儲存到資料庫中
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)
七 測試
使用者1的主題
使用者2的主題