天天看點

Django圖書管理系統(前端對資料庫的增删改查)

圖書管理系統

出版社的管理

 源碼位置:https://gitee.com/machangwei-8/learning_materials/tree/master/%E9%A1%B9%E7%9B%AE/bookmanager

1.設計URL

urlpatterns = [
  url(r'^publisher_list/', views.publisher_list),
]      

1.1環境準備

建立項目bookmanager。app名字修改成對應的。

Django圖書管理系統(前端對資料庫的增删改查)
Django圖書管理系統(前端對資料庫的增删改查)

settings

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) #項目目錄      
DEBUG = True  #debug模式,測試的時候使用true      

 建立資料庫: create database bookmanager;

#settings.py設定資料庫配置
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'bookmanager',
        'HOST':'127.0.0.1',
        'PORT':3306,
        'USER':'root',
        'PASSWORD':'123',
    }
}

#init中使用pymysql
import pymysql
pymysql.install_as_MySQLdb()

#models.py中建立表
from django.db import models

# Create your models here.
class Publisher(models.Model):
    pid=models.AutoField(primary_key=True) #修改主鍵名字,使用自己建立的主鍵
    name=models.CharField(max_length=32)      

 剛剛配置将USER配置成了USR,導緻執行makegrations報錯:

Django圖書管理系統(前端對資料庫的增删改查)

遷移檔案生成:

Django圖書管理系統(前端對資料庫的增删改查)

遷移檔案中生成表名,字段名等:

Django圖書管理系統(前端對資料庫的增删改查)

再添加一個字段。它提示添加個預設值或者退出:

Django圖書管理系統(前端對資料庫的增删改查)

退出後,添加預設值再操作,添加字段,出錯

Django圖書管理系統(前端對資料庫的增删改查)
Django圖書管理系統(前端對資料庫的增删改查)

最終執行的遷移檔案是這個内容,我再這裡面添加一下這個字段:

Django圖書管理系統(前端對資料庫的增删改查)

然後再models裡面添加這個,相當于一開始就在models裡加了這個字段然後執行了makegragions。這樣表裡的内容和遷移檔案對應上了。

Django圖書管理系統(前端對資料庫的增删改查)
Django圖書管理系統(前端對資料庫的增删改查)

似乎執行改變了一次就生成一個檔案:

Django圖書管理系統(前端對資料庫的增删改查)

剛才出問題了,将這些删掉,再執行試試。

Django圖書管理系統(前端對資料庫的增删改查)

生成資料庫表:

Django圖書管理系統(前端對資料庫的增删改查)

添加并上傳:

Django圖書管理系統(前端對資料庫的增删改查)

展示出版社,設定url

from app01 import views
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^publisher_list/', views.publisher_list),
]      
def publisher_list(request):
    #顯示一個含出版社資訊的頁面
    return render(request,'publisher_list.html')      
Django圖書管理系統(前端對資料庫的增删改查)
Django圖書管理系統(前端對資料庫的增删改查)
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>魔降風雲變</title>
</head>
<body>
    <h1>出版社清單</h1>
</body>
</html>      

publisher_list.html

Django圖書管理系統(前端對資料庫的增删改查)

這樣就拿到頁面了,但是還要展示出資料庫中的資料。

渲染資料庫的資料,将資料以表格形式顯示出來:

from app01 import models
#展示出版社
def publisher_list(request):
    # 從資料庫中查詢到出版社的資訊
    all_publishers = models.Publisher.objects.all()
    return render(request, 'publisher_list.html', {'all_publishers': all_publishers}) #publisher_list.html中使用的是字典中的鍵,鍵代替這個所有的對象
#render方法也可以傳{鍵值對},在html模闆檔案中使用鍵對傳入的值進行操作。      

HTML頁面我們可以寫死了,但是我們需要的是根據資料庫的内容展示出來,用模闆渲染出來。

在函數中傳進來的是對象清單。每一個都是對象,是表中一行資料:

Django圖書管理系統(前端對資料庫的增删改查)

每行資料庫的内容顯示在網頁,使用pk,那麼無論主鍵是啥名字,都可以用pk代替

Django圖書管理系統(前端對資料庫的增删改查)

給表格加個邊框:

Django圖書管理系統(前端對資料庫的增删改查)

添加序号列:forloop.counter,從字典中每循環一次就計數一次,這樣就讓每行内容有個序号。而我們隻需要将模闆變量傳進去,用固定文法操作。

