• Django点滴(四)ORM对象存取


    ps: 看了昆汀塔伦蒂诺的新片,Django原来d不发音啊,所以应该念“姜戈”(类似jungle的发音)。


    无论是RoR还是Django,甚至颇具野心的前端框架EmberJs.data,将ORM集成于框架之中并赋予方便存储的API,大大提高了开发效率。不像Java世界中的Hibernate弄了个HQL查询语言,Django这里利用动态语言的优势,令CRUD语义更加自然(EJB3.0中JPA其实也有类似的意思)。当然你还是可以用纯粹的sql直接操作。

    https://docs.djangoproject.com/en/dev/ref/models/instances/


    这里先跳过如何用django.Models对数据库建模。假设已经存在下列ORM对象定义,Blog<-(一对一)->Entry<-(一对多)->Author。

    class Blog(models.Model):
        name = models.CharField(max_length=100)
        tagline = models.TextField()
    
        def __unicode__(self):
            return self.name
    
    class Author(models.Model):
        name = models.CharField(max_length=50)
        email = models.EmailField()
    
        def __unicode__(self):
            return self.name
    
    class Entry(models.Model):
        blog = models.ForeignKey(Blog)
        headline = models.CharField(max_length=255)
        body_text = models.TextField()
        pub_date = models.DateField()
        mod_date = models.DateField()
        authors = models.ManyToManyField(Author)
        n_comments = models.IntegerField()
        n_pingbacks = models.IntegerField()
        rating = models.IntegerField()
    
        def __unicode__(self):
            return self.headline

    基本CRUD操作

    from blog.models import Blog, Entry, Author
    
    blog = Blog(name='Beatles Blog', tagline='All the latest Beatles news.')
    blog.save()
    
    entry = Entry.objects.get(pk=1)
    blog = Blog.objects.get(name="Beatles Blog")
    entry.blog = blog   # ForeignKey
    entry.save()
    
    john = Author.objects.create(name="John")
    paul = Author.objects.create(name="Paul")
    george = Author.objects.create(name="George")
    ringo = Author.objects.create(name="Ringo")
    entry.authors.add(john, paul, george, ringo)   # ManyToManyField
    
    all_author = Author.objects.all()
    
    blog.delete()
    
    Entry.objects.filter(pub_date__year=2007).update(headline='Everything is the same')
    Entry.objects.all().update(n_pingbacks=F('n_pingbacks') + 1)



    查询过滤器

    分为 filter(**kwargs)exclude(**kwargs)两种,前者是包含条件查询,后者是不包含条件查询。都返回QuerySet集合,并且可以级联查询。
    如果明确地查询唯一对象,可以使用 get(**kwargs)

    如果查询所有对象,使用all()就行。


    Entry.objects.filter(
         headline__startswith='What'
     ).exclude(
         pub_date__gte=datetime.date.today()
     ).filter(
         pub_date__gte=datetime(2005, 1, 30)
     )

    查询条件的交并集问题:
    ### 查询结果要同时满足两个条件的交集
    Blog.objects.filter(entry__headline__contains='Lennon', entry__pub_date__year=2008)
    ### 查询结果是分别满足两个条件的并集
    Blog.objects.filter(entry__headline__contains='Lennon').filter(entry__pub_date__year=2008)

    查询表达式

    (注意字段名后面是两个下划线,再加查询表达式)。

    比较,lte, le, gt, gte :
    ### SELECT * FROM blog_entry WHERE pub_date <= '2006-01-01';
    Entry.objects.filter(pub_date__lte='2006-01-01') 

    (精确)相等, id, pk:
    ### SELECT ... WHERE id = 14;
    Blog.objects.get(id=14) 


    包含:
    ### SELECT ... WHERE headline LIKE '%Lennon%';
    Entry.objects.get(headline__contains='Lennon')

    此外,还有icontains、startswith、endswith、isnull, in, 等


    关系传递的查询表达式

    对某个对象的外键或关联对象直接作为查询条件。
    Entry.objects.filter(blog__name__exact='Beatles Blog')
    Blog.objects.filter(entry__authors__name='Lennon')
    Blog.objects.filter(entry__authors__isnull=False, entry__authors__name__isnull=True)



    分片查询

    以下等同于 SELECT  *   FROM  Entry  OFFSET 5  LIMIT  3
    Entry.objects.all()[5:8]

    F表达式(F Expression)

    之前的查询表达式的右侧都是常量,而F表达式用于引用被查询对象的其他字段。
    (n_xxx表示xxx字段按照数字类型处理。)
    from django.db.models import F
    from datetime import timedelta
    
    Entry.objects.filter(n_comments__gt=F('n_pingbacks') * 2)
    Entry.objects.filter(rating__lt=F('n_comments') + F('n_pingbacks'))
    Entry.objects.filter(authors__name=F('blog__name'))
    Entry.objects.filter(mod_date__gt=F('pub_date') + timedelta(days=3))
    F('somefield').bitand(16)

    利用Q对象(Q Object)的复杂查询

    一旦查询条件使用了Q对象,所有条件就都必须是Q对象。Q对象可以用& (And), | (Or), ~ (Not)来运算。
    from django.db.models import Q
    
    ### SELECT * from polls WHERE question LIKE 'Who%' AND (pub_date = '2005-05-02' OR pub_date = '2005-05-06')
    Poll.objects.get(
        Q(question__startswith='Who'),
        Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6))
    )
    

    复制对象

    将pk设为None后保存,即可生成新记录。如果对象有继承关系,还要将pk和id都设为None才行。

    blog = Blog(name='My blog', tagline='Blogging is easy')
    blog.save() # blog.pk == 1
    
    blog.pk = None
    blog.save() # blog.pk == 2
    
    class ThemeBlog(Blog):
        theme = models.CharField(max_length=200)
    
    django_blog = ThemeBlog(name='Django', tagline='Django is easy', theme='python')
    django_blog.save() # django_blog.pk == 3
    
    django_blog.pk = None
    django_blog.id = None
    django_blog.save() # django_blog.pk == 4


    注意,复制对象不会复制原有对象的关系,需要手动复制。

    entry = Entry.objects.all()[0] # some previous entry
    old_authors = entry.authors.all()
    entry.pk = None
    entry.save()
    entry.authors = old_authors # saves new many2many relations

    访问关系对象

    无论是外键,还是一对多,多对多关系,都需要访问其他关系对象。

    一对一关系时,正向、反向访问都直接用字段名即可。

    一对多关系时,正向访问用字段名,反向访问用字段名加上"_set"后缀。关系对象集可以用add, remove, create, clear,count, filter等来操作。

    Entry.objects.get(id=2).blog
    Entry.objects.get(id=2).authors.filter(name__contains='John')
    Blog.objects.get(id=1).entry_set.all()
    






  • 相关阅读:
    <img />标签 alt title
    ubuntu中rar与unrar用法详解
    vi及缩进设置
    ubuntu下读取数据库中文乱码解决
    ubuntu下phpstorm无法输入中文的解决办法
    ubuntu下mysqli_connect()显示未定义,mysqli_fetch_all()显示未定义 解决方法
    权限控制
    NULL
    ubuntu下chromium 安装flash player
    手把手教你把Vim改装成一个IDE编程环境(图文)
  • 原文地址:https://www.cnblogs.com/jiangu66/p/3003874.html
Copyright © 2020-2023  润新知