models之欄位型別和引數
示例:
# class Test(models.Model): # courses_test
# """測試學習用"""
# # Auto = models.AutoField() # 自增長欄位
# # BigAuto = models.BigAutoField()
#
# # 二進位制資料
# Binary = models.BinaryField()
#
# # 布林型
# Boolean = models.BooleanField()
# NullBoolean = models.NullBooleanField()
#
# # 整型
# PositiveSmallInteger = models.PositiveSmallIntegerField(db_column="age") # 5個位元組
# SmallInteger = models.SmallIntegerField(primary_key=False) # 6個位元組
# PositiveInteger = models.PositiveIntegerField() # 10個位元組
# Integer = models.IntegerField(verbose_name="11個位元組大小") # 11個位元組
# BigInteger = models.BigIntegerField(unique=True) # 20個位元組
#
# # 字串型別
# Char = models.CharField(max_length=100, null=True, blank=True, db_index=True) # varchar
# Text = models.TextField(help_text="這個是longtext") # longtext
#
# # 時間日期型別
# Date = models.DateField(unique_for_date=True, auto_now=True) #自動填入最新時間
# DateTime = models.DateTimeField(editable=False, unique_for_month=True, auto_now_add=True)
# Duration = models.DurationField() # int, Python timedelta實現
#
# # 浮點型
# Float = models.FloatField()
# Decimal = models.DecimalField(max_digits=4, decimal_places=2) # 11.22, 16.34
#
# # 其它欄位
# Email = models.EmailField() # 郵箱
# Image = models.ImageField()
# File = models.FileField()
# FilePath = models.FilePathField()
# URL = models.URLField()
# UUID = models.UUIDField()
# GenericIPAddress = models.GenericIPAddressField()
#
#
# class A(models.Model):
# onetoone = models.OneToOneField(Test, related_name="one")
#
#
# on_delete 六種模式
# class B(models.Model):
# foreign = models.ForeignKey(A, on_delete=models.CASCADE) # 刪除級聯
# # foreign = models.ForeignKey(A, on_delete=models.PROTECT)
# # foreign = models.ForeignKey(A, on_delete=models.SET_NULL, null=True, blank=True) # 刪除置空
# # foreign = models.ForeignKey(A, on_delete=models.SET_DEFAULT, default=0)
# # foreign = models.ForeignKey(A, on_delete=models.DO_NOTHING)
# # foreign = models.ForeignKey(A, on_delete=models.SET)
#
#
# class C(models.Model):
# manytomany = models.ManyToManyField(B) # 1.所有欄位都有的引數
# 2.個別欄位才有的引數
# 3.關係型欄位的引數 """
on_delete 當一個被外來鍵關聯的物件被刪除時,Django將模仿on_delete引數定義的SQL約束執行相應操作
如下6種操作
CASCADE:模擬SQL語言中的ON DELETE CASCADE約束,將定義有外來鍵的模型物件同時刪除!(該操作為當前Django版本的預設操作!)
PROTECT:阻止上面的刪除操作,但是彈出ProtectedError異常
SET_NULL:將外來鍵欄位設為null,只有當欄位設定了null=True時,方可使用該值。
SET_DEFAULT:將外來鍵欄位設為預設值。只有當欄位設定了default引數時,方可使用。
DO_NOTHING:什麼也不做。
SET():設定為一個傳遞給SET()的值或者一個回撥函式的返回值。注意大小寫。
"""
實際建立表單示例:
from django.db import models # Create your models here. class AddressInfo(models.Model): # coures_addressinfo
"""省市縣地址資訊"""
address = models.CharField(max_length=200, null=True, blank=True, verbose_name="地址")
pid = models.ForeignKey('self', null=True, blank=True, verbose_name="自關聯",on_delete=models.SET_NULL)
# pid = models.ForeignKey('AddressInfo', null=True, blank=True, verbose_name="自關聯")
note = models.CharField(max_length=200, null=True, blank=True, verbose_name="說明") def __str__(self): # __unicode__(self)
return self.address class Meta:
# 定義元資料
db_table = 'address'
# ordering = ['pid'] # 指定按照什麼欄位排序
verbose_name = '省市縣地址資訊'
verbose_name_plural = verbose_name
# abstract = True
# permissions = (('定義好的許可權', '許可權說明'),)
# managed = False
unique_together = ('address', 'note') # ((),())
# app_label = 'courses'
# db_tablespace # 定義資料庫表空間的名字 class Teacher(models.Model):
"""講師資訊表"""
nickname = models.CharField(max_length=30, primary_key=True, db_index=True, verbose_name="暱稱")
introduction = models.TextField(default="這位同學很懶,木有簽名的說~", verbose_name="簡介")
fans = models.PositiveIntegerField(default="", verbose_name="粉絲數")
created_at = models.DateTimeField(auto_now_add=True, verbose_name="建立時間")
updated_at = models.DateTimeField(auto_now=True, verbose_name="更新時間") class Meta:
verbose_name = "講師資訊表"
verbose_name_plural = verbose_name def __str__(self): # Python2:__unicode__
return self.nickname class Course(models.Model):
"""課程資訊表"""
title = models.CharField(max_length=100, primary_key=True, db_index=True, verbose_name="課程名")
teacher = models.ForeignKey(Teacher, null=True, blank=True, on_delete=models.CASCADE,
verbose_name="課程講師") # 刪除級聯
type = models.CharField(choices=((1, "實戰課"), (2, "免費課"), (0, "其它")), max_length=12,
default=0, verbose_name="課程型別")
price = models.PositiveSmallIntegerField(verbose_name="價格")
volume = models.BigIntegerField(verbose_name="銷量")
online = models.DateField(verbose_name="上線時間")
created_at = models.DateTimeField(auto_now_add=True, verbose_name="建立時間")
updated_at = models.DateTimeField(auto_now=True, verbose_name="更新時間") class Meta:
verbose_name = "課程資訊表"
get_latest_by = "created_at"
verbose_name_plural = verbose_name def __str__(self):
return f"{self.get_type_display()}-{self.title}" # 示例:實戰課-Django零基礎入門到實戰
# return "{}-{}".format(self.get_type_display(), self.title) # 示例:實戰課-Django零基礎入門到實戰 class Student(models.Model):
"""學生資訊表"""
nickname = models.CharField(max_length=30, primary_key=True, db_index=True, verbose_name="暱稱")
course = models.ManyToManyField(Course, verbose_name="課程")
age = models.PositiveSmallIntegerField(verbose_name="年齡")
gender = models.CharField(choices=((1, "男"), (2, "女"), (0, "保密")), max_length=1,
default=0, verbose_name="性別")
study_time = models.PositiveIntegerField(default="", verbose_name="學習時長(h)")
created_at = models.DateTimeField(auto_now_add=True, verbose_name="建立時間")
updated_at = models.DateTimeField(auto_now=True, verbose_name="更新時間") class Meta:
verbose_name = "學生資訊表"
ordering = ['age']
verbose_name_plural = verbose_name def __str__(self):
return self.nickname class TeacherAssistant(models.Model):
"""助教資訊表"""
nickname = models.CharField(max_length=30, primary_key=True, db_index=True, verbose_name="暱稱")
teacher = models.OneToOneField(Teacher, null=True, blank=True, on_delete=models.SET_NULL,
verbose_name="講師") # 刪除置空
hobby = models.CharField(max_length=100, null=True, blank=True, verbose_name="愛好")
created_at = models.DateTimeField(auto_now_add=True, verbose_name="建立時間")
updated_at = models.DateTimeField(auto_now=True, verbose_name="更新時間") class Meta:
verbose_name = "助教資訊表"
db_table = "courses_assistant"
verbose_name_plural = verbose_name def __str__(self):
return self.nickname
簡單查詢語句等
# # 1.查詢、檢索、過濾
# teachers = Teacher.objects.all()
# print(teachers)
# teacher2 = Teacher.objects.get(nickname='Jack') # get()只能返回一條結果,多條則會報錯
# print(teacher2, type(teacher2))
# teacher3 = Teacher.objects.filter(fans__gte=500) # QuerySet, 可以是多條結果
# for t in teacher3:
# print(f"講師姓名{t.nickname}--粉絲數{t.fans}")
# # 2.欄位資料匹配,大小寫敏感
# teacher4 = Teacher.objects.filter(fans__in=[666, 1231])
# print(teacher4)
# teacher5 = Teacher.objects.filter(nickname__icontains='A')
# print(teacher5)
# # 3.結果切片、排序、鏈式查詢
# print(Teacher.objects.all()[:1])
# teacher6 = Teacher.objects.all().order_by('-fans')
# for t in teacher6:
# print(t.fans)
# print(Teacher.objects.filter(fans__gte=500).order_by('nickname'))
# # 4.檢視執行的原生SQL
# print(str(Teacher.objects.filter(fans__gte=500).order_by('nickname').query))
# """SELECT `courses_teacher`.`nickname`, `courses_teacher`.`introduction`, `courses_teacher`.`fans`,
# `courses_teacher`.`created_at`, `courses_teacher`.`updated_at` FROM `courses_teacher`
# WHERE `courses_teacher`.`fans` >= 500 ORDER BY `courses_teacher`.`nickname` ASC
# """
"""返回新QuerySet API"""
# 1.all(), filter(), order_by(), exclude(), reverse(), distinct()
# s1 = Student.objects.all().exclude(nickname='A同學')
# for s in s1:
# print(s.nickname, s.age)
# s2 = Student.objects.all().exclude(nickname='A同學').reverse()
# for s in s2:
# print(s.nickname, s.age) # 2.extra(), defer(), only() 實現欄位別名,排除一些欄位,選擇一些欄位
# s3 = Student.objects.all().extra(select={"name": "nickname"})
# for s in s3:
# print(s.name)
# print(str(Student.objects.all().only('nickname', 'age').query)) # 3.values(), values_list() 獲取字典或元組形式的QuerySet
# print(TeacherAssistant.objects.values('nickname', 'hobby'))
# print(TeacherAssistant.objects.values_list('nickname', 'hobby'))
# print(TeacherAssistant.objects.values_list('nickname', flat=True)) # 4.dates(), datetimes() 根據時間日期獲取查詢集
# print(Course.objects.dates('created_at', 'year', order='DESC'))
# print(Course.objects.datetimes('created_at', 'year', order='DESC')) # 5.union(), intersection(), difference() 並集、交集、差集
# p_240 = Course.objects.filter(price__gte=240)
# p_260 = Course.objects.filter(price__lte=260)
# print(p_240.union(p_260))
# print(p_240.intersection(p_260))
# print(p_240.difference(p_260)) # 6.select_related() 一對一、多對一查詢優化, prefetch_related() 一對多、多對多查詢優化;反向查詢
# courses = Course.objects.all().select_related('teacher')
# for c in courses:
# print(f"{c.title}--{c.teacher.nickname}--{c.teacher.fans}") # students = Student.objects.filter(age__lt=30).prefetch_related('course')
# for s in students:
# print(s.course.all())
# print(Teacher.objects.get(nickname="Jack").course_set.all()) # 7.annotate() 使用聚合計數、求和、平均數 raw() 執行原生的SQL
# print(Course.objects.values('teacher').annotate(vol=Sum('volume')))
# print(Course.objects.values('teacher').annotate(pri=Avg('price'))) # """不返回Query API"""
# # 1.獲取物件 get(), get_or_create(), first(), last(), latest(), earliest(), in_bulk()
# print(Course.objects.first())
# print(Course.objects.last())
# print(Course.objects.earliest())
# print(Course.objects.latest())
# print(Course.objects.in_bulk(['Python系列教程4', 'Golang系列教程1']))
#
# # 2.建立物件 create(), bulk_create(), update_or_create() 建立,批量建立,建立或更新
#
# # 3.更新物件 update(), update_or_create() 更新,更新或建立
# Course.objects.filter(title='Java系列教程2').update(price=300)
#
# # 4.刪除物件 delete() 使用filter過濾
# Course.objects.filter(title='test').delete()
#
# # 5.其它操作 exists(), count(), aggregate() 判斷是否存在,統計個數,聚合
# print(Course.objects.filter(title='test').exists())
# print(Course.objects.filter(title='Java系列教程2').exists())
# print(Course.objects.count())
# print(Course.objects.aggregate(Max('price'), Min('price'), Avg('price'), Sum('volume')))
# courses = Course.objects.values('teacher').annotate(t=GroupConcat('title', distinct=True,
# ordering='title ASC',
# separator='-'))
# for c in courses:
# print(c) # Course.objects.update(price=F('price') - 11)
# print(Course.objects.filter(volume__lte=F('price') * 10))
#
# print(Course.objects.filter(Q(title__icontains='java') & Q(volume__gte=5000)))
#
# print(Course.objects.filter(Q(title__icontains='golang') | Q(volume__lte=1000)))