第七章:Django开发中数据库的高级使用

时间:2021-05-17 19:21:08

一、关于Django中的字段方法名与MySQL中字段匹配

MySQL字段 Django方法 描述 使用频率
int IntegerField 常用
samllint SmallIntegerField
varchar CharField 要指定长度 常用
text TextField 表示很多文字的时候使用
float FloatField 相当于python中float
date DateField 相当于python中的datetime.date,models.DateTimeField() 常用于时间
boolean BooleanField 如果没指定default,默认值是None
可空的boolean NullBooleanField 表示可以为空的布尔值
邮箱 EmailField max_length=254
文件地址 FilePathField
url字段 URLField 默认max_length=200
UUID字段 UUIDField UUIDField(default=uuid.uuid4) 常用

备注,直接利用上面的时间字段生成的时间会有因为时区差修改方式Django开发时区差处理方式

二、DjangoORM中的Field可以指定的字段

参数 作用 示例 使用频率
null 默认是False,如果指定为True,表示该字段可以为空 id = IntegerField(null=True) 常用
blank 默认是False,如果指定为True,表示可以为空,blank是django给表单添加的
default 给定默认值 CharField(default=’xx’) 常用
primary_key 主键 id = IntergerField(primary_key=True) 常用
unique 唯一的 id = IntergerField(unique=True) 常用
DateField.auto_now 每次修改都会将当前时间更新进去,只有调用Model.save()方法才会调用,QuerySet.update方法将不会调用。这个参数只是Date和DateTime以及Time类才有的 update_time = models.DateTimeField(auto_now=True,null=True) 常用
DateField.auto_now_add 第一次添加进去,都会将当前时间设置进去。以后修改,不会修改这个值 create_time = models.DateTimeField(auto_now_add=True,null=True) 常用

三、关于Django中外键ForeignKey的使用

  • 1、创建一个博客表,一个作者表,在博客表中添加一个外键约束,代码如下


    # 创建一个博客的数据模型

    class BlogModel(models.Model):
    id = models.AutoField(primary_key=True)
    title = models.CharField(max_length=100, null=False)
    content = models.TextField(null=False)
    create_time = models.DateTimeField(auto_now_add=True,null=True)
    update_time = models.DateTimeField(auto_now=True,null=True)
    #博客的作者,外键约束到作者表
    author = models.ForeignKey('AuthorModel',null=True)
    #修改表名字
    class Meta:
    db_table = 'bolog'


    # 创建一个作者的数据模型

    class AuthorModel(models.Model):
    author_name = models.CharField(max_length=20,null=True)
    age = models.IntegerField(null=True)

    #修改表名
    class Meta:
    db_table = 'author'
  • 2、在博客表中添加数据的时候使用到外键


    # 新增文章视图

    def add(request):
    if request.method == 'GET':
    return render(request, 'books_add.html')
    elif request.method == 'POST':
    #获取表单的内容
    title = request.POST.get('title',None)
    content = request.POST.get('content',None)
    blogModel = BlogModel(title=title,content=content,author=AuthorModel.objects.get(id = 1))
    blogModel.save()
    #重定向到新增页面
    return HttpResponseRedirect('book_add')
    else:
    return HttpResponse(u'是不被处理的请求方式')
  • 3、正向查找(博客表查找作者)

    • 1、博客对作者(多对一的关系)
    • 2、作者对博客(一对多的关系)

    # 测试的视图

    def test(request):
    blogModel = BlogModel.objects.get(id = 9)
    print '*'*100
    print blogModel.author
    print blogModel.author.author_name
    print blogModel.author.age
    print '*'*100
    return HttpResponse(u'我是测试的')
  • 4、反向查找(作者表查博客表)


    # 测试的视图

    def test(request):
    author = AuthorModel.objects.all().first()
    print '*'*100
    blogSet = author.blogmodel_set.all()
    print blogSet[0].title
    print '*'*100
    return HttpResponse(u'我是测试的')
    • 1、上面的反向查找用的是blogmodel_set(模型名_set),这个blogmodel_set(模型名_set)不是固定的,如果你反向查找BookModel就写bookmodel_set(模型名_set)
    • 2、使用查询返回的是一个QuerySet

