zoukankan      html  css  js  c++  java
  • 55.ORM外键:引用同app下的不同模型,引用不同app下的模型,引用模型自身使用详解

    外键和表关系

    外键是属于数据库级别的,在MySQL中,表有两种引擎,一种是InnoDB,另外一种是myisam。如果使用的是InnoDB引擎,是支持外键约束的。外键的存在使得ORM框架在处理表关系的时候异常强大。因此这里我们首先来介绍外键在Django中的使用。

    类定义为 class ForeignKey(to,on_delete,**options)。第一个参数to是应用的哪个模型(也就是应用的表),第二个参数on_delete在使用外键应用的模型数据被删除了,这个字段该如何处理。举例说明,如果有一个user和一个Article两个模型。一个user可以发表多篇文章,一个Article只能有一个Author,并且通过外键进行应用。

    1. 使用外键引用同一个APP中的不同模型,示例代码如下:

    # 注意:在定义一个模型的时候,模型的名字的首字母一定要大写,否者的话,模型名字下面会出现波浪线。
    class User(models.Model):
    	username = models.CharField(max_length=20)
    	password = models.CharField(max_length=100)
    
    class Article(models.Model):
    	title = models.CharField(max_length=100)
    	content = models.TextField()
    
    	author = models.ForeignKey('User',on_delete=models.CASCADE)
    	
    
    使用ForeignKey来定义模型之间的关系,即在article的实例中可以通过author属性来做对应的User模型。这样使用起来非常方便。

    views.py文件中实现向数据库表中添加一条数据,示例代码如下:

    
    from django.http import HttpResponse
    from  .models import User,Article
    
    
    def index(request):
        # 向数据库表中添加一条数据,首先要先将被引用的表添加数据,并进行保存
        user = User(username='孤烟逐云', password='hello')
        user.save()
        article = Article(title='Python', content='真好')
        article.author = user
        article.save()
        return HttpResponse("Success ! ")
        
    
    为什么使用了ForeignKey后,就能通过author属性访问到对应的user对象呢?

    因为在底层,Django为Article表添加了一个属性名_id的字段(比如author的字段名称是author_id),这个字段是一个外键,记录着对应的作者的主键。以后通过article.author访问的时候,实际上是通过author_id找到对应的数据,然后再提取user表中的这条数据,形成一个模型。

    展示表User中的数据:

    在这里插入图片描述

    展示表article中的数据:

    在这里插入图片描述

    views.py文件实现从数据库表中查询数据,并且打印输出,示例代码如下:

    
    from django.http import HttpResponse
    from  .models import User,Article
    
    
    def index(request):
    	article = Article.objects.all()
        print(article)
        return HttpResponse("Success ! ")
    
    此时的打印结果为:

    在这里插入图片描述

    重写Article类的__str__(self)方法,将数据显示出来,示例代码如下:
    class Article(models.Model):
        title = models.CharField(max_length=100)
        content = models.TextField()
        author = models.ForeignKey('User',on_delete=models.CASCADE)
    
        def __str__(self):
            return "<(Article id: %s, title: %s, content: %s, author: %s)>" % (self.id, self.title, self.content, self.author)
    
    
    再次运行项目进行打印输出,数据具体信息:

    在这里插入图片描述

    2. 使用外键引用另外一个app的模型

    那么应该在传递to参数的时候,使用app.model_name进行指定。以上例为例,如果User和Article不是在同一个APP中,那么在引用的时候的示例代码如下:
    # Book模型在book,app中,
    from django.db import models
    
    
    class Book(models.Model):
    # 定义属性,出版社的地址
        pub_add = models.CharField(max_length=100)
    
    
    # 在article模型中进行外键引用
    class Article(models.Model):
        title = models.CharField(max_length=100)
        content = models.TextField()
        # 使用外键引用同一个app下的模型
        author = models.ForeignKey('User',on_delete=models.CASCADE)
        # 使用外键引用不同app下的模型
        pub = models.ForeignKey('book.Book',on_delete=models.CASCADE)
    
    在使用命令python manage.py migrate将迁移脚本文件映射到数据库中的过程中,出现django.db.utils.IntegrityError: (1452, 'Cannot add or update a child row: a foreign key constraint fails (`orm_relationship

    _demo.#sql-158c_79, CONSTRAINT article_article_pub_id_e2e65cb7_fk_book_book_id FOREIGN KEY (pub_id) REFERENCES book
    _book (id`))')

    解决办法就是将settings.py文件中的DATABASE配置"default"变量中,添加:
    # 取消对外键的检查
     'OPTIONS':{
            "init_command":"SET foreign_key_checks = 0;",
        }
    
    之后再次使用命令python manage.py migrate 就没有任何错误出现了。
    来到navicat中查看映射生成的表:
    book表中的字段信息

    在这里插入图片描述

    article表中的字段信息:

    在这里插入图片描述

    查看article_artilce表中外键的引用情况,由输出信息可以看出,引用了同一个app:article中的user表和不同app:book中的book表。

    在这里插入图片描述

    3.使用外键引用本身模型

    'to'参数可以为'self',或者是这个模型的名字,在论坛开发中,一般的评论都可以进行二级评论,即可以针对另外一个评论进行评论,那么在定义模型的时候就需要使用外键来引用资深了,示例代码如下:
    class Comment(models.Model):
        content = models.TextField()
        origion_comment = models.ForeignKey('self',on_delete=models.CASCADE)
    
    查看article_comment这个表:

    在这里插入图片描述

    始于才华,忠于颜值;每件事情在成功之前,看起来都是天方夜谭。一无所有,就是无所不能。
  • 相关阅读:
    函数
    数组
    类的例题
    异常语句
    类的学习
    for的穷举、迭代
    for循环
    switch case
    反相器,扇入扇出
    T触发器,JK触发器的verilog实现
  • 原文地址:https://www.cnblogs.com/guyan-2020/p/12219607.html
Copyright © 2011-2022 走看看