实用型的DJANGO ORM

简介: 比较深入一点的内容,需要用时,用心看看。 URL:   https://www.sitepoint.com/doing-more-with-your-django-models/ https://www.

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

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)
目录
相关文章
|
8月前
|
存储 关系型数据库 数据库
Django创建应用、ORM的进阶使用及模型类数据库迁移1
Django创建应用、ORM的进阶使用及模型类数据库迁移1
75 0
|
7月前
|
SQL 关系型数据库 MySQL
Django入门ORM(Django操作MySQL) 专题一
Django入门ORM(Django操作MySQL) 专题一
|
8月前
|
存储 数据可视化 数据库
Django创建应用、ORM的进阶使用及模型类数据库迁移3
Django创建应用、ORM的进阶使用及模型类数据库迁移3
54 0
|
8月前
|
关系型数据库 MySQL 数据库
Django创建应用、ORM的进阶使用及模型类数据库迁移2
Django创建应用、ORM的进阶使用及模型类数据库迁移2
49 0
|
16天前
|
Oracle 关系型数据库 MySQL
Django框架ORM操作(二)
Django框架ORM操作(二)
|
16天前
|
SQL 存储 前端开发
Django框架ORM操作(一)
Django框架ORM操作(一)
Django框架ORM操作(一)
|
19天前
|
SQL 缓存 数据库
在Python Web开发过程中:数据库与缓存,如何使用ORM(例如Django ORM)执行查询并优化查询性能?
在Python Web开发中,使用ORM如Django ORM能简化数据库操作。为了优化查询性能,可以:选择合适索引,避免N+1查询(利用`select_related`和`prefetch_related`),批量读取数据(`iterator()`),使用缓存,分页查询,适时使用原生SQL,优化数据库配置,定期优化数据库并监控性能。这些策略能提升响应速度和用户体验。
18 0
|
5月前
|
SQL 数据库 开发者
Python Web 开发: 什么是 Django ORM?如何使用它进行数据库操作?
Python Web 开发: 什么是 Django ORM?如何使用它进行数据库操作?
|
29天前
|
SQL 缓存 数据库
Django ORM的性能优化:高效处理大量数据
【4月更文挑战第15天】本文介绍了优化Django ORM性能的六大技巧:1) 使用批量操作如bulk_create和bulk_update;2) 利用prefetch_related和select_related减少查询次数;3) 为常用字段添加索引;4) 优化数据库查询,避免循环查询;5) 使用缓存提升频繁查询性能;6) 在必要时使用原生SQL。这些策略能帮助处理大量数据时提升Django ORM的效率。
|
29天前
|
SQL 自然语言处理 数据库连接
Django ORM的魔力:简化数据库操作与迁移
【4月更文挑战第15天】Django ORM是Django框架的关键部分,提供了一种高级的面向对象方式与数据库交互,简化了手动SQL操作。通过定义Python数据模型,开发者能轻松创建数据库表结构,使用ORM执行查询、添加、修改和删除数据。Django ORM还自动化处理数据库连接、事务和数据类型转换。当模型变化时,Django的迁移工具帮助管理数据库结构的更新。通过这种方式,Django ORM促进了高效、专注于业务逻辑的Web开发。