四、多对多的关系,Django会默认创建一个中间表

  • 1、创建博客表与标签表,使用ManyToManyField进行多对多的关系


    # 创建一个博客的数据模型

    class BlogModel(models.Model):
    id = models.AutoField(primary_key=True)
    title = models.CharField(max_length=100, null=False)
    content = models.TextField(null=False)
    create_time = models.DateTimeField(auto_now_add=True, null=True)
    update_time = models.DateTimeField(auto_now=True, null=True)
    # 博客的作者,外键约束到作者表
    author = models.ForeignKey('AuthorModel', on_delete=models.CASCADE, null=True)
    # 一个博客可能有多个标签,一个标签也可以用在多个博客上,(多对多的关系)
    tag = models.ManyToManyField('TagModel', null=True)

    # 修改表名字
    class Meta:
    db_table = 'bolog'



    # 创建一个标签的模型

    class TagModel(models.Model):
    name = models.CharField(max_length=100)

    # 修改表名
    class Meta:
    db_table = 'tag'
  • 2、为博客表添加数据的时候带上标签(使用add添加)


    # 测试的视图

    def test(request):
    # 1.创建博客模型
    author = AuthorModel.objects.get(id = 2)
    blogModel = BlogModel(title='我是博客2',content='我是博客2的文章',author=author)
    # 2.博客模型数据保存
    blogModel.save()
    # 3.利用add添加tag
    tagModel = TagModel.objects.all()
    for tag in tagModel:
    blogModel.tag.add(tag)
    return HttpResponse(u'我是测试的')
  • 3、正向查找(博客表查询标签表)


    # 测试的视图

    def test(request):
    blogModel = BlogModel.objects.get(id = 12)
    print '*'*100
    # 由于这里查询的是多个所以要用.all()
    tags = blogModel.tag.all()
    html = ','.join(x.name for x in tags)
    print html
    print '*'*100
    return HttpResponse(u'我是测试的')
  • 4、反向查找(标签查找博客表)


    # 测试的视图

    def test(request):
    tag= TagModel.objects.get(id = 3)
    tagSet = tag.blogmodel_set.all()
    print '*'*100
    html = ','.join(x.title for x in tagSet)
    print html
    print '*'*100
    return HttpResponse(u'我是测试的')

五、关于QuerySet上常用的方法,查询最后返回的依旧是QuerySet类型

  • 1、all()查找所有的数据[不演示]
  • 2、first()查找第一个[不演示]
  • 3、get(fieldname= xx)[不演示],当查询不到的时候就会报错,建议用filter,
  • 4、filter()查询数据


    # 测试的视图

    def test(request):
    tag = TagModel.objects.all().filter(name='python')
    print '*'*100
    print tag
    print '*'*100
    return HttpResponse(u'我是测试的')
  • 5、contains模糊查询


    # 测试的视图

    def test(request):
    tag = TagModel.objects.all().filter(name__contains='py')
    print '*'*100
    print tag
    print '*'*100
    return HttpResponse(u'我是测试的')
  • 6、exclude()排除查询


    # 测试的视图

    def test(request):
    tag = TagModel.objects.exclude(name__contains='py')
    print '*'*100
    html = ','.join(x.name for x in tag)
    print html
    print '*'*100
    return HttpResponse(u'我是测试的')
  • 7、order_by()排序,默认是升序,如果要降序就-1操作


    # 测试的视图

    def test(request):
    author = AuthorModel.objects.all().order_by('age')
    print '*'*100
    html = ','.join(x.author_name for x in author)
    print html
    print '*'*100
    return HttpResponse(u'我是测试的')

    # 测试的视图

    def test(request):
    author = AuthorModel.objects.all().order_by('-age')
    print '*'*100
    html = ','.join(x.author_name for x in author)
    print html
    print '*'*100
    return HttpResponse(u'我是测试的')
  • 8、values()QuerySet数据类型转换为字典返回(常用于ajax请求返回数据)


    # 测试的视图

    def test(request):
    tag = TagModel.objects.all().values()
    print '*'*100
    print tag
    print '*'*100
    return HttpResponse(u'我是测试的')
  • 9、count()计算多少条数,不要用length


    # 测试的视图

    def test(request):
    tag = TagModel.objects.count()
    print '*'*100
    print tag
    print '*'*100
    return HttpResponse(u'我是测试的')
  • 10、latest(field_name=None)获取距离最近的一条数据,其中field_name必须是时间字段


    # 测试的视图

    def test(request):
    blogModel = BlogModel.objects.latest('create_time')
    print '*'*100
    print blogModel.title
    print '*'*100
    return HttpResponse(u'我是测试的')
  • 11、earliest(field_name=None)latest()一样的,只是获取距离最久的那个


    # 测试的视图

    def test(request):
    blogModel = BlogModel.objects.earliest('create_time')
    print '*'*100
    print blogModel.title
    print '*'*100
    return HttpResponse(u'我是测试的')
  • 12、last()first()一样的使用,获取最后一条数据


    # 测试的视图

    def test(request):
    blogModel = BlogModel.objects.all().last()
    print '*'*100
    print blogModel.title
    print '*'*100
    return HttpResponse(u'我是测试的')
  • 13、update()更新数据


    # 测试的视图

    def test(request):
    blogModel = BlogModel.objects.filter(id=8).update(title='晨曦')
    print '*'*100
    print blogModel #返回的是发生变化的条数
    print '*'*100
    return HttpResponse(u'我是测试的')
  • 14、delete()删除数据

