2015-09-14 11 views
7

2つの列の連結を使用してモデルをフィルタリングする方法はありますか?私のモデルは、このようなものです:私は必要なもの2つの列を連結した後のDjangoクエリーセットフィルタ

class Item(models.Model): 
    series = models.CharField(max_length=50) 
    number = models.CharField(max_length=50) 

は、ユーザ入力のA123は、私は%のAのようなシリーズと番号を持っている任意の項目を見つけることができるようにしたい場合は、2列の連結後にフィルタリングすることで、 123%または%A1と23% これはdjangoモデルを使って可能ですか?または、生のSQLで可能ですか? 私はむしろ連結で新しい列を構成したくないです。

答えて

12

はい、可能です。フィールドの連結でQuerySetをannotateにする必要があり、その新しい "仮想"カラムでフィルタリングが可能になります。先に述べたものに加えて

relevant documentation on filtering annotations

using Concat as an annotation function

+0

おかげで注釈を付ける使用しています。私はここで説明したようにそれをやってみました: http://stackoverflow.com/questions/4348124/django-orm-filter-by-extra-attribute/4348728#4348728 しかし、私はいくつかのエラーを取得し、私もこのようにそれをやって疲れた: 請求書= invoices.extra( ここ= [ 'CONCAT(document_series_name、document_number)LIKE "%のF001の%"']、 ) を私は同じerros得た:範囲外 タプルインデックスを は/ usr/local/lib/python2.7/dist-packages/django/db/backends/postgresql_psycopg2/base.py in execute、行44 –

+1

これは、しばらく聞いていないバージョン番号です...ドキュメントはもはや利用できません!私はあなたが本当にすべきであっても、何らかの理由でアップグレードすることはできないと仮定しています。少なくともセキュリティ上の理由からです。とにかく、おそらくあなたの最善の策は、おそらく 'F()'式が利用可能かどうかをチェックすることです。 – mccc

+0

ありがとう、私は試してみる、答えはまだ有効です、ありがとう –

9

、例:

from django.db.models import Value 
from django.db.models.functions import Concat 
queryset = Item.objects.annotate(search_name=Concat('series', Value(' '), 'number')) 
# then you can filter: 
queryset.filter(search_name__icontains='whatever text') 
+0

"価値"とは何ですか? – Mojimi

+0

これは、カラム名の代わりに実際の文字列を使用する場合に使用する必要がある関数です – mccc

0

ここannotate() functionConcat expressionに基づいてフィルタリングする方法を示して完全な例です。

# Tested with Django 1.9.2 
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.base import ModelBase 
from django.db.models.functions import Concat 

NAME = 'udjango' 


def main(): 
    setup() 

    class Item(models.Model): 
     series = models.CharField(max_length=50) 
     number = models.CharField(max_length=50) 

    syncdb(Item) 

    Item.objects.create(series='A', number='1234') 
    Item.objects.create(series='A', number='1230') 
    Item.objects.create(series='A', number='9999') 
    Item.objects.create(series='B', number='1234') 

    print(Item.objects.annotate(
     search=Concat('series', 'number')).filter(
      search__icontains='A123').values_list('series', 'number')) 
    # >>> [(u'A', u'1234'), (u'A', u'1230')] 


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': 'WARN'}, 
       'loggers': { 
        "django.db": {"level": "WARN"}}}) 
    app_config = AppConfig(NAME, sys.modules['__main__']) 
    apps.populate([app_config]) 
    django.setup() 
    original_new_func = ModelBase.__new__ 

    @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() 
2

あなたは、AJAXリクエストの一部つもり使用している場合、私は、私はviews.py

AllUser = User.objects.all() 
users = [] 
for i in AllUser: 
    if query in i.get_full_name(): 
     users += [{'first_name':i.first_name,'last_name':i.last_name,'full_name':i.get_full_name()}] 

qUser = users 

と返されたAjaxのページで(この

のように使用し始め、私の方法を見つけました私の場合は 'searchajax.html')

{% if qUser %} 
    {% for i in qUser %} 
    <p class="queryP">{{ i.full_name }}</p> 
    {% endfor %} 
{% endif %} 

それは:)私のために非常によく動作します)

もう一つの方法は、その定義され、連結方式が存在しない、悲しいことに、私はジャンゴ1.3を使用しています、):)それはあまりにも同じ仕事を作る

from django.db.models import CharField, Value as V 
from django.db.models.functions import Concat 
author = User.objects.annotate(screen_name=Concat('first_name', V(' ') ,'last_name')) 
for i in author: 
    print i.screen_name 

答えを

関連する問題