Django圖書管理系統(前端對資料庫的增删改查)

2.寫函數

from django.shortcuts import render

from app01 import models

# 展示出版社

def publisher_list(request):

  # 從資料庫中查詢到出版社的資訊

  all_publishers = models.Publisher.objects.all()

  # 傳回一個包含出版社資訊的頁面

  return render(request, 'publisher_list.html', {'all_publishers': all_publishers})

 過程放在1裡面了

3.寫模闆

<table border="1">
    <thead>
    <tr>
        <th>序号</th>
        <th>ID</th>
        <th>名稱</th>
    </tr>
    </thead>
    <tbody>

    {% for publisher in all_publishers %}
        <tr>
            <td>{{ forloop.counter }}</td>
            <td>{{ publisher.pk }}</td>
            <td>{{ publisher.name }}</td>
        </tr>
    {% endfor %}

    </tbody>
</table>      

3.1、新增

obj = models.Publisher.objects.create(name=publisher_name)      

 新增功能的效果:出版社清單頁面中一個按鈕,點選跳轉頁面。這個頁面中輸入出版社的相關資訊(出版社名稱),有個按鈕送出資訊,背景要把輸入的資訊插入到資料庫當中。插入之後浏覽器需要再跳轉到出版社清單頁面。

這個按鈕直接是個a标簽就可以。也就是我在出版社清單中有個a标簽,點選跳轉頁面add_publisher,裡面要有form表單。

Django圖書管理系統(前端對資料庫的增删改查)
Django圖書管理系統(前端對資料庫的增删改查)

添加url,點選views跳轉進入寫函數:

Django圖書管理系統(前端對資料庫的增删改查)

寫出添加資料庫記錄的頁面:這樣在框中輸入資料,背景将資料擷取到并寫入資料庫中

Django圖書管理系統(前端對資料庫的增删改查)

 2處理的原理如下1處:

Django圖書管理系統(前端對資料庫的增删改查)
Django圖書管理系統(前端對資料庫的增删改查)

 擷取出版社的名稱:是擷取這個送出請求的name,獲得post請求鍵值對中的值

Django圖書管理系統(前端對資料庫的增删改查)

# 使用ORM将資料插入到資料庫中,将擷取到的要添加的出版社名稱建立一個字段是輸入名稱的資料表記錄。pid不用寫,因為是自增

Django圖書管理系統(前端對資料庫的增删改查)

1處的請求2處沒有擷取到,然後後面的name=None,這樣前端3處跳轉報錯(1048, "Column 'name' cannot be null")

Django圖書管理系統(前端對資料庫的增删改查)

 上面的報錯的原因是1處get的名字與2處不一緻,所有沒有擷取到post送出的值,那麼1處的變量就是None。解決方法,将它們改為一緻,我将模闆檔案的2處改為publisher_name。

下面我做的操作是在3處寫入‘小馬出版社’,點選送出之後,5處不變,重新進入模闆檔案的頁面。可看函數,函數中無論GET或者POST請求都是傳回的同樣的頁面。然後再看

4處資料庫,函數拿到了我們送出的資料并在資料庫中已經建立了這條記錄。

Django圖書管理系統(前端對資料庫的增删改查)

網頁送出‘小馬過河2出版社’,建立一條資料,傳回的是這個類的對象,就是那個資料表的一條記錄。可以通過建立一行資料時的傳回值取出這行資料的各個字段的内容。

Django圖書管理系統(前端對資料庫的增删改查)

我們需要的是當我們從添加出版社的頁面送出添加之後,那麼頁面跳轉檢視所有出版社的頁面,這樣能看到新添加的出版社。那麼使用重定向:

看下圖,在add_publisher頁面中添加進一行資料後,直接跳轉到publisher_list頁面并顯示新添加的一條記錄‘小熊出版社’。

Django圖書管理系統(前端對資料庫的增删改查)

添加資料頁面可以通過添加後進入展示所有資料的頁面,但是展示表中所有記錄的頁面還沒有進入添加資料的頁面,那麼在展示表中所有記錄的頁面添加一個a标簽讓它跳轉到新增資料的頁面即可,如下圖

此處的a标簽位址應寫成路徑,在url路由中能找到,這裡實作了點選新增進入添加資料的頁面,添加資料又能傳回這裡的展示頁面。新增a标簽的跳轉實際上是點選之後又發送了一次get請求。

