Django-外键

什么是外键?

外键是数据表用来指向某个外来的键值的字段。

为什么使用外键?

1.取出冗余数据

2.数据结构化,使用和执行效率变高

3.便于管理,更好存储数据。

外键的种类

常见外键:ForeignKey

多对多:ManyToManyField

一对一:OneToOneField

万能外键:ContentType

ForeignKey

```python

from django.dbimport models

#coding=utf-8

# Create your models here.

class StudentClass(models.Model):

    name= models.CharField(max_length=12,help_text='班级名称')

master= models.CharField(max_length=12,help_text='班主任')

def __str__(self):

        return 'StudentClass:' + self.name

class Student(models.Model):

    name= models.CharField(max_length=12,help_text='学生姓名')

school_class= models.ForeignKey(StudentClass,on_delete=models.CASCADE)

#(on_delete 属性说明)

    #django 1.9一定需要的

    #1.CASCADE,级联删除

    #当班级记录删除时,删除对应的所有学会

    #2.DO_NOTHING 什么都不做

    #会破坏数据的完整性

    #3.PROTECT 保护

    #当班级删除记录的时候,若有学生关联班级,则不给删除班级

    #4.SET_NULL,设置为NULL

    #当班级删除记录的时候,若有学生关联该班级,则这些学生的班级关联字段全都设置为NULL

# school_class = models.ForeignKey(StudentClass,on_delete=models.SET_NULL, null=True)

    #5.SET_DEFAULT 设置为默认值

    # def default_class():

#    return SchoolClass.objects.first()

# school_class = models.ForeignKey(StudentClass, on_delete=models.SET_DEFAULT, default=default_class)

    #6.SET() 自定义方法,返回一个值,设置该字段的值

    """

    外键查询数据    1.正向查询s = student.objects.first()

    s.school_class #找到关联的班级对象"""

"""

    2.反向查询c = StudentCLass.objects.first()

c.student_set.all()

    related_name, 明确关系,班级通过什么属性找到学生school_class = models.ForeignKey(StudentClass, on_delete=moels.CASCADE, related_name='student')

c = StudentClass.objects.first()

c.student.all()

    """

```

MangToManyField

如:一本书可能有多个作者,一个作者可能出了多本书

```

#coding=utf-8

from django.dbimport models

# Create your models here.

class Author(models.Model):

    author_name= models.CharField(max_length=50)

def __str__(self):

        return 'author_name:'+ self.author_name

class Book(models.Model):

    book_name= models.CharField(max_length=50)

authors= models.ManyToManyField(Author,through='BookAuthor')

class BookAuthor(models.Model):

    author= models.ForeignKey(Author,on_delete=models.CASCADE)

book= models.ForeignKey(Book,on_delete=models.CASCADE)

#还可以添加额外字段

#dir()找到它有那些属性

#多对多字段会创建一个维护多对多关系的表 默认book_author表

#可以使用through 指向中间表,自己来创建这个中间表

"""

正向查询book = Book.objects.first()

authors = book.author.all()

反向查询author = Author.objects.first()

books = author.book_set.all()  #如果指定了relate_name 那么就要换名称了related_name,明确关系,同ForeignKey

authors = models.ManyToManyField(Author, related_name = 'books')

编辑ManyToMany 字段,无需执行save()保存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.boos_set.remove(book)

"""

```

OneToOneField

如:Django用户表和自定义用户拓展表

```

on_delete

class Profile(models.Model):

    user = models.OneToOneField(User,on_delete = models.CASCADE)

    nickname = models.CharField(max_length=24)

'''

正向

profile = Profile.objects.first()

user = profile.user

反向

user = User.objects.first()

profile = user.profile

编辑该字段直接赋值就可以

'''

```

ContentType

如:评论任何对象,评论表不仅能指向文章,还可以指向视频

1.评论表中有两个字段维护这个关系

一个记录类型

一个记录值

class Viedo(models.Model): ...

class Article(models.Model): ...

class Comment(models.Model):

    content_type = models.ForeignKey(ContentType, on_delete = CASCADE) #记录关联对象的类型

    object_id = models.PositiveIntegerField() #记录关联对象的主键值

    content_objects  = GenericForeignKey('content_type' , 'object_id)#常规字段,便于使用

    text=...#评论内容

'''

正向:

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 =rticle_content_type, object_id = article.pk)


反向方法2:主动建立关系

from django.contrib.contenttypes.fields import GenericRelation

#对应模型加入 comments = GenericRelation(‘Comment')字段

article = Article.objects.first()
comments = article.comments.all()

'''

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容