比较深入一点的内容,需要用时,用心看看。

URL:

https://www.sitepoint.com/doing-more-with-your-django-models/

https://www.sitepoint.com/doing-more-with-your-django-models/

  

So you have a Django app, but sometimes you find the Django models too constraining. We will guide you through using Django models to get more out of them. This is an intermediate tutorial, as some familiarity with Django is assumed. For example, we assume you know how to write a basic Django model, you know how to override Python methods, as well as how .filter and .exclude work.

We will talk about these topics

  1. Proxy Models
  2. Overriding .save
  3. Using signals
  4. Optimizing your DB access using .extra
  5. Advanced lookups using Q objects
  6. Aggregation and Annotation
  7. Using F() expressions

Lets look at some common operations you may want to perform using Django and how the above Django functionality will help you achieve them.

How can I get two Python representation of the same Database table?

You may want to have two model classes corresponding to a single database table. For example,admin.site.register allows a Model to be registered only once. However, you may want the same model twice in the Admin area. Proxy models can help you do that!

from django.contrib.auth.models import User

class NewUser(User):
    class Meta:
        proxy = True

Now in your admin.py you can register NewUser again and customize your ModelAdmin. (For example, if you want to show only some of the fields, add a custom ordering and so on).

How can I take action before saving a model to database?

Sometime you may have some denormalized data. Consider this model:

class Poll(models.Model):
    ###...
    num_choices = models.PositiveIntegerField()

class Choice(models.Model):
    poll = models.ForeignKey(Poll)
    ###...

You want to increment the num_choices before saving Choice. You can do that by overriding .save like this.

def save(self, *args, **kwargs):
    self.poll.num_choices += 1
    self.poll.save()
    super(Choice, self).save(*args, **kwargs)

How can I take action before saving the models to database if I didn’t write the model?

Overriding .save is great when you are writing all the models. However for example you have aSubscription model and when someone sings up they are assigned a subscription. However since you didn’t write the User model, you can not override the .save model.

Django emits signals before taking any action. You can connect your functions to signals to take action when interesting stuff happens. Django comes with two signals
pre_save and post_save which you can connect to.

from django.db.models.signals import pre_save
from django.contrib.auth.models import User

def subscription_handler(**kwargs):
    #Do something with the Subscription model

pre_save.connect(subscription_handler, sender=User, dispatch_uid="subscription_handler")

How can I get related objects without hitting the database many times?

Assume we have these models:

class Subject(models.Model):
    ###...

class Score(models.Model):
    ###...
    subject = models.ForeignKey(Subject)
    score = models.PositiveIntegerField()

Now you are iterating over a Subject queryset, and you want the sum of all the Score objects which have a foreign key to current object. You can do this by getting individual Score objects and then summing them in Python, but it would be faster to do that in the database. Django has a method .extra which allows you to insert arbitrary clauses in the sql generated by the queryset. For example here you can do

Subject.objects.extra(select={"total_scores": "select sum(score) from poll_score where poll_score.subject_id = poll_subject.id"})

assuming that the app is called poll for which the default names for tables are poll_subject andpoll_score.

How can you compose OR, NOT and other SQL operations?

By default Django will AND all criteria passed to the filtering methods. If you want to use OR/NOT operator, you will need to use Q objects.

We have a model like:

class Score(models.Model):
    ###...
    subject = models.ForeignKey(Subject)
    score = models.PositiveIntegerField()
    date = models.DateField()

So, if you want all Score objects for Physics which have either score > 95 or are in 2012.

    criteria = Q(subject__name="Physics") & (Q(score__gt=95)|Q(date__year=2012))

We used the double underscore notation to apply filters and joined them together using boolean operators. You can pass them to .filter. (Or to .exclude)

Score.objects.filter(criteria)

How can I get group_by type of operations?

Django provides two methods on its querysets – .aggregate and .annotate. Aggregates convert the queryset in a dictionary on name, value pairs.

E.g., if you want the maximum, minimum, and average of Score objects. You can get them as

from django.db.models import Avg, Max, Min

Score.objects.all().aggregate(Max('score'), Avg('score'), Min('score'))

For more, see the guide on aggregation

How can I compare within rows?

Django provides F objects which are used to create queries which compare within rows.

We have a model like this:

class Department(models.Model):
    ##...
    num_employees = models.PositiveIntegerField()
    num_managers = models.PositiveIntegerField()

You want to find all departments which have more managers than employees.

from django.db.models import F
Department.objects.filter(num_managers__gt=F('num_employees'))

F objects support addition, subtraction, multiplication, division so you can do things like

Department.objects.filter(num_employees__lt=F('num_managers')*2)