Django圖書管理系統(前端對資料庫的增删改查)

我現在添加一個重複的出版社名稱,它會添加記錄到資料庫中, 

Django圖書管理系統(前端對資料庫的增删改查)

出版社名字不應該重複的,下面就把這個字段設定成唯一鍵,然後執行資料遷移的那兩條指令結果報錯,原因是資料庫中已經有重複的資料了‘小熊出版社’。

django.db.utils.IntegrityError: (1062, "Duplicate entry '小熊出版社' for key 'app01_publisher_name_36f04192_uniq'")

Django圖書管理系統(前端對資料庫的增删改查)

pycharm中将這條資料删除掉并送出

Django圖書管理系統(前端對資料庫的增删改查)

然後執行那兩條資料遷移的指令,成功修改這個字段為唯一鍵:

Django圖書管理系統(前端對資料庫的增删改查)

既然這個字段已經是唯一鍵了,那麼我在頁面添加資料庫中已經有的這個字段内容,那麼報錯如下:

(1062, "Duplicate entry '小熊出版社' for key 'app01_publisher_name_36f04192_uniq'")      
Django圖書管理系統(前端對資料庫的增删改查)

資料庫有限制,我應該在資料庫插入之前,就進行判斷有沒有這個資料,而不是直接就往資料裡面插入資料

這裡添加了判斷條件之後還是報錯頁面,原因是,我們應該在資料插入之前就判斷是否存在相同的字段内容

Django圖書管理系統(前端對資料庫的增删改查)

 1處插入資料前判斷是否有相同的,有就傳進error資訊到,然後在傳回的原網頁後面渲染上錯誤提示資訊(2處)。這樣同名的資料插入網頁會提示已存在的提示

Django圖書管理系統(前端對資料庫的增删改查)

如果我不寫内容直接點選送出

Django圖書管理系統(前端對資料庫的增删改查)

出現了一條空資料,這顯然不是我們想要的,所有我們需要在這個的函數上做判斷,如果擷取的值為空,那麼傳回這個頁面,并在輸入框後面渲染不能輸入為空的錯誤提示

 這裡顯示為已存在,剛剛我在裡面插入了一個空的資料,現在将它删除掉

Django圖書管理系統(前端對資料庫的增删改查)
Django圖書管理系統(前端對資料庫的增删改查)

現在顯示的是不能為空了,一開始error不是這個資訊,到了不能為空這裡,又被覆寫了一次。

Django圖書管理系統(前端對資料庫的增删改查)

看下面的代碼,有三個render

Django圖書管理系統(前端對資料庫的增删改查)

我想要将三個render簡化成一個:

1)我可以最後傳回一個render,其它的隻是指派error變量。然後render的頁面裡渲染不同的error值。如果沒有錯誤即預設error是空字元串就可以。

2)然後判斷error資訊是否非假(即非空),非假才執行建立資料記錄的操作并重定向頁面到檢視所有出版社資料資訊的頁面

當設定了一個error是空字元串的時候,正常傳回的頁面是沒有顯示内容的。這樣雖然函數的結構修改了,但是功能沒有改變

Django圖書管理系統(前端對資料庫的增删改查)
Django圖書管理系統(前端對資料庫的增删改查)
Django圖書管理系統(前端對資料庫的增删改查)
def add_publisher(request):
    error=''
    #傳回一個包含from表單的出版社頁面
    if request.method=='POST':
        publish_name=request.POST.get('publisher_name')
        # 判斷出版社名稱是否有重複的
        if models.Publisher.objects.filter(name=publish_name):
            error='出版社名稱已存在'
        #判斷輸入值是否為空
        if not publish_name:
           error="輸入不能為空"
        if not error:
            obj=models.Publisher.objects.create(name=publish_name)
            #跳轉到展示出版社的頁面
            return redirect('/publisher_list/')
    return render(request,'add_publisher.html',{'error':error})      

add_publisher

但是還是有個問題,就是取出來的資料id是亂序的

Django圖書管理系統(前端對資料庫的增删改查)

 這是因為publiser_list這一頁的get請求出來的資料沒有排序,将從資料庫中取出來的所有資料給個排序就解決了

Django圖書管理系統(前端對資料庫的增删改查)
Django圖書管理系統(前端對資料庫的增删改查)

3.2、删除

obj_list = models.Publisher.objects.filter(pk=pk)
obj_list.delete()

obj = models.Publisher.objects.get(pk=pk)
obj.delete()      

 想要删除某一條記錄,應該做什麼樣的操作呢?那麼在名稱列後面有個按鈕或者a标簽,點選它就删除掉這條記錄,這樣是可以的吧。

Django圖書管理系統(前端對資料庫的增删改查)

那麼在展示頁中後面添加一列,使用a标簽

Django圖書管理系統(前端對資料庫的增删改查)

現在應該是我點選一個删除,然後發送一個請求 ,并在後端資料庫将這條資料删除,删除之後再跳轉到這個頁面

先設計删除url,建立删除函數,删除函數邏輯如下;

Django圖書管理系統(前端對資料庫的增删改查)

如果我的函數中有一處存在錯誤,可能所有函數對應的網頁都不能通路:檢查元素加載失敗

Django圖書管理系統(前端對資料庫的增删改查)

給删除a标簽設定一個位址,已經實作點選删除通路這個路徑了

Django圖書管理系統(前端對資料庫的增删改查)

但是點選删除的是哪條記錄,我需要擷取到才能在背景将這條記錄删除掉。于是将它的跳轉路徑拼接一個這條記錄的主鍵id

Django圖書管理系統(前端對資料庫的增删改查)

 删除代碼:

Django圖書管理系統(前端對資料庫的增删改查)
Django圖書管理系統(前端對資料庫的增删改查)

點選删除:

Django圖書管理系統(前端對資料庫的增删改查)

 這時候我是點選删除按鈕删的,我也可能使用浏覽器通路位址進行删除

Django圖書管理系統(前端對資料庫的增删改查)

id=15的已删除:

Django圖書管理系統(前端對資料庫的增删改查)

如果自己拼接在浏覽器位址欄通路請求不存在的記錄:報錯:Publisher matching query does not exist.

Django圖書管理系統(前端對資料庫的增删改查)

那麼我應該對這種情況做個判斷,因為是get擷取資料的,get不到就會顯示錯誤,那麼将get改為過濾

Django圖書管理系統(前端對資料庫的增删改查)

過濾出來可能多條記錄,也可以對queryset 這個對象清單裡的對象批量删除

Django圖書管理系統(前端對資料庫的增删改查)
Django圖書管理系統(前端對資料庫的增删改查)
Django圖書管理系統(前端對資料庫的增删改查)
def del_publisher(request):
    # 擷取要删除的資料
    pk = request.GET.get('id')
    obj_list = models.Publisher.objects.filter(pk=pk)
    if not obj_list:
        # 沒有要删除的資料
        return HttpResponse('要删除的資料不存在')
    # 删除該資料
    # obj.delete()
    obj_list.delete()
    # 跳轉到展示頁面
    return redirect('/publisher_list/')      

删除功能代碼

3.3、編輯(修改資料)

obj.name = publisher_name
obj.save() # 儲存資料到資料庫中      

想要進行編輯的話應該是什麼樣的過程。點選編輯a标簽之後可以跳轉到編輯頁面,這個編輯頁面包含了你要編輯的那條資料,直接在這上面進行修改,修改完了之後送出,背景修改了之後跳轉回來到所有出版社展示頁

建立url,建立函數,将編輯标簽和删除标簽寫在同一列

Django圖書管理系統(前端對資料庫的增删改查)
Django圖書管理系統(前端對資料庫的增删改查)
Django圖書管理系統(前端對資料庫的增删改查)

點選其中一個頁面往這個位址發送請求了,并且根據id擷取到了是哪條資料需要編輯

Django圖書管理系統(前端對資料庫的增删改查)

應該傳回一個頁面,這個頁面中包含點選編輯的那條原始資料。編輯頁面和添加頁面差不多。

 編輯的頁面這樣的話麼有帶上id=2這條資料的name

Django圖書管理系統(前端對資料庫的增删改查)
Django圖書管理系統(前端對資料庫的增删改查)

因為編輯按鈕a标簽跳轉的時候帶着對應資料的id,那麼由此獲得這條資料并将它的内容name預設填入到編輯的input标簽裡

通過點選編輯按鈕傳到請求裡的id查出滿足條件的資料庫記錄,并傳到html模闆檔案中進行調用其中的值進行渲染。使得編輯框裡顯示要編輯的原資料内容      
Django圖書管理系統(前端對資料庫的增删改查)

如圖,點選這個id的就顯示出來要編輯的原資料。編輯的展示這樣就沒有問題

Django圖書管理系統(前端對資料庫的增删改查)

下面點選送出,要進行以下的邏輯操作:

Django圖書管理系統(前端對資料庫的增删改查)

要修改id=2的資料:由于發送POST請求之前,也要擷取到obj對象,所有把POST請求處理放在後面

Django圖書管理系統(前端對資料庫的增删改查)
Django圖書管理系統(前端對資料庫的增删改查)

 現在需要将可能遇到的問題寫上。傳進錯誤資訊進行渲染

Django圖書管理系統(前端對資料庫的增删改查)

寫這些功能先寫正常的情況下,然後再考慮會出現的問題。

4、項目目錄結構

Django圖書管理系統(前端對資料庫的增删改查)
Django圖書管理系統(前端對資料庫的增删改查)
Django圖書管理系統(前端對資料庫的增删改查)
from django.shortcuts import render, redirect, HttpResponse
from app01 import models


# 展示出版社
def publisher_list(request):
    # 從資料庫中查詢到出版社的資訊
    all_publishers = models.Publisher.objects.all().order_by('pk')
    # 傳回一個包含出版社資訊的頁面
    return render(request, 'publisher_list.html', {'all_publishers': all_publishers}) 


# 新增出版社
def add_publisher(request):
    # 對請求方式進行判斷
    if request.method == 'POST':
        # 處理POST請求
        # 擷取到出版社的名稱
        publisher_name = request.POST.get('publisher_name')
        # 判斷出版社名稱是否有重複的
        if models.Publisher.objects.filter(name=publisher_name):
            return render(request, 'add_publisher.html', {'error': '出版社名稱已存在'})
        # 判斷輸入的值是否為空
        if not publisher_name:
            return render(request, 'add_publisher.html', {'error': '不能輸入為空'})
        # 使用ORM将資料插入到資料庫中
        obj = models.Publisher.objects.create(name=publisher_name)
        # 跳轉到展示出版社的頁面
        return redirect('/publisher_list/')
    # 傳回一個包含form表單的頁面
    return render(request, 'add_publisher.html')


# 新增出版社
def add_publisher(request):
    error = ''
    # 對請求方式進行判斷
    if request.method == 'POST':
        # 處理POST請求
        # 擷取到出版社的名稱
        publisher_name = request.POST.get('publisher_name')
        # 判斷出版社名稱是否有重複的
        if models.Publisher.objects.filter(name=publisher_name):
            error = '出版社名稱已存在'
        # 判斷輸入的值是否為空
        if not publisher_name:
            error = '不能輸入為空'
        if not error:
            # 使用ORM将資料插入到資料庫中
            obj = models.Publisher.objects.create(name=publisher_name)
            # 跳轉到展示出版社的頁面
            return redirect('/publisher_list/')
    # 傳回一個包含form表單的頁面
    return render(request, 'add_publisher.html', {'error': error})


# 删除出版社
def del_publisher(request):
    # 擷取要删除的資料
    pk = request.GET.get('id')
    obj_list = models.Publisher.objects.filter(pk=pk)
    if not obj_list:
        # 沒有要删除的資料
        return HttpResponse('要删除的資料不存在')
    # 删除該資料
    # obj.delete()
    obj_list.delete()
    # 跳轉到展示頁面
    return redirect('/publisher_list/')


# 編輯出版社
def edit_publisher(request):
    error = ''
    # 查找要編輯的資料
    pk = request.GET.get('id')  # url上攜帶的參數  不是GET請求送出參數
    obj_list = models.Publisher.objects.filter(pk=pk)
    if not obj_list:
        return HttpResponse('要編輯的資料不存在')

    obj = obj_list[0]

    if request.method == 'POST':
        # 處理POST請求
        # 擷取新送出的出版的名稱
        publisher_name = request.POST.get('publisher_name')

        if models.Publisher.objects.filter(name=publisher_name):
            # 新修改的名稱已存在
            error = '新修改的名稱已存在'
        if obj.name == publisher_name:
            error = '名稱未修改'
        if not publisher_name:
            error = '名稱不能為空'

        if not error:
            # 修改資料
            obj.name = publisher_name
            obj.save()  # 儲存資料到資料庫中
            # 跳轉到出版社的展示頁面
            return redirect('/publisher_list/')

    # 傳回一個包含原始資料的頁面
    return render(request, 'edit_publisher.html', {'obj': obj,'error':error})      

參考代碼views