外键
外键是数据表用来指向某个外来的键值的字段
1.外键的作用:
1.去除冗余的数据
2.数据结构化,使用和执行效率更高
3.便于管理,更好地存储数据.
总结:重复的数据,不同类型的内容
2.ForeignKey
from django.db import models
# 班级表
class SchoolClass(models.Model):
class_name = models.CharField(max_length=32)
class_master = models.CharField(max_length=32)
def __str__(self):
return self.class_name
class Student(models.Model):
name = models.CharField(max_length=32)
SEX_CHOICE = {
(0, "男"),
(1, "女")
}
sex = models.IntegerField(choices=SEX_CHOICE, default=0)
student_class = models.ForeignKey(to="SchoolClass", on_delete=models.CASCADE)
# on_delete 属性说明:必填,对应关联的记录(班级),删除的时候,该记录(学生)怎么处理
# 1. models.CASCADE 级联删除
# 当班级记录删除时,删除所有的学生信息,确保数据完整
# 2. models.PROTECT 保护
# 当班级记录删除的时候,若有学生关联班级,则不给删除班级
# 3. models.SET_NULL 设置为NULL
# 当班级记录删除的时候,若有学生关联班级,则将这些学生的班级外键字段,值设置为NULL
# student_class = models.ForeignKey(to="SchoolClass", on_delete=models.CASCADE, null=True)
# 4. models.SET_DEFAULT 设置默认值
# def default_class(self):
# return SchoolClass.objects.first()
# student_class = models.ForeignKey(to="SchoolClass", on_delete=models.SET_DEFAULT, default=default_class)
# 需要设置默认值
# 5. models.SET()
# 自定义方法, 返回一个值,设置该字段的值
# 6. models.DO_NOTHING 什么也不做
# 这个会破坏数据的完整性, 慎用
# (正向:顺理成章)
# s = Student.objects.first()
# s.school_class # 找到关联的班级对象
# (反向:冥冥之中)
# c = SchoolClass.objects.first()
# c.student_set.all() # xxxx_set 找到被关联的对象
# related_name,明确关系,班级通过什么属性找到学生
# school_class = models.ForeignKey(SchoolClass, on_delete=models.CASCADE, related_name='students')
# c = SchoolClass.objects.first()
# c.students.all()
# 编辑该字段,直接赋值即可
# c = SchoolClass.objects.first()
# s = Student()
# s.student_name = 'test'
# s.school_class = c
# s.save()
def __str__(self):
return self.name
3.ManyToMantField
from django.db import models
# Create your models here.
# 作者表
class Author(models.Model):
author_name = models.CharField(max_length=24)
def __str__(self):
return '<Author: {0}>'.format(self.author_name)
__unicode__ = __str__
# 书籍表
class Book(models.Model):
book_name = models.CharField(max_length=48)
authors = models.ManyToManyField(Author)
def __str__(self):
return '<Book: {0}>'.format(self.book_name)
__unicode__ = __str__
# 正向(顺理成章)
# book = Book.objects.first()
# authors = book.authors.all() # 获得该书所有作者
# 反向(冥冥之中)
# author = Author.objects.first()
# books = author.book_set.all() # 获得该作者所有书
# related_name,明确关系,同ForeignKey
# authors = models.ManyToManyField(Author, related_name='books')
# 编辑ManyToMany字段,无需执行save()保存
# 参考:https://docs.djangoproject.com/en/2.2/ref/models/relations/#django.db.models.fields.related.RelatedManager
# add, remove, clear
# book = Book.objects.first()
# author = Author.objects.first()
# 1、书籍新增作者
# book.authors.add(author)
# 2、书籍移除作者
# book.authors.remove(author)
# 3、作者添加书籍
# author.book_set.add(book)
# 4、作者移除书籍
# author.book_set.remove(book)
4.OneToOneField
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
nickname = models.CharField(max_length=24)
def __str__(self):
return '<Profile: {0}>'.format(self.nickname)
__unicode__ = __str__
# 基本使用方法和ForeignKey一样
# 正向:顺理成章
# profile = Profile.objects.first()
# user = profile.user
# 反向:冥冥之中,我知道你的存在
# user = User.objects.first()
# profile = user.profile
# 编辑该字段,直接赋值即可
5.ContentType
from django.db import models
from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
from django.contrib.contenttypes.models import ContentType
# Create your models here.
# 文章表
class Article(models.Model):
title = models.CharField(max_length=36)
content = models.TextField(blank=True)
# comments = GenericRelation('Comment') # 由于Comment后面才定义,所以用字符串惰性引用
def __str__(self):
return '<Article: {0}>'.format(self.title)
__unicode__ = __str__
# 视频表
class Video(models.Model):
video_name = models.CharField(max_length=36)
url = models.URLField()
def __str__(self):
return '<Video: {0}>'.format(self.video_name)
__unicode__ = __str__
# 评论表
class Comment(models.Model):
# 无法同时指向多个对象
# article = models.ForeignKey(Article, on_delete=models.CASCADE)
# video = models.ForeignKey(Video, on_delete=models.CASCADE)
# 万能关系
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE) # 记录关联对象的类型
object_id = models.PositiveIntegerField() # 记录关联对象的主键值
content_object = GenericForeignKey('content_type', 'object_id') # 常规字段,便于使用
# 评论内容
text = models.TextField()
def __str__(self):
return '<Comment: {0}>'.format(self.text)
__unicode__ = __str__
# 正向,使用content_object可直接访问
'''
comment = Comment.objects.first()
obj = comment.content_object # 直接得到所被评论的对象
'''
# 反向,无法直接从其他对象找到Comment对应的评论
'''
from django.contrib.contenttypes.models import ContentType
article = Article.objects.first()
article_content_type = ContentType.objects.get_for_model(article)
# 通过Comment自身的筛选查询得到
comments = Comment.objects.filter(content_type=article_content_type, object_id=article.pk)
'''
# 反向,方法2,主动建立关系
# 参考:https://docs.djangoproject.com/en/2.2/ref/contrib/contenttypes/#reverse-generic-relations
'''
from django.contrib.contenttypes.fields import GenericRelation
# 对应模型加入 comments = GenericRelation('Comment') 字段
article = Article.objects.first()
comments = article.comments.all()
'''
# content type 官方文档
# https://docs.djangoproject.com/en/2.2/ref/contrib/contenttypes/