六、根据条件查询数据

  • 1、exact相当于等号

    select * from 表名 where title = 'xx'

    # 测试的视图

    def test(request):
    blogModel = BlogModel.objects.filter(title__exact='xx')
    blogModel1 = BlogModel.objects.filter(title= 'xx')
    print '*'*100
    print blogModel[0].content
    print blogModel1[0].content
    print '*'*100
    return HttpResponse(u'我是测试的')
  • 2、iexactexact一样的使用,只是忽视大小写查询数据

  • 3、contains字段包含,用户模糊查询


    # 测试的视图

    def test(request):
    tag = TagModel.objects.filter(name__contains='py')
    print '*'*100
    print tag
    print '*'*100
    return HttpResponse(u'我是测试的')
  • 4、icontainscontains一样的使用,只是忽视大小写的查询

  • 5、startswith以什么开始


    # 测试的视图

    def test(request):
    # 计算以py开头的条数
    tag = TagModel.objects.filter(name__startswith='py').count()
    print '*'*100
    print tag
    print '*'*100
    return HttpResponse(u'我是测试的')
  • 6、istartswith跟上面的使用一样的,只是忽视大小写

  • 7、endswith以什么结尾,跟上面startswith用法一样的
  • 8、iendswith跟上面的使用一样的
  • 9、in判断是否在里面


    # 测试的视图

    def test(request):
    # 查询年龄在18-20之间的
    author = AuthorModel.objects.filter(age__in=[18,20])
    print '*'*100
    print ','.join(x.author_name for x in author)
    print '*'*100
    return HttpResponse(u'我是测试的')
  • 10、gt大于


    # 测试的视图

    def test(request):
    #查询年龄大于17的
    author = AuthorModel.objects.filter(age__gt=17)
    print '*'*100
    print ','.join(x.author_name for x in author)
    print '*'*100
    return HttpResponse(u'我是测试的')
  • 11、gte大于等于,跟上面一样的使用

  • 12、lt小于,跟上面一样的使用
  • 13、lte小于等于,跟上面一样的使用
  • 14、range返回一个区间的,跟上面的in效果差不多,但是用于时间区域会更好


    # 测试的视图

    def test(request):
    startTime = '2017-07-23 14:54:52'
    endTime = '2017-07-23 16:09:38'
    # 计算一个事件区域的查询个数,包括头部与尾部
    blogModel = BlogModel.objects.filter(create_time__range=(startTime,endTime)).count()
    print '*'*100
    print blogModel
    print '*'*100
    return HttpResponse(u'我是测试的')
  • 15、isnull判断是否为空

  • 16、切片操作,跟python的使用一样的,只是不能为负数