实用型的DJANGO ORM的更多相关文章

  1. django orm总结[转载]

    django orm总结[转载] 转载地址: http://www.cnblogs.com/linjiqin/archive/2014/07/01/3817954.html 目录1.1.1 生成查询1 ...

  2. Django ORM - 001 - 外键表查询主表信息

    开始用Django做web开发,我想大家都会遇到同样的问题,那就是如何高效快速的查询需要的数据,MVC都很简单,但是ORM折腾起来就有些费时间,我准备好好研究下Django ORM,所以会有一个系列的 ...

  3. Django ORM 中的批量操作

    Django ORM 中的批量操作 在Hibenate中,通过批量提交SQL操作,部分地实现了数据库的批量操作.但在Django的ORM中的批量操作却要完美得多,真是一个惊喜. 数据模型定义 首先,定 ...

  4. Django ORM 查询管理器

    Django ORM 查询管理器 ORM 查询管理器 对于 ORM 定义: 对象关系映射, Object Relational Mapping, ORM, 是一种程序设计技术,用于实现面向对象编程语言 ...

  5. Django ORM模型的一点体会

    作者:Vamei 出处:http://www.cnblogs.com/vamei 严禁转载. 使用Python的Django模型的话,一般都会用它自带的ORM(Object-relational ma ...

  6. 数据库表反向生成(二) Django ORM inspectdb

    在前一篇我们说了,mybatis-generator反向生成代码. 这里我们开始说如何在django中反向生成mysql model代码. 我们在展示django ORM反向生成之前,我们先说一下怎么 ...

  7. Django ORM那些相关操作

    一般操作 https://docs.djangoproject.com/en/1.11/ref/models/querysets/         官网文档 常用的操作 <1> all() ...

  8. django orm 及常用参数

    一些说明: 表myapp_person的名称是自动生成的,如果你要自定义表名,需要在model的Meta类中指定 db_table 参数,强烈建议使用小写表名,特别是使用MySQL作为后端数据库时. ...

  9. Django ORM中,如何使用Count来关联对象的子集数量

    示例models 解决方法 有时候,我们想要获取一个对象关联关系的数量,但是我们不要所有的关联对象,我们只想要符合规则的那些关联对象的数量. 示例models # models.py from dja ...

随机推荐

  1. CSS左侧固定右侧自适应

    方法一: float + margin.left{ float: left; width: 100px; }.right {margin-left:100px; } /*清除浮动*/ .contain ...

  2. StackOverflow 创始人关于如何高效编程的清单

    这是 StackOverflow 联合创始人 Jeff Atwood 注释的十戒.程序员普遍有很强的自尊心,都应该看看本文,打印下来时刻提醒自己. “无我编程”发生在开发阶段,表现为技术团队经常通过同 ...

  3. ASP.Net 知识点总结(三)

    1.描述一下C#中索引器的实现过程,是否只能根据数字进行索引? 答:不是.可以用任意类型. 2.<%# %> 和 <% %> 有什么区别? 答:<%# %>表示绑定 ...

  4. 树形DP UVA 1292 Strategic game

    题目传送门 /* 题解:选择一个点,它相邻的点都当做被选择,问最少选择多少点将所有点都被选择 树形DP:dp[i][0/1]表示当前点选或不选,如果选,相邻的点可选可不选,取最小值 */ /***** ...

  5. 405 Convert a Number to Hexadecimal 数字转换为十六进制数

    给定一个整数,编写一个算法将这个数转换为十六进制数.对于负整数,我们通常使用 补码运算 方法.注意:    十六进制中所有字母(a-f)都必须是小写.    十六进制字符串中不能包含多余的前导零.如果 ...

  6. cocos creator 场景如何透明,多个canvas层级显示

    转载地址:https://forum.cocos.com/t/creator-canvas/55373/14 Creator 版本:1.7 目标平台:WEB MOBILE 项目需要,页面做了多个Can ...

  7. 构建一个.net的干货类库,以便于快速的开发 - 加密

    在开发程序的时候,加密是一个程序一个必须的功能,基本上任何程序都会用到加密,而不同的加密方式又适应不同需求,有些加密是不可逆的,最常见是用于用户密码的加密,因为很多时候程序里面不该显示出用户的明文密码 ...

  8. Git学习笔记(0)-错误汇总

    一.LF will be replaced by CRLF 1.发现问题 $ git add welcome.txt warning: LF will be replaced by CRLF in w ...

  9. [ SDOI 2006 ] 保安站岗

    \(\\\) Description 给出一棵 \(n\) 个节点以 \(1\) 为根的树,一个节点的覆盖半径是 \(1\) ,点有点权 \(val_x\) . 选择一些点,使得点权和最小,同时每个节 ...

  10. String field contains invalid UTF-8 data when serializing a protocol buffer. Use the 'bytes' type if you intend to send raw bytes.

    [libprotobuf ERROR google/protobuf/wire_format.cc:1053] String field contains invalid UTF-8 data whe ...