• Django之ORM操作


     此篇依赖于上一篇:Django之模型注册

    我们在models.py中定义的表结构,在admin.py中将它们注册进去了,现在我们登陆django admin界面就会看到我们注册的所有表。

     数据如下:

    现在我们来拿Blog表,进行增删改查操作,它总共两个字段name,tagline。

    进入项目目录下,执行:

     增删改

    增加记录

    python manager.py shell
    from orm.models import Blog
    b = Blog(name="javaScript",tagline="java model")
    b.save()
    或
    Blog(name="Windows",tagline="Windows model").save()
    或
    Blog.objects.create(name="Onesen",tagline="Onesen Ui")
    

    删除记录

    Blog.objects.filter(name="Linux").delete()
    

    修改记录

    Blog.objects.filter(name="Onesen").update(tagline="TwoSen")
    Entry.objects.filter(pub_date__year=2007).update(headline='Everything is the same')
    # 将原有数据批量自增
    Entry.objects.all().update(n_pingbacks=F('n_pingbacks') + 1)
    

    关联:

    以Blog表和Entry表的关联为例

    ForeignKey的关联修改

    # Blog表是Entry表的外键
    from orm.models import Entry
    # 找出一条Blog记录
    cheese_blog = Blog.objects.get(name="Windows")
    # 找出一条Entry记录
    entry = Entry.objects.get(pk=1)
    # 将Entry表的blog与查询到的blog关联
    entry.blog = cheese_blog
    # 保存Entry设置
    entry.save()
    

    ManyToManyField关联修改

     Entry表中authors = models.ManyToManyField(Author)

    以Author表和Entry表的关联人例,现在给Entry表的authors字段关联多个Author

    关联前

    开始关联

    # 从Author表中选择出3个对象
    from orm.models import Author
    author1 = Author.objects.get(pk=1)
    author2 = Author.objects.get(pk=2)
    author3 = Author.objects.get(pk=3)
    
    # 从Entry表中选择出一个对象
    from orm.models import Entry
    entry = Entry.objects.get(pk=1)
    # 将从Author表选择出的3个对象关联到Entry表选择出的1个对象中
    entry.authors.add(author1,author2,author3)
    

    关联后

    普通查询

     除了可以通过python manager.py shell来查询数据以外,还可以通过pycharm来查询数据。

    例如:

    #!/usr/bin/env python
    # _*_ coding:utf-8 _*_
    
    import os
    os.environ['DJANGO_SETTINGS_MODULE'] = 'Blog.settings'
    import django
    django.setup()
    
    from orm import models
    auth = models.Author.objects.get(pk=1)
    print auth
    

    单表查询

    #!/usr/bin/env python
    # _*_ coding:utf-8 _*_
    
    import os
    os.environ['DJANGO_SETTINGS_MODULE'] = 'Blog.settings'
    import django
    django.setup()
    
    
    import datetime
    from orm import models
    
    # 单条查询用get,不可返回多条数据
    models.Entry.objects.get(pk=1)
    models.Entry.objects.get(headline__exact='technology')
    models.Entry.objects.get(headline__iexact='technology')  # 大小写不敏感
    models.Entry.objects.get(headline__contains='nology')
    models.Entry.objects.get(headline__icontains='nology')
    # 多条查询用filter
    models.Entry.objects.filter(pub_date__year=2017)
    models.Entry.objects.all().filter(pub_date__year=2017)
    models.Entry.objects.filter(pub_date__gt='2017-03-30')
    # 排除用exclude
    datas = models.Entry.objects.filter(
        headline__startswith=u"文学"
    ).exclude(
        pub_date__gt=datetime.date.today()
    )
    # 查询出固定的条数用切片
    models.Entry.objects.all()[:2]
    # 排序操作用order_by
    models.Entry.objects.order_by('pub_date')[0]
    # 查询所有用all
    models.Entry.objects.all()
    

    关联查询

     不同表之间关联查询

    #!/usr/bin/env python
    # _*_ coding:utf-8 _*_
    
    import os
    os.environ['DJANGO_SETTINGS_MODULE'] = 'Blog.settings'
    import django
    django.setup()
    
    import datetime
    from orm import models
    
    # 与entry.headline模糊匹配tech的所有记录有关联的Blog表的所有记录
    models.Blog.objects.filter(entry__headline__contains='tech')
    # 与Blog.name精确匹配Windows的所有记录有关联的Entry表的所有记录
    models.Entry.objects.filter(blog__name__exact='Windows')
    

    同一张表的不同字段的操作

    #!/usr/bin/env python
    # _*_ coding:utf-8 _*_
    
    import os
    os.environ['DJANGO_SETTINGS_MODULE'] = 'Blog.settings'
    import django
    django.setup()
    
    from orm import models
    
    from django.db.models import F
    # 查询Entry表的所有记录,条件是n_pingbacks值大于n_comments
    models.Entry.objects.filter(n_pingbacks__gt=F('n_comments'))
    # 查询Entry表的所有记录,条件是n_pingbacks值大于rating*1.5
    models.Entry.objects.filter(n_pingbacks__gt=F('rating')*1.5)
    
    from datetime import timedelta
    # 查询Entry表的所有记录,条件是mod_date大于pub_date加3天
    models.Entry.objects.filter(mod_date__gt=F('pub_date') + timedelta(days=3))
    

    Caching and QuerySets

    每个QuerySet包含一个Cache来最小化数据库访问。明白它是如何工作的将有利于你写出高效的代码。
    当产生一个新的QuerySet时,它的Cache是空的。当第一次操作QuerySet时,发生了数据库查询,Django在返回精确请求结果的同时将查询结果保存在QuerySet的Cache中,随后对QuerySet的访问将重用Cache中的结果

    # 一次数据库查询,随后都是Cache访问
    queryset = Entry.objects.all()  # 产生空的QuerySet
    [entry for entry in queryset] # Queries the database,对QuerySet做了完全评估,此时QuerySet会Cache结果集
    print queryset[5] # Uses cache
    print queryset[5] # Uses cache
    
    # 此时会产生一次数据库查询,一次利用Cache
    queryset = Entry.objects.all()
    print([p.headline for p in queryset]) # Queries the database,对QuerySet做了完全评估,此时QuerySet会Cache结果集
    print([p.headline for p in queryset])
    
    # 两次数据库查询
    queryset = Entry.objects.all()
    print queryset[5]  # Queries the database,对QuerySet做了部分评估,此时QuerySet不Cache结果集
    print queryset[5]  # Queries the database again
    
    # 此时将会产生两次数据库查询
    print([e.headline for e in Entry.objects.all()])
    print([e.headline for e in Entry.objects.all()])
    

    复杂查询

    Q对象可用来封装查询关键字,需要从django.db.models中导入Q方法

    # Q实现一个简单的LIKE查询
    from django.db.models import Q
    Q(question__startswith='What')
    
    # 使用&或|来将两个Q对象组合成一个新的Q对象
    Q(question__startswith='Who') | Q(question__startswith='What')
    这个操作类似以下WHERE语句
    WHERE question LIKE 'Who%' OR question LIKE 'What%'
    # Q对象使用~来执行一个否操作
    Q(question__startswith='Who') | ~Q(pub_date__year=2005)
    
    # 如果同时罗列出多个Q查询,则它们会被AND到一起
    Poll.objects.get(
        Q(question__startswith='Who'),
        Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6))
    )
    换成SQL语句则为:
    SELECT * from polls WHERE question LIKE 'Who%'
        AND (pub_date = '2005-05-02' OR pub_date = '2005-05-06')
    		
    # 当Q对象和关键字参数结合使用的时候,Q对象必须放在关键字前面
    如,以下语句是合法的
    Poll.objects.get(
        Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)),
        question__startswith='Who')
    否则不合法
    Poll.objects.get(
        question__startswith='Who',
        Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)))	
    

    聚合查询

    #!/usr/bin/env python
    # _*_ coding:utf-8 _*_
    
    import os
    os.environ['DJANGO_SETTINGS_MODULE'] = 'Blog.settings'
    import django
    django.setup()
    
    from orm import models
    
    # 总计
    models.Entry.objects.count()
    models.Entry.objects.filter(headline__startswith='tech').count()
    
    # 平均值
    from django.db.models import Avg
    models.Entry.objects.aggregate(Avg('rating'))
    models.Entry.objects.all().aggregate(Avg('rating'))
    
    # 最大值
    from django.db.models import Max
    models.Entry.objects.aggregate(Max('rating'))
    models.Entry.objects.all().aggregate(Max('rating'))
    

    更多聚合查询的例子:https://docs.djangoproject.com/en/1.9/topics/db/aggregation/

    用户认证

    from django.contrib.auth import authenticate
    user = authenticate(username='john', password='secret')
    if user is not None:
        # the password verified for the user
        if user.is_active:
            print("User is valid, active and authenticated")
        else:
            print("The password is valid, but the account has been disabled!")
    else:
        # the authentication system was unable to verify the username and password
        print("The username and password were incorrect.")
    

    用户退出

    from django.contrib.auth import logout
     
    def logout_view(request):
        logout(request)
        # Redirect to a success page.
    
  • 相关阅读:
    公司内部图书管理界面原型设计图
    对象的判等
    虚方法的调用
    类的初始化顺序
    A good idea: TotT – Testing on the Toilet
    变量命名
    QSignalMapper
    dxsdk出错,代码写完后按这个solution试下
    SVG 我太土了。。
    gsl在vc下编译时一个问题
  • 原文地址:https://www.cnblogs.com/kongzhagen/p/6606058.html
Copyright © 2020-2023  润新知