Python學習——Django模型——表關係

關係型數據庫最強大之處在於“關係”,表和表之間是有關聯的,表之間的關係有一對一,一對多,多對多。

1.1一對一

學生和檔案之間屬於一對一,學生表和檔案表就是一對一關係,學生表是主表,檔案表是從表。從表中有一個外鍵和學生表關聯,並且要求外鍵取值唯一,對應關鍵字爲:OneToOneField

#創建模型
class Student(models.Model):
    sno = models.CharField(max_length=6,primary_key=True)
    sname = models.CharField(max_length=100,null=False)
    ssex = models.CharField(max_length=2,default='男',null=True)
    sage = models.IntegerField(null=True)
    sclass = models.CharField(max_length=10,null=True)

    def __str__(self):
        return "no:{},name:{}".format(self.sno,self.sname)

    class Meta:
        db_table = 'student'

class Archives(models.Model):
    idcard = models.CharField(max_length=18, unique=True)
    address = models.CharField(max_length=200,null=True)
    # on_delete=models.CASCADE 級聯刪除,刪除學生會連同檔案一塊刪除
    student = models.OneToOneField(Student, on_delete=models.CASCADE)

    def __str__(self):
        return "{},{}".format(self.idcard,self.address)

    class Meta:
        db_table = 'archives'

增加數據

def addstudent(request):
    student = Student()
    student.sno = '180502'
    student.sname = '楊康'
    student.sage = 22
    student.save()
    return HttpResponse("增加了一個學生")

def addarchives(request):
    stu = Student.objects.get(pk='180503')
    arc = Archives()
    arc.idcard = '130098384893838953'
    arc.student = stu   #學生對象必須已經保存到數據庫,否認錯誤
    arc.save()
    return HttpResponse("增加檔案")

刪除數據

def deletestudent(request):
    student = Student.objects.get(pk='180503')
    student.delete()
    return HttpResponse("刪除學生")

正向查詢

def findstudent(request):
    # 獲取學生信息
    student = Student.objects.first()
    print(student)
    # 通過學生對象獲取檔案信息
    archive = student.archives
    print(archive)
    return  HttpResponse(student)

反向查詢

def findarchives(request):
    #獲取檔案記錄
    archive = Archives.objects.first()
    #通過檔案獲取關聯學生信息
    student = archive.student
    return HttpResponse(student)

跨關係查詢

def lookup(request):
	#根據檔案查學生
    # student = Student.objects.get(archives__pk=1)
    student = Student.objects.get(archives__idcard='13009488384383838')
    #根據學生查檔案
    archive = Archives.objects.get(student__sno='180501')
    return HttpResponse(archive)

on_delete

  • CASECADE,默認級聯刪除數據
  • PROTECT 保護模式,當從表中存在級聯記錄的時候,刪除主表記錄會拋出保護異常,從表中不存在級聯數據的時候,是允許刪除的
  • SET——xxx
    • NULL        字段本身允許爲空
    • DEFAULT   字段本身有默認值
  • DO-NOTHING   什麼都不做

1.2一對多

一個出版社可以出版多本書,一本書只能被一個出版社出版。出版社和圖書表屬於一對多,一對多一般將主表中的主鍵併到從表中做外鍵。在模型中用ForeignKey表示多對一

class Publisher(models.Model):
    pname = models.CharField(max_length=100,null=True)

    def __str__(self):
        return self.pname

    class Meta:
        db_table = 'publisher'

class Book(models.Model):
    bname = models.CharField(max_length=200,null=True)
    #多對一模型通過ForeignKey表示多對一
    #如果publisher定義在book之後,第一個參數應該用字符串'Publisher'
    publisher = models.ForeignKey(Publisher,on_delete=models.CASCADE,null=True)

    def __str__(self):
        return self.bname
    class Meta:
        db_table = 'book'

正向查詢

def findpublisher(req):
    pub = Publisher.objects.first()
    print(pub)
    # pub = Publisher()
    book = pub.book_set.all()
    print(book)
    return HttpResponse("查詢出版社")

反向查詢

def findbook(req):
    book = Book.objects.first()
    return HttpResponse(book.publisher.pname)

跨關係查詢

def loopup(req):
    # 根據圖書獲取出版社
    pub = Publisher.objects.get(book__bname='花樣年華927937')
    print(pub)

    # 根據出版社獲取圖書
    books = Book.objects.filter(publisher__pname='科技出版社5829')
    print(books)
    return HttpResponse("跨關係查詢")

1.3多對多

一個買家可以購買多件商品,一件商品可以被多個買家購買,買家和商品之間構成多對多關係,多對多關係必然會生成一張中間表:買家-商品表,記錄商品和買家的關係,該表包含商品表主鍵和買家表的主鍵

from django.db import models

# Create your models here.
class Buyer(models.Model):
    bname = models.CharField(max_length=30)
    level = models.IntegerField(default=1)

class Goods(models.Model):
    gname = models.CharField(max_length=100)
    price = models.FloatField()
    buyer = models.ManyToManyField(Buyer)
    def __str__(self):
        return self.gname +"  "+ str(self.price)

購買商品

def sellgoods(req):
    goods = Goods.objects.get(pk=randint(1,Goods.objects.count()))
    goods.buyer.add(Buyer.objects.get(pk=randint(1,Buyer.objects.count())))
    goods.save()
    return HttpResponse("剁手成功")

正向查詢

def findgoods_by_buyer(req):
    buyer = Buyer.objects.get(pk=13)
    res = buyer.goods_set.all()
    print(res)
    return HttpResponse("由買家查詢商品")

反向查詢

def findbuyer_by_goods(request):
    goods = Goods.objects.last()
    buyer = goods.buyer.all()
    print(buyer)
    return HttpResponse("由商品查詢買家")

2.模型繼承

django中的數據庫模塊提供了一個非常不錯的功能,就是支持models的面向對象,可以在models中添加Meta,指定是否抽象,然後進行繼承

class Animal(models.Model):
        xxx
        class Meta:
            abstract = True/False
    
class Dog(Animal):
        xxx

​默認模型就是允許繼承的,但是默認的繼承處理方式不是很合理:
  • 默認在父類中定義的字段會存在父類的表中,子類的數據通用部分會存在父表中,子類特有數據會在子表中,子類通過外鍵進行級聯

  • 默認方式比較垃圾,效率比較低

開發中,需要將父類抽象化,在元信息中使用abstract=True

  • 抽象化的父類不會再數據庫生成表了

  • 子類會將父類中的通用數據,複製到子表中

3 原生sql

from django.db import connection
​
# with語句相當與cursor= connection.cursor() 和 cursor.close(),簡化了語
with connection.cursor() as cursor:                        
        cursor.execute("UPDATE bar SET foo = 1 WHERE baz = %s", [self.baz])
        cursor.execute("SELECT foo FROM bar WHERE baz = %s", [self.baz])
        row = cursor.fetchone()
​
# 返回列表套字典
with connection.cursor() as cursor:
        cursor.execute("select * from publisher")
        columns = [col[0] for col in cursor.description]
        res = [dict(zip(columns, row)) for row in cursor.fetchall()]
        print(res)

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章