如果想要引用另外一个app的模型,那么应该在传递to参数的时候,使用app.model_name进行指定。如果User和Article不是在同一个app中。
models.py文件
from django.db import models # 分类 class Category(models.Model): name = 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) 第一个参数指向关联的模型 category = models.ForeignKey("Category", on_delete=models.CASCADE) # "user.User"中的user是app名称,该User模型是user这个app模型下面的,引入其他模型 author = models.ForeignKey("user.User", on_delete=models.CASCADE, null=True)如果模型的外键引用的是本身自己这个模型,那么to参数可以为’self’,或者是这个模型的名字。在论坛开发中,一般评论都可以进行二级评论,即可以针对另外一个评论进行评论,那么在定义模型的时候就需要使用外键来引用自身。
class Comment(models.Model): content = models.TextField() origin_comment = models.ForeignKey('self',on_delete=models.CASCADE,null=True) # 或者 # origin_comment = models.ForeignKey('Comment',on_delete=models.CASCADE,null=True)如果一个模型使用了外键。那么在对方那个模型被删掉后,该进行什么样的操作。可以通过on_delete来指定。可以指定的类型如下:
1.CASCADE:级联操作。如果外键对应的那条数据被删除了,那么这条数据也会被删除。 from django.shortcuts import render from .models import Article, Category from django.http import HttpResponse def delete_view(request): category = Category.objects.get(pk=1) # 分类表中的category是外键,删除该外键会影响到文章表中关联这个外键的文章表数据,级联删除 category.delete() return HttpResponse("删除成功") 2.PROTECT:受保护。即只要这条数据引用了外键的那条数据,那么就不能删除外键的那条数据。 from django.db import models # 分类 class Category(models.Model): name = models.CharField(max_length=100) # 文章 class Article(models.Model): title = models.CharField(max_length=100) content = models.TextField() # PROTECT,不允许删除引用了外键的数据 category = models.ForeignKey("Category", on_delete=models.PROTECT) 3.SET_NULL:设置为空。如果外键的那条数据被删除了,那么在本条数据上就将这个字段设置为空。如果设置这个选项,前提是要指定这个字段可以为空。 from django.db import models # 分类 class Category(models.Model): name = models.CharField(max_length=100) # 文章 class Article(models.Model): title = models.CharField(max_length=100) content = models.TextField() # SET_NULL 设置为空 前提必须允许为空 category = models.ForeignKey("Category", on_delete=models.SET_NULL, null=True) 4.SET_DEFAULT:设置默认值。如果外键的那条数据被删除了,那么本条数据上就将这个字段设置为默认值。如果设置这个选项,前提是要指定这个字段一个默认值。 from django.db import models # 分类 class Category(models.Model): name = models.CharField(max_length=100) # 文章 class Article(models.Model): title = models.CharField(max_length=100) content = models.TextField() # SET_DEFAULT 设置为默认值,前提需要先给默认值 category = models.ForeignKey("Category", on_delete=models.SET_DEFAULT, default=Category.objects.get(pk=2)) 5.SET():如果外键的那条数据被删除了。那么将会获取SET函数中的值来作为这个外键的值。SET函数可以接收一个可以调用的对象(比如函数或者方法),如果是可以调用的对象,那么会将这个对象调用后的结果作为值返回回去。 from django.db import models # 分类 class Category(models.Model): name = models.CharField(max_length=100) # 文章 class Article(models.Model): title = models.CharField(max_length=100) content = models.TextField() # 设置值 category = models.ForeignKey("Category", on_delete=models.SET(Category.objects.get(pk=4))) 6.DO_NOTHING:不采取任何行为。一切全看数据库级别的约束。 # 不采取任何行为。一切全看数据库级别的约束 category = models.ForeignKey("Category", on_delete=models.DO_NOTHING)以上这些选项只是Django级别的,数据级别依旧是RESTRICT!
数据库层面的约束有四种:
RESTRICT:默认的选项,如果想要删除父表的记录时,而在子表中有关联该父表的记录,则不允许删除父表中的记录;NOACTION:同 RESTRICT效果一样,也是首先先检查外键;CASCADE:父表delete、update的时候,子表会delete、update掉关联记录;SET NULL:父表delete、update的时候,子表会将关联记录的外键字段所在列设为null,所以注意在设计子表时外键不能设为not null;查找是数据库操作中一个非常重要的技术。查询一般就是使用filter、exclude以及get三个方法来实现。我们可以在调用这些方法的时候传递不同的参数来实现查询需求。在ORM层面,这些查询条件都是使用field+__+condition的方式来使用的。
exact 使用精确的=进行查找。如果提供的是一个None,那么在SQL层面就是被解释为NULL.
from django.shortcuts import render from django.http import HttpResponse from .models import Article, Category from django.db import connection # ORM查询数据库中操作 def find_data(request): # article = Article.objects.get(id__exact=1) # 打印SQL原生语句 # print(connection.queries) # article = Article.objects.get(pk__exact=1) # print(article) # 使用get查询数据,如果数据不存在,会报错 # article = Article.objects.get(pk__exact=None) # 采用filter查询数据,返回的是QuerySet模型对象 article = Article.objects.filter(pk__exact=None) print(article) # 打印SQL原生语句 print(article.query) return HttpResponse("find")article.query,可以得到Django执行的SQL语句。但是只能作用于QuerySet对象上。
iexact 使用like进行查找.(精确查找,不是模糊查询)
# like查询,模糊查询,但是在SQL原生语句中没有添加 %查找名称% 所以没有模糊查询的效果,而是精确查找,下面介绍的contains字段才是模糊查询 article = Article.objects.get(id__iexact=1) print(connection.queries) article = Article.objects.filter(id__iexact=1) print(article.query) article = Article.objects.filter(title__iexact='hello world') 那么以上的查询就等价于以下的SQL语句: select * from article where title like 'hello world';注意上面这个sql语句,因为在MySQL中,没有一个叫做ilike的。所以exact和iexact的区别实际上就是LIKE和=的区别,在大部分collation=utf8_general_ci情况下都是一样的(collation是用来对字符串比较的)
contains 大小写敏感,判断某个字段是否包含了某个数据。(模糊查询)
articles = Article.objects.filter(title__contains='hello') 在翻译成SQL语句为如下: select * where title like binary '%hello%';要注意的是,在使用contains的时候,翻译成的sql语句左右两边是有百分号的,意味着使用的是模糊查询。而exact翻译成sql语句左右两边是没有百分号的,意味着使用的是精确的查询。
icontains 大小写不敏感的匹配查询。(模糊查询)
articles = Article.objects.filter(title__icontains='hello') 在翻译成SQL语句为如下: select * where title like '%hello%';in 提取那些给定的field的值是否在给定的容器中。容器可以为list、tuple或者任何一个可以迭代的对象,包括QuerySet对象。
articles = Article.objects.filter(id__in=[1,2,3]) 以上代码在翻译成SQL语句为如下: select *from articles where id in (1,2,3) 当然也可以传递一个QuerySet对象进去。 # 查找标题为hello的文章分类 articles = Article.objects.filter(title__icontains="hello") # article 就是模型Article的小写,反向引用 category = Category.objects.filter(article__in=articles) # 查找文章ID为1,2,3的文章分类 category = Category.objects.filter(article__id__in=[1,2,3])根据关联的表进行查询 想要获取文章标题中包含"hello"的所有的分类。
# 查询获取文章标题中包含"hello"的所有的分类。 categories = Category.objects.filter(article__title__contains="hello") categories = Category.objects.filter(article__title__icontains="hello")gt 某个field的值要大于给定的值。
# 将所有id大于4的文章全部都找出来。 articles = Article.objects.filter(id__gt=4) 将翻译成以下SQL语句: select * from articles where id > 4;gte 类似于gt,是大于等于。
lt 类似于gt是小于。
lte 类似于lt,是小于等于。
range 判断某个field的值是否在给定的区间中。
# range范围查询 查询文章id为1-3之间的文章 article = Article.objects.filter(id__range=(1,3)) print(article) start_date = datetime(year=2019, month=12, day=1) end_date = datetime(year=2019, month=12, day=30) # creat_time字段范围查询 date_range = Common.objects.filter(creat_time__range=(start_date,end_date)) print(date_range) 以上代码的意思是提取所有发布时间在2019/12/1到2019/12/29当天之间的文章。 将翻译成以下的SQL语句: SELECT `user_common`.`id`, `user_common`.`content`, `user_common`.`pid`, `user_common`.`test_date` FROM `user_common` WHERE `user_common`.`test_date` BETWEEN 2019-12-01 02:00:00 AND 2019-12-30 02:00:00。注意:MYSQL是没有时区的概念的,Django框架才有,需要下载MYSQL支持时区文件,参考:
默认情况下MySQL不装载时区,自动采用系统时区。 windows下装载时区的办法:
从http://dev.mysql.com/downloads/timezones.html页面下载时区文件;将压缩包中的文件(.frm、.MYD和.MYI文件)放到MySQL安装目录下的data目录下的mysql目录中,记得操作时退出MySQL,否则会失败。重启MySQL。