2016-08-01 5 views
2

最初にモデルをソートしてからスコアでソートしたいので、毎日最高の得点記事を表示したいと思っています。私はポストと同じエラーを取得し、私はそれがこれを動作するはずにもわからないんだけどしかしDjango日付でソートする(日)

Article.objects.filter().order_by('-date_modified__day', '-score') 
FieldError: Cannot resolve keyword 'day' into field. Join on 'date_modified' not permitted. 

class Article(models.Model): 

date_modified = models.DateTimeField(blank=True, null=True) 
score = models.DecimalField(max_digits=5, decimal_places=3, blank=True, null=True) 

この回答Django Datetime Field Query - Order by Time/Hourは、私はのように私のdate_modified'__day'を使用することを示唆しています方法。

私は他の答えを見つけたdjango order by date in datetime/extract date from datetime.extraを使用して:

Article.objects.filter().extra(select={"day_mod": "strftime('%d', date_modified)"}, order_by=['-day_mod', '-score']) 

これはありません、他の条件でフィルタリングするために動作しますが、私は、このようなカテゴリーとしてフィルタに条件を適用した場合:

Article.objects.filter(category = 'Art').extra(select={'day_mod': "strftime('%d', date_modified)"}, order_by=['-day_mod', '-score']) 

私はこのエラーが発生する:

File "/home/mykolas/anaconda2/lib/python2.7/site-packages/IPython/core/formatters.py", line 699, in __call__ 
printer.pretty(obj) 

File "/home/mykolas/anaconda2/lib/python2.7/site-packages/IPython/lib/pretty.py", line 383, in pretty 
return _default_pprint(obj, self, cycle) 

File "/home/mykolas/anaconda2/lib/python2.7/site-packages/IPython/lib/pretty.py", line 503, in _default_pprint 
_repr_pprint(obj, p, cycle) 

File "/home/mykolas/anaconda2/lib/python2.7/site-packages/IPython/lib/pretty.py", line 694, in _repr_pprint 
output = repr(obj) 

File "/home/mykolas/lenv/lib/python2.7/site-packages/django/db/models/query.py", line 234, in __repr__ 
data = list(self[:REPR_OUTPUT_SIZE + 1]) 

File "/home/mykolas/lenv/lib/python2.7/site-packages/django/db/models/query.py", line 258, in __iter__ 
self._fetch_all() 

File "/home/mykolas/lenv/lib/python2.7/site-packages/django/db/models/query.py", line 1074, in _fetch_all 
self._result_cache = list(self.iterator()) 

File "/home/mykolas/lenv/lib/python2.7/site-packages/django/db/models/query.py", line 52, in __iter__ 
results = compiler.execute_sql() 

File "/home/mykolas/lenv/lib/python2.7/site-packages/django/db/models/sql/compiler.py", line 848, in execute_sql 
cursor.execute(sql, params) 

File "/home/mykolas/lenv/lib/python2.7/site-packages/django/db/backends/utils.py", line 83, in execute 
sql = self.db.ops.last_executed_query(self.cursor, sql, params) 

File "/home/mykolas/lenv/lib/python2.7/site-packages/django/db/backends/sqlite3/operations.py", line 146, in last_executed_query 
return sql % params 

TypeError: %d format: a number is required, not unicode 

本当にわからないここには、助けに感謝します。

答えて

1
from django.db.models import DateTimeField 
from django.db.models.functions import Trunc 

Article.objects.order_by(
    Trunc('date_modified', 'date', output_field=DateTimeField()).desc(), 
    '-score') 
+0

ありがとうございます。 Django 1.10の完璧なタイミング:) – Xlrv

1

私は余分な方法なしで、スタンダードの日付の順序を使用する必要がありますね。フォーマット処理はテンプレートの責任です。

Article.objects.filter(category='Art').order_by=('-date_modified', '-score') 

テンプレートでは、必要な形式で日付を表示できます。私はあなたに例を残して、more optionsのAPIドキュメントを参照してください。

{{ date_modified|date:"M/d"|lower }} 

別の例(多分MOR、適切なニーズのために):

{{ date_modified|date:"D d M Y" }} {{ date_modified|time:"H:i" }} 
+0

これは完全に問題が解決しない、あなたの提案された解決策は入れますスコアに関係なく、最新の修正記事がトップに表示されます。 Xlrvが望んでいるのは、(時間に関係なく)その日までに注文してからスコアを注文することです。 –

2

あなたがFunc表現を使用することができますジャンゴ> = 1.8を使用している場合。あなたが抱えている問題は%という表記法がデータベースアダプタに直接渡され、%を関連するパラメータに置き換えようとしていることです。

from django.db.models import F, Func, Value 

Article.objects.annotate(
    day_mod=Func(Value('%d'), F('date_modified'), 
    function='strftime' 
).order_by('-day_mod', '-score') 

これは(理論的には、私はそれをテストしていない)必要があり、このようなSQLクエリで終わる:

あなたはこのようにそれを使用することができます

SELECT 
    ... 
    strftime('%d', "article"."date_modified") AS "day_mod" 
FROM "article" 
    ... 
ORDER BY "day_mod" DESC, "score" DESC 

は、しかし、私は疑いますstrftimeに年と月を追加する必要があります。そうしないと、月の初めの記事が前月末に発生した古い記事に埋もれてしまいます。

strftime関数は、MySQLまたはPostgreSQLではサポートされていないことにも注意してください。限り、私はそれが生産で使用すべきではないSQLiteによってのみサポートされていることを伝えることができます。

残念ながら、SQLの日時フォーマットの標準とは思われません。 MySQLはDATE_FORMAT(date, format)、PostgreSQLはto_char(date, format)を使用しているようです。

あなたは両方のSQLiteと他のDBをサポートしたい場合は、することはできませんすべてのDBは、同じ書式文字列を使用して、あなたの日付時刻をフォーマットしますが、それは少し難しいかもしれない関連as_sqliteas_<db>方法でwrite a custom expression

おそらく、日時を現在までキャストしている、つまりCAST (date_modified AS DATE)です。これはSQLのほとんどのフレーバーで動作するはずです。私が思い付くことができます最も簡単な方法は次のとおりです。

from django.db.models import DateField, Expression, F 

class CastToDate(Expression): 
    template = 'CAST(%(expressions)s AS DATE)' 

    def __init__(self, expressions, output_field=None, **extra): 
     output_field = output_field or DateField() 
     super(CastToDate, self).__init__(self, expressions, output_field, **extra) 
     if len(expressions) != 1: 
      raise ValueError('expressions must have exactly 1 element') 

Articles.objects.annotate(
    day_mod=CastToDate(F('date_modified'))).order_by('-day_mod', '-score') 
+0

答えVilliersのおかげで、私はそれがより簡潔であるとして受け入れられたようにウラジミールを選んだ。 Django 1.10にいない人たちもあなたの答えを見るでしょう。 – Xlrv