En tant que Simon says, vous pouvez désormais utiliser des expressions dans les requêtes et ces valeurs seront calculées dans la base de données. Voici les questions que vous avez posées au sujet de la nouvelle technique de tri:
Foo.objects.order_by(F('a') - F('b'))
Foo.objects.order_by(F('a') - F('bar__x'))
Voici un exemple complet runnable qui joue avec ces expressions: juste signaler
# Tested with Django 1.9.2
import logging
import sys
import django
from django.apps import apps
from django.apps.config import AppConfig
from django.conf import settings
from django.db import connections, models, DEFAULT_DB_ALIAS
from django.db.models import F
from django.db.models.base import ModelBase
from django.db.models.functions import Concat, Value
from mock import patch, PropertyMock, MagicMock
NAME = 'udjango'
def main():
setup()
class Bar(models.Model):
x = models.IntegerField()
class Foo(models.Model):
a = models.IntegerField()
b = models.IntegerField()
bar = models.ForeignKey(Bar)
syncdb(Bar)
syncdb(Foo)
bar1 = Bar.objects.create(x=1)
bar5 = Bar.objects.create(x=5)
Foo.objects.create(a=10, b=3, bar=bar1)
Foo.objects.create(a=13, b=3, bar=bar5)
Foo.objects.create(a=15, b=9, bar=bar1)
print(Foo.objects.annotate(ordering=F('a') - F('b'))
.order_by('ordering').values_list('a', 'b', 'bar__x', 'ordering'))
# >>> [(15, 9, 1, 6), (10, 3, 1, 7), (13, 3, 5, 10)]
print(Foo.objects.annotate(ordering=F('a') - F('bar__x'))
.order_by('ordering').values_list('a', 'b', 'bar__x', 'ordering'))
# >>> [(13, 3, 5, 8), (10, 3, 1, 9), (15, 9, 1, 14)]
print(Foo.objects.order_by(F('a') - F('b')).values_list('a', 'b', 'bar__x'))
# >>> [(15, 9, 1), (10, 3, 1), (13, 3, 5)]
print(Foo.objects.order_by(F('a') - F('bar__x')).values_list('a', 'b', 'bar__x'))
# >>> [(13, 3, 5), (10, 3, 1), (15, 9, 1)]
logging.info('Done.')
def setup():
db_file = NAME + '.db'
with open(db_file, 'w'):
pass # wipe the database
settings.configure(
DEBUG=True,
DATABASES={
DEFAULT_DB_ALIAS: {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': db_file}},
LOGGING={'version': 1,
'disable_existing_loggers': False,
'formatters': {
'debug': {
'format': '%(asctime)s[%(levelname)s]'
'%(name)s.%(funcName)s(): %(message)s',
'datefmt': '%Y-%m-%d %H:%M:%S'}},
'handlers': {
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler',
'formatter': 'debug'}},
'root': {
'handlers': ['console'],
'level': 'INFO'},
'loggers': {
"django.db": {"level": "DEBUG"}}})
app_config = AppConfig(NAME, sys.modules['__main__'])
apps.populate([app_config])
django.setup()
original_new_func = ModelBase.__new__
# noinspection PyDecorator
@staticmethod
def patched_new(cls, name, bases, attrs):
if 'Meta' not in attrs:
class Meta:
app_label = NAME
attrs['Meta'] = Meta
return original_new_func(cls, name, bases, attrs)
ModelBase.__new__ = patched_new
def syncdb(model):
""" Standard syncdb expects models to be in reliable locations.
Based on https://github.com/django/django/blob/1.9.3
/django/core/management/commands/migrate.py#L285
"""
connection = connections[DEFAULT_DB_ALIAS]
with connection.schema_editor() as editor:
editor.create_model(model)
main()
qu'une question similaire a été posée: http : //stackoverflow.com/questions/930865/how-to-sort-by-a-computed-value-in-django – cethegeek