จุดเด่นของ Django: โมเดล ผู้ดูแลระบบ และการควบคุมฐานข้อมูลเชิงสัมพันธ์ (ตอนที่ 3)
เผยแพร่แล้ว: 2022-03-10ก่อนที่เราจะเริ่มต้น ฉันต้องการทราบว่าความสามารถในการดูแลระบบในตัวของ Django แม้จะปรับแต่งแล้ว ไม่ได้มีไว้สำหรับผู้ใช้ปลายทาง แผงผู้ดูแลระบบมีอยู่ในฐานะนักพัฒนา ผู้ปฏิบัติงาน และเครื่องมือผู้ดูแลระบบสำหรับการสร้างและบำรุงรักษาซอฟต์แวร์ ไม่ได้มีจุดประสงค์เพื่อใช้ให้ความสามารถในการกลั่นกรองผู้ใช้ปลายทาง หรือความสามารถอื่นๆ ของผู้ดูแลระบบบนแพลตฟอร์มที่คุณพัฒนา
บทความนี้มีพื้นฐานมาจากสมมติฐานในสองส่วน:
- แผงผู้ดูแลระบบ Django นั้นใช้งานง่ายมาก โดยพื้นฐานแล้วคุณรู้วิธีใช้งานอยู่แล้ว
- แผงผู้ดูแลระบบ Django มีประสิทธิภาพมากจนเราสามารถใช้เป็นเครื่องมือในการเรียนรู้เกี่ยวกับการแสดงข้อมูลในฐานข้อมูลเชิงสัมพันธ์โดยใช้โมเดล Django
ฉันเสนอแนวคิดเหล่านี้โดยมีข้อแม้ว่าเรายังต้องเขียนโค้ดการกำหนดค่าบางอย่างเพื่อเปิดใช้งานความสามารถที่มีประสิทธิภาพมากขึ้นของแผงผู้ดูแลระบบ และเรายังคงต้องใช้ ORM (การทำแผนที่เชิงวัตถุสัมพันธ์) ของ Django เพื่อระบุการแสดงข้อมูล ในระบบของเรา
การอ่านที่แนะนำ
“Django Highlights” เป็นชุดที่นำเสนอแนวคิดที่สำคัญของการพัฒนาเว็บใน Django คุณอาจต้องการอ่านเกี่ยวกับการจัดหาขั้นตอนการตรวจสอบสิทธิ์ผู้ใช้ที่ปลอดภัย และติดตามการสาธิตเกี่ยวกับการใช้เทมเพลต Django เพื่อเขียนหน้าที่ซับซ้อน
การตั้งค่า
เรากำลังจะดำเนินการกับโครงการตัวอย่างในบทความนี้ โครงการจำลองข้อมูลบางอย่างที่ห้องสมุดจะจัดเก็บเกี่ยวกับหนังสือและผู้อุปถัมภ์ ตัวอย่างควรใช้ได้กับระบบหลายประเภทที่จัดการผู้ใช้และ/หรือสินค้าคงคลัง ข้อมูลคร่าวๆ มีลักษณะดังนี้:
โปรดทำตามขั้นตอนต่อไปนี้เพื่อให้โค้ดตัวอย่างทำงานบนเครื่องของคุณ
1. การติดตั้งแพ็คเกจ
เมื่อติดตั้ง Python 3.6 ขึ้นไป ให้สร้างไดเร็กทอรีและสภาพแวดล้อมเสมือน จากนั้น ติดตั้งแพ็คเกจต่อไปนี้:
pip install django django-grappelli
Django เป็นเว็บเฟรมเวิร์กที่เรากำลังทำงานด้วยในบทความนี้ ( django-grappelli
เป็นธีมแผงผู้ดูแลระบบที่เราจะกล่าวถึงสั้น ๆ )
2. รับโครงการ
เมื่อติดตั้งแพ็คเกจก่อนหน้าแล้ว ให้ดาวน์โหลดโค้ดตัวอย่างจาก GitHub วิ่ง:
git clone https://github.com/philipkiely/library_records.git cd library_records/library
3. การสร้าง Superuser
ใช้คำสั่งต่อไปนี้ ตั้งค่าฐานข้อมูลของคุณและสร้าง superuser อินเทอร์เฟซบรรทัดคำสั่งจะแนะนำคุณตลอดขั้นตอนการสร้าง superuser บัญชีผู้ใช้ superuser ของคุณจะเป็นช่องทางให้คุณเข้าถึงแผงการดูแลระบบในทันที ดังนั้นอย่าลืมจำรหัสผ่านที่คุณตั้งไว้ ใช้:
python manage.py migrate python manage.py createsuperuser
4. กำลังโหลดข้อมูล
สำหรับการสำรวจของเรา ฉันได้สร้างชุดข้อมูลที่เรียกว่าฟิกซ์เจอร์ ซึ่งคุณสามารถโหลดลงในฐานข้อมูลได้ (เพิ่มเติมเกี่ยวกับวิธีการสร้างฟิกซ์เจอร์ที่ส่วนท้ายของบทความ) ใช้โปรแกรมติดตั้งเพื่อเติมฐานข้อมูลของคุณก่อนที่จะสำรวจในแผงการดูแลระบบ วิ่ง:
python manage.py loaddata ../fixture.json
5. การดำเนินโครงการตัวอย่าง
ในที่สุด คุณก็พร้อมที่จะรันโค้ดตัวอย่างแล้ว ในการรันเซิร์ฟเวอร์ ให้ใช้คำสั่งต่อไปนี้:
python manage.py runserver
เปิดเบราว์เซอร์ของคุณไปที่ https://127.0.0.1:8000 เพื่อดูโครงการ โปรดทราบว่าคุณจะถูกนำไปยังแผงการดูแลระบบที่ /admin/ โดยอัตโนมัติ ฉันทำสำเร็จด้วยการกำหนดค่าต่อไปนี้ใน library/urls.py :
from django.contrib import admin from django.urls import path from records import views urlpatterns = [ path('admin/', admin.site.urls), path('', views.index), ]
รวมกับการเปลี่ยนเส้นทางอย่างง่ายต่อไปนี้ใน records/views.py :
from django.http import HttpResponseRedirect def index(request): return HttpResponseRedirect('/admin/')
การใช้แผงการดูแลระบบ
เราทำได้! เมื่อคุณโหลดหน้าของคุณ คุณควรเห็นสิ่งต่อไปนี้:
มุมมองนี้ทำได้โดยใช้รหัสสำเร็จรูปต่อไปนี้ใน records/admin.py :
from django.contrib import admin from .models import Book, Patron, Copy admin.site.register(Book) admin.site.register(Copy) admin.site.register(Patron)
มุมมองนี้ควรให้ความเข้าใจเบื้องต้นเกี่ยวกับข้อมูลที่ระบบเก็บไว้แก่คุณ ฉันจะลบความลึกลับบางอย่างออก: Groups
และ Users
ถูกกำหนดโดย Django และจัดเก็บข้อมูลและการอนุญาตสำหรับบัญชีในระบบ คุณสามารถอ่านเพิ่มเติมเกี่ยวกับรูปแบบ User
ใช้ได้ในบทความก่อนหน้าในชุดนี้ Books
Copys
และ Patrons
คือตารางในฐานข้อมูลที่เราสร้างขึ้นเมื่อเรียกใช้การย้ายข้อมูลและเติมโดยการโหลดโปรแกรมติดตั้ง โปรดทราบว่า Django สร้างพหูพจน์ชื่อรุ่นอย่างไร้เดียงสาด้วยการเติม “s” ต่อท้าย แม้ในกรณีเช่น “สำเนา” ซึ่งสะกดผิด
ในโครงการของเรา Book
คือบันทึกที่มีชื่อหนังสือ ผู้แต่ง วันที่ตีพิมพ์ และ ISBN (หมายเลขหนังสือมาตรฐานสากล) ห้องสมุดเก็บรักษา Copy
ของหนังสือแต่ละ Book
หรืออาจมีหลายเล่ม Copy
แต่ละฉบับสามารถตรวจสอบได้โดย Patron
หรือสามารถเช็คอินได้ในขณะนี้ Patron
เป็นส่วนเสริมของ User
ที่บันทึกที่อยู่และวันเกิดของพวกเขา
สร้าง อ่าน อัปเดต ทำลาย
ความสามารถมาตรฐานอย่างหนึ่งของแผงการดูแลระบบคือการเพิ่มอินสแตนซ์ของแต่ละรุ่น คลิกที่ "หนังสือ" เพื่อไปที่หน้าของโมเดล แล้วคลิกปุ่ม "เพิ่มหนังสือ" ที่มุมบนขวา การทำเช่นนั้นจะดึงแบบฟอร์มขึ้นมา ซึ่งคุณสามารถกรอกและบันทึกเพื่อสร้างหนังสือได้
การสร้าง Patron
เผยให้เห็นความสามารถในตัวอื่นของแบบฟอร์มการสร้างของผู้ดูแลระบบ: คุณสามารถสร้างแบบจำลองที่เชื่อมต่อได้โดยตรงจากแบบฟอร์มเดียวกัน ภาพหน้าจอด้านล่างแสดงป๊อปอัปที่เรียกใช้โดยเครื่องหมายบวกสีเขียวทางด้านขวาของเมนูแบบเลื่อนลง User
ดังนั้น คุณสามารถสร้างทั้งสองรุ่นได้ในหน้าผู้ดูแลระบบเดียวกัน
คุณสามารถสร้าง COPY
ได้โดยใช้กลไกเดียวกัน
สำหรับแต่ละระเบียน คุณสามารถคลิกแถวเพื่อแก้ไขโดยใช้แบบฟอร์มเดียวกัน คุณยังสามารถลบเรกคอร์ดได้โดยใช้การดำเนินการของผู้ดูแลระบบ
การดำเนินการของผู้ดูแลระบบ
แม้ว่าความสามารถในตัวของแผงการดูแลระบบจะมีประโยชน์อย่างกว้างขวาง แต่คุณสามารถสร้างเครื่องมือของคุณเองได้โดยใช้การดำเนินการของผู้ดูแลระบบ เราจะสร้างสองรายการ: ชุดแรกสำหรับสร้างสำเนาหนังสือและอีกชุดสำหรับเช็คอินหนังสือที่ส่งคืนในห้องสมุดแล้ว
หากต้องการสร้าง Copy
Book
ให้ไปที่ URL /admin/records/book/
และใช้เมนูแบบเลื่อนลง "การดำเนินการ" เพื่อเลือก "เพิ่มสำเนาของหนังสือ" จากนั้นใช้ช่องทำเครื่องหมายที่คอลัมน์ด้านซ้าย ของตารางเพื่อเลือกหนังสือหรือหนังสือที่จะเพิ่มสำเนาไปยังสินค้าคงคลัง
การสร้างสิ่งนี้ขึ้นอยู่กับวิธีการของแบบจำลองที่เราจะกล่าวถึงในภายหลัง เราสามารถเรียกได้ว่าเป็นการดำเนินการของผู้ดูแลระบบโดยการสร้างคลาส ModelAdmin
สำหรับโมเดล Profile
ดังต่อไปนี้ใน records/admin.py :
from django.contrib import admin from .models import Book, Patron, Copy class BookAdmin(admin.ModelAdmin): list_display = ("title", "author", "published") actions = ["make_copys"] def make_copys(self, request, queryset): for q in queryset: q.make_copy() self.message_user(request, "copy(s) created") make_copys.short_description = "Add a copy of book(s)" admin.site.register(Book, BookAdmin)
คุณสมบัติ list_display
แสดงว่าฟิลด์ใดที่ใช้แทนโมเดลในหน้าภาพรวมของโมเดล คุณสมบัติ actions
แสดงรายการการดำเนินการของผู้ดูแลระบบ การดำเนินการของผู้ดูแลระบบถูกกำหนดให้เป็นฟังก์ชันภายใน BookAdmin
และรับอาร์กิวเมนต์สามอย่าง: ตัวอ็อบเจ็กต์ admin เอง คำขอ (คำขอ HTTP จริงที่ส่งโดยไคลเอ็นต์) และชุดการสืบค้น (รายการของอ็อบเจ็กต์ที่มีช่องทำเครื่องหมายไว้) เราดำเนินการแบบเดียวกันกับแต่ละรายการในชุดการสืบค้น จากนั้นแจ้งให้ผู้ใช้ทราบว่าการดำเนินการเสร็จสิ้นแล้ว การดำเนินการของผู้ดูแลระบบทุกครั้งต้องมีคำอธิบายสั้นๆ เพื่อให้สามารถระบุได้อย่างถูกต้องในเมนูแบบเลื่อนลง สุดท้ายนี้ เราได้เพิ่ม BookAdmin
เมื่อลงทะเบียนโมเดล
การเขียนการดำเนินการของผู้ดูแลระบบสำหรับการตั้งค่าคุณสมบัติเป็นกลุ่มนั้นค่อนข้างซ้ำซาก นี่คือรหัสสำหรับตรวจสอบ Copy
สังเกตว่ามันใกล้เคียงกับการกระทำก่อนหน้า
from django.contrib import admin from .models import Book, Patron, Copy class CopyAdmin(admin.ModelAdmin): actions = ["check_in_copys"] def check_in_copys(self, request, queryset): for q in queryset: q.check_in() self.message_user(request, "copy(s) checked in") check_in_copys.short_description = "Check in copy(s)" admin.site.register(Copy, CopyAdmin)
ธีมผู้ดูแลระบบ
โดยค่าเริ่มต้น Django มีสไตล์ที่ค่อนข้างเรียบง่ายสำหรับแผงการดูแลระบบ คุณสามารถสร้างธีมของคุณเองหรือใช้ธีมของบุคคลที่สามเพื่อให้แผงการดูแลระบบมีรูปลักษณ์ใหม่ ธีมโอเพนซอร์ซยอดนิยมอย่างหนึ่งคือ grappelli ซึ่งเราติดตั้งไว้ก่อนหน้าในบทความ คุณสามารถดูเอกสารประกอบสำหรับความสามารถทั้งหมดได้
การติดตั้งธีมนั้นค่อนข้างตรงไปตรงมา เพียงสองบรรทัดเท่านั้น ขั้นแรก เพิ่ม grappelli
ลงใน INSTALLED_APPS
ดังนี้ใน library/settings.py :
INSTALLED_APPS = [ 'grappelli', 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'records', ]
จากนั้นปรับ library/urls.py :
from django.contrib import admin from django.urls import path, include from records import views urlpatterns = [ path('grappelli/', include('grappelli.urls')), path('admin/', admin.site.urls), path('', views.index), ]
เมื่อมีการเปลี่ยนแปลงเหล่านั้น แผงผู้ดูแลระบบควรมีลักษณะดังนี้:
มีธีมอื่นๆ มากมาย และคุณสามารถพัฒนาธีมของคุณเองได้อีกครั้ง ฉันจะใช้รูปลักษณ์เริ่มต้นสำหรับส่วนที่เหลือของบทความนี้
ทำความเข้าใจโมเดล
ตอนนี้ คุณคุ้นเคยกับแผงการดูแลระบบและใช้งานเพื่อนำทางข้อมูลแล้ว มาดูโมเดลที่กำหนดโครงสร้างฐานข้อมูลของเรากัน แต่ละรุ่นแสดงหนึ่งตารางในฐานข้อมูลเชิงสัมพันธ์
ฐานข้อมูลเชิงสัมพันธ์จัดเก็บข้อมูลในตารางอย่างน้อยหนึ่งตาราง ตารางเหล่านี้แต่ละตารางมีโครงสร้างคอลัมน์ที่ระบุ รวมถึงคีย์หลัก (ตัวระบุที่ไม่ซ้ำกันสำหรับแต่ละองค์ประกอบ) และคอลัมน์ของค่าอย่างน้อยหนึ่งคอลัมน์ ซึ่งมีหลายประเภท เช่น สตริง จำนวนเต็ม และวันที่ แต่ละอ็อบเจ็กต์ที่จัดเก็บไว้ในฐานข้อมูลจะแสดงเป็นแถวเดียว ส่วน "เชิงสัมพันธ์" ของชื่อนั้นมาจากคุณลักษณะที่สำคัญที่สุดของเทคโนโลยีที่อาจเรียกได้ว่าเป็น นั่นคือ การสร้างความสัมพันธ์ระหว่างตาราง วัตถุ (แถว) สามารถมีหนึ่งต่อหนึ่ง หนึ่งต่อกลุ่ม (คีย์ต่างประเทศ) หรือการแมปแบบกลุ่มต่อกลุ่มกับแถวในตารางอื่น เราจะพูดถึงเรื่องนี้เพิ่มเติมในตัวอย่าง
โดยค่าเริ่มต้น Django ใช้ SQLite3 เพื่อการพัฒนา SQLite3 เป็นเครื่องมือฐานข้อมูลเชิงสัมพันธ์อย่างง่าย และฐานข้อมูลของคุณถูกสร้างขึ้นโดยอัตโนมัติเป็น db.sqlite3 ในครั้งแรกที่คุณเรียกใช้ python manage.py migrate
เราจะดำเนินการต่อด้วย SQLite3 สำหรับบทความนี้ แต่ไม่เหมาะสำหรับการใช้งานจริง เนื่องจากโดยหลักแล้ว การเขียนทับสามารถเกิดขึ้นได้กับผู้ใช้ที่ทำงานพร้อมกัน ในการผลิตหรือเมื่อเขียนระบบที่คุณตั้งใจจะใช้งานในวันหนึ่ง ให้ใช้ PostgreSQL หรือ MySQL
Django ใช้โมเดลเพื่อเชื่อมต่อกับฐานข้อมูล การใช้ส่วนหนึ่งของ ORM ของ Django ไฟล์ records/models.py มีหลายโมเดล ซึ่งช่วยให้สามารถระบุฟิลด์ คุณสมบัติ และเมธอดสำหรับแต่ละอ็อบเจ็กต์ได้ เมื่อสร้างแบบจำลอง เรามุ่งมั่นเพื่อสถาปัตยกรรม "โมเดลอ้วน" ด้วยเหตุผล ซึ่งหมายความว่าควรจัดการการตรวจสอบความถูกต้องของข้อมูล การแยกวิเคราะห์ การประมวลผล ตรรกะทางธุรกิจ การจัดการข้อยกเว้น การแก้ไขขอบเคส และงานที่คล้ายกันให้มากที่สุดเท่าที่จะเป็นไปได้ในข้อมูลจำเพาะของตัวแบบ ภายใต้ประทุน โมเดล Django นั้นซับซ้อนมาก เป็นออบเจ็กต์ที่มีลักษณะเด่นพร้อมพฤติกรรมเริ่มต้นที่มีประโยชน์อย่างกว้างขวาง สิ่งนี้ทำให้สถาปัตยกรรม "Fat Model" ทำได้ง่ายโดยไม่ต้องเขียนโค้ดจำนวนมาก
มาดูโมเดลทั้งสามกันในแอปพลิเคชันตัวอย่างของเรา เราไม่สามารถครอบคลุมทุกอย่างได้ เนื่องจากนี่ควรจะเป็นบทความเบื้องต้น ไม่ใช่เอกสารฉบับสมบูรณ์ของเฟรมเวิร์ก Django แต่ฉันจะเน้นตัวเลือกที่สำคัญที่สุดที่ฉันทำในการสร้างโมเดลง่ายๆ เหล่านี้
คลาส Book
เป็นโมเดลที่ตรงไปตรงมาที่สุด นี่คือจาก records/models.py :
from django.db import models class Book(models.Model): title = models.CharField(max_length=300) author = models.CharField(max_length=150) published = models.DateField() isbn = models.IntegerField(unique=True) def __str__(self): return self.title + " by " + self.author def make_copy(self): Copy.objects.create(book=self)
ฟิลด์ CharField
ทั้งหมดต้องมีแอตทริบิวต์ max_length
ที่ระบุ ความยาวทั่วไปคือ 150 อักขระ ซึ่งฉันเพิ่มเป็นสองเท่าสำหรับ title
ในกรณีที่ชื่อเรื่องยาวมาก แน่นอนว่ายังมีขีดจำกัดตามอำเภอใจซึ่งอาจเกินได้ สำหรับความยาวของข้อความที่ไม่ จำกัด ให้ใช้ TextField
ฟิลด์ที่ published
คือ DateField
เวลาที่หนังสือถูกตีพิมพ์ไม่สำคัญ แต่ถ้าเป็นเช่นนั้นฉันจะใช้ DateTimeField
สุดท้าย ISBN เป็นจำนวนเต็ม (ISBN คือ 10 หรือ 13 หลัก ดังนั้นทั้งหมดจึงพอดีในค่าสูงสุดของจำนวนเต็ม) และเราใช้ unique=True
เนื่องจากไม่มีหนังสือสองเล่มใดที่มี ISBN เดียวกันได้ ซึ่งจากนั้นจะบังคับใช้ในระดับฐานข้อมูล
ออบเจ็กต์ทั้งหมดมีเมธอด __str__(self)
ที่กำหนดการแสดงสตริง เราลบล้างการใช้งานเริ่มต้นโดยคลาส models.Model
และแทนหนังสือเป็น "ชื่อโดยผู้แต่ง" ในทุกที่ที่โมเดลจะแสดงเป็นสตริง จำได้ว่าก่อนหน้านี้เราใช้ list_display
ในวัตถุ admin ของ Book
เพื่อกำหนดว่าฟิลด์ใดที่จะแสดงในรายการของแผงการดูแลระบบ หาก list_display
รายการผู้ดูแลระบบแทนจะแสดงการแสดงสตริงของโมเดล เช่นเดียวกับที่จะแสดงสำหรับทั้ง Patron
และ Copy
สุดท้าย เรามีวิธีการเกี่ยวกับ Book
ที่เราเรียกในการดำเนินการของผู้ดูแลระบบที่เราเขียนไว้ก่อนหน้านี้ ฟังก์ชันนี้สร้าง Copy
ที่เกี่ยวข้องกับอินสแตนซ์ของ Book
ในฐานข้อมูล
ย้ายไปยัง Patron
โมเดลนี้แนะนำแนวคิดของความสัมพันธ์แบบหนึ่งต่อหนึ่ง ในกรณีนี้ด้วยโมเดล User
ในตัว ลองดูจาก records/models.py :
from django.db import models from django.contrib.auth.models import User class Patron(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE) address = models.CharField(max_length=150) dob = models.DateField() def __str__(self): return self.user.username
ฟิลด์ user
ไม่ใช่ฟังก์ชัน bijective อย่างแน่นอน อาจมีอินสแตนซ์ของ User
ที่ไม่มีอินสแตนซ์ของ Patron
ที่เกี่ยวข้อง อย่างไรก็ตาม User
ไม่สามารถเชื่อมโยงกับอินสแตนซ์ของ Patron
ได้มากกว่าหนึ่งราย และ Patron
ไม่สามารถ ดำรงอยู่ได้หากไม่มีความสัมพันธ์กับผู้ใช้เพียงกลุ่มเดียว มีการบังคับใช้ที่ระดับฐานข้อมูล และรับประกันโดยข้อกำหนด on_delete=models.CASCADE
: หากอินสแตนซ์ User
ถูกลบ Profile
ที่เกี่ยวข้องจะถูกลบออก
ฟิลด์อื่นและ __str__(self)
ที่เราเคยเห็นมาก่อน เป็นที่น่าสังเกตว่าคุณสามารถเข้าถึงผ่านความสัมพันธ์แบบหนึ่งต่อหนึ่งเพื่อรับแอตทริบิวต์ ในกรณีนี้คือ user.username
ในฟังก์ชันของแบบจำลอง
หากต้องการขยายประโยชน์ของความสัมพันธ์ฐานข้อมูล ให้หันมาสนใจที่ Copy
from records/models.py :
from django.db import models class Copy(models.Model): book = models.ForeignKey(Book, on_delete=models.CASCADE) out_to = models.ForeignKey(Patron, blank=True, null=True, on_delete=models.SET_NULL) def __str__(self): has_copy = "checked in" if self.out_to: has_copy = self.out_to.user.username return self.book.title + " -> " + has_copy def check_out(self, p): self.out_to = p self.save() def check_in(self): self.out_to = None self.save()
อีกครั้งที่เราเคยเห็นสิ่งนี้มาก่อนแล้ว ดังนั้นเรามาเน้นที่สิ่งใหม่: models.ForeignKey
Copy
จะต้องเป็น Book
เดียว แต่ห้องสมุดอาจมี Copy
หลายฉบับของหนังสือแต่ละ Book
Book
สามารถมีอยู่ในฐานข้อมูลโดยที่ห้องสมุดไม่มี Copy
ในแค็ตตาล็อก แต่ไม่สามารถมี Copy
ได้หากไม่มี Book
พื้นฐาน
ความสัมพันธ์ที่ซับซ้อนนี้แสดงด้วยบรรทัดต่อไปนี้:
book = models.ForeignKey(Book, on_delete=models.CASCADE)
พฤติกรรมการลบจะเหมือนกับของ Patron
ในการอ้างอิงถึง User
ความสัมพันธ์ระหว่าง Copy
และ Patron
แตกต่างกันเล็กน้อย สามารถเช็คเอาท์ Copy
ได้ถึงหนึ่ง Patron
แต่ Patron
แต่ละคนสามารถตรวจสอบ Copy
ได้มากเท่าที่ห้องสมุดอนุญาต อย่างไรก็ตาม นี่ไม่ใช่ความสัมพันธ์แบบถาวร บางครั้ง Copy
จะไม่ถูกเช็คเอาท์ Patron
และ Copy
มีอยู่อย่างอิสระจากกันในฐานข้อมูล การลบอินสแตนซ์ของอินสแตนซ์หนึ่งไม่ควรลบอินสแตนซ์ของอีกรายการหนึ่ง
ความสัมพันธ์นี้ยังคงเป็นกรณีการใช้งานสำหรับคีย์นอก แต่มีอาร์กิวเมนต์ต่างกัน:
out_to = models.ForeignKey(Patron, blank=True, null=True, on_delete=models.SET_NULL)
ที่นี่ การมี blank=True
อนุญาตให้แบบฟอร์มยอมรับ None
เป็นค่าสำหรับความสัมพันธ์ และ null=True
อนุญาตให้คอลัมน์สำหรับความสัมพันธ์ของ Patron
ในตาราง Copy
ในฐานข้อมูลยอมรับ null
เป็นค่า พฤติกรรมการลบ ซึ่งจะถูกทริกเกอร์บน Copy
หากอินสแตนซ์ของ Patron
ถูกลบในขณะที่มีการเช็คเอาท์นั้นคือการตัดความสัมพันธ์ในขณะที่ปล่อยให้ Copy
Copy
เสียหายโดยการตั้งค่าฟิลด์ Patron
เป็นโมฆะ
ประเภทฟิลด์เดียวกัน models.ForeignKey
สามารถแสดงความสัมพันธ์ที่แตกต่างกันอย่างมากระหว่างอ็อบเจ็กต์ ความสัมพันธ์เดียวที่ฉันไม่สามารถใส่ในตัวอย่างได้อย่างสมบูรณ์คือเขตข้อมูลแบบกลุ่มต่อกลุ่มซึ่งเหมือนกับเขตข้อมูลแบบหนึ่งต่อหนึ่ง ยกเว้นว่า ตามชื่อที่แนะนำ แต่ละอินสแตนซ์สามารถเชื่อมโยงกับอินสแตนซ์อื่น ๆ ได้มากมาย และแต่ละอื่น ๆ และแต่ละอย่างสามารถเชื่อมโยงกับคนอื่น ๆ ได้มากมายเช่นหนังสือสามารถมีผู้แต่งได้หลายคนซึ่งแต่ละคนได้เขียนหนังสือหลายเล่ม
การย้ายถิ่น
คุณอาจสงสัยว่าฐานข้อมูลรู้ได้อย่างไรว่าแสดงอะไรในตัวแบบ จากประสบการณ์ของผม การอพยพย้ายถิ่นเป็นหนึ่งในสิ่งที่ค่อนข้างตรงไปตรงมา จนกระทั่งไม่เป็นเช่นนั้น แล้วพวกมันก็จะกัดกินหน้าคุณ ต่อไปนี้คือวิธีรักษาแก้วของคุณให้ไม่เสียหาย สำหรับผู้เริ่มต้น: เรียนรู้เกี่ยวกับการย้ายข้อมูลและวิธีโต้ตอบกับสิ่งเหล่านี้ แต่พยายามหลีกเลี่ยงการแก้ไขไฟล์การโยกย้ายด้วยตนเอง หากคุณทราบแล้วว่าคุณกำลังทำอะไรอยู่ ให้ข้ามส่วนนี้และติดตามสิ่งที่เหมาะกับคุณ
ไม่ว่าจะด้วยวิธีใด ให้ตรวจสอบเอกสารอย่างเป็นทางการสำหรับการปฏิบัติต่อบุคคลดังกล่าวอย่างสมบูรณ์
การย้ายข้อมูลแปลการเปลี่ยนแปลงในแบบจำลองเป็นการเปลี่ยนแปลงในสคีมาฐานข้อมูล คุณไม่จำเป็นต้องเขียนมันเอง Django สร้างขึ้นด้วยคำสั่ง python manage.py makemigrations
คุณควรเรียกใช้คำสั่งนี้เมื่อคุณสร้างโมเดลใหม่หรือแก้ไขฟิลด์ของโมเดลที่มีอยู่ แต่ไม่จำเป็นต้องทำเช่นนั้นเมื่อสร้างหรือแก้ไขเมธอดของโมเดล สิ่งสำคัญคือต้องสังเกตว่าการโยกย้ายมีอยู่เป็นลูกโซ่ โดยแต่ละอันจะอ้างอิงถึงการโยกย้ายก่อนหน้า เพื่อให้สามารถแก้ไขสคีมาฐานข้อมูลได้โดยปราศจากข้อผิดพลาด ดังนั้น หากคุณกำลังทำงานร่วมกันในโครงการ การรักษาประวัติการย้ายข้อมูลเดียวที่สอดคล้องกันในการควบคุมเวอร์ชันเป็นสิ่งสำคัญ เมื่อมีการโยกย้ายที่ไม่ได้ใช้ ให้เรียกใช้ python manage.py migrate
เพื่อปรับใช้ก่อนที่จะเรียกใช้เซิร์ฟเวอร์
ตัวอย่างโปรเจ็กต์ถูกแจกจ่ายด้วยการโยกย้ายเดียว, records/migrations/0001_initial.py อีกครั้ง นี่คือโค้ดที่สร้างโดยอัตโนมัติซึ่งคุณไม่ควรต้องแก้ไข ดังนั้นฉันจะไม่คัดลอกโค้ดในนี้ แต่ถ้าคุณต้องการเข้าใจว่าเกิดอะไรขึ้นเบื้องหลัง ให้ลองดู
การแข่งขัน
ต่างจากการย้ายถิ่น การติดตั้งไม่ใช่ลักษณะทั่วไปของการพัฒนา Django ฉันใช้เพื่อแจกจ่ายข้อมูลตัวอย่างกับบทความ และไม่เคยใช้อย่างอื่นมาก่อน อย่างไรก็ตาม เนื่องจากเราใช้ก่อนหน้านี้ ฉันรู้สึกจำเป็นต้องแนะนำหัวข้อนี้
ครั้งหนึ่ง เอกสารอย่างเป็นทางการค่อนข้างบางในหัวข้อนี้ โดยรวมแล้ว สิ่งที่คุณควรรู้คือโปรแกรมติดตั้งเป็นวิธีการนำเข้าและส่งออกข้อมูลจากฐานข้อมูลของคุณในหลากหลายรูปแบบ รวมถึง JSON ซึ่งเป็นสิ่งที่ฉันใช้ ฟีเจอร์นี้ส่วนใหญ่มีไว้เพื่อช่วยในสิ่งต่างๆ เช่น การทดสอบอัตโนมัติ และไม่ใช่ระบบสำรองหรือวิธีการแก้ไขข้อมูลในฐานข้อมูลแบบสด นอกจากนี้ โปรแกรมติดตั้งจะไม่อัปเดตด้วยการย้ายข้อมูล และหากคุณพยายามใช้โปรแกรมติดตั้งกับฐานข้อมูลที่มีสคีมาที่เข้ากันไม่ได้ โปรแกรมจะล้มเหลว
ในการสร้างโปรแกรมติดตั้งสำหรับฐานข้อมูลทั้งหมด ให้เรียกใช้:
python manage.py dumpdata --format json > fixture.json
ในการโหลดฟิกซ์เจอร์ ให้รัน:
python manage.py loaddata fixture.json
บทสรุป
การเขียนโมเดลใน Django เป็นเรื่องใหญ่ และการใช้แผงผู้ดูแลระบบก็เป็นอีกเรื่องหนึ่ง ใน 3,000 คำ ฉันทำได้เพียงแนะนำแต่ละคำเท่านั้น หวังว่าการใช้แผงการดูแลระบบจะช่วยให้คุณมีอินเทอร์เฟซที่ดีขึ้นในการสำรวจว่าแบบจำลองทำงานอย่างไรและสัมพันธ์กันอย่างไร ทำให้คุณมีความมั่นใจในการทดสอบและพัฒนาการแสดงข้อมูลเชิงสัมพันธ์ของคุณเอง
หากคุณกำลังมองหาจุดเริ่มต้นง่ายๆ ให้ลองเพิ่มโมเดล Librarian
ที่สืบทอดมาจาก User
เหมือนกับ Profile
สำหรับความท้าทายที่มากขึ้น ให้ลองใช้ประวัติการชำระเงินสำหรับแต่ละ Copy
และ/หรือ Patron
(มีหลายวิธีในการทำสิ่งนี้ให้สำเร็จ)
Django Highlights เป็นซีรีส์ที่นำเสนอแนวคิดที่สำคัญของการพัฒนาเว็บใน Django แต่ละบทความเขียนขึ้นเพื่อเป็นแนวทางแบบสแตนด์อโลนในด้านการพัฒนา Django เพื่อช่วยให้นักพัฒนาส่วนหน้าและนักออกแบบเข้าถึงความเข้าใจที่ลึกซึ้งยิ่งขึ้นของ "อีกครึ่งหนึ่ง" ของโค้ดเบส บทความเหล่านี้ส่วนใหญ่สร้างขึ้นเพื่อช่วยให้คุณเข้าใจทฤษฎีและแบบแผน แต่มีตัวอย่างโค้ดบางส่วนที่เขียนใน Django 3.0
อ่านเพิ่มเติม
คุณอาจสนใจบทความและเอกสารต่อไปนี้
- จุดเด่นของ Django: โมเดลผู้ใช้และการตรวจสอบสิทธิ์ (ตอนที่ 1)
- ไฮไลท์ของ Django: เทมเพลตบันทึกเส้น (ตอนที่ 2)
- ไฮไลท์ของ Django: การโต้เถียงเรื่องทรัพย์สินทางปัญญาและไฟล์สื่อ (ตอนที่ 4)
- เอกสารผู้ดูแลระบบ Django
- โมเดลจังโก้
- การอ้างอิงฟิลด์โมเดล Django
- Django การย้ายถิ่น