2012-07-10 96 views
9

我有一個Person模型,我使用的是Django的形式與外鍵Person編輯另一個對象。人員模型有first_namelast_name字段。我想運行一個方法來過濾外部參考的下拉框的結果。Django的:values_list()多個字段連接在一起

我試圖用values_list()覆蓋窗體域選項(選項屬性),像這樣:

data.form.fields['person'].choices = GetPersons().values_list('id', 'first_name') 

GetPersons()只是過濾Person類像

return Person.objects.filter(id__gt=1000)` 

例如,所以只有我找到我想要展示的人。如何使用values_list()返回first_namelast_name的連接而不必返回字典並手動分割所有內容?

回答

11

我心目中2個sugestions你:

  • 第一個是與extra來連接領域的數據庫。對我來說是一個骯髒的解決方案,但可以運行

樣品:

persons = GetPersons().extra(select={'full_name': "concatenate(first, last) "}) 
choices = persons.values_list('id', 'full_name') 

和...

  • 第二個使用列表理解:

樣品:

choices = [ (p.id, '{0} {1}'.format(p.first, p.last),) for p in GetPersons() ] 
+0

謝謝,@danihp,我會用理解並接受你的答案。 – Furbeenator 2012-07-10 16:36:40

0

每個:Is it possible to reference a property using Django's QuerySet.values_list?,避免values_list不適用時,使用理解,而不是。

models.py: 
class Person(models.Model): 
    first_name = models.CharField(max_length=32) 
    last_name = models.CharField(max_length=64) 
    def getPrintName(self): 
     return self.last_name + ", " + self.first_name 

views.py: 
data.form.fields['person'].choices = [(person.id, person.getPrintName()) for person in GetPersons()] 
5

這聽起來像Django 1.8中的annotate() function更靈活。您可以將兩個字段與Concat 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, Value 

NAME = 'udjango' 


def main(): 
    setup() 

    class Person(models.Model): 
     first_name = models.CharField(max_length=30) 
     last_name = models.CharField(max_length=30) 

    syncdb(Person) 

    Person.objects.create(first_name='Jimmy', last_name='Jones') 
    Person.objects.create(first_name='Bob', last_name='Brown') 

    print(Person.objects.annotate(
     full_name=Concat('first_name', 
         Value(' '), 
         'last_name')).values_list('id', 'full_name')) 
    # >>> [(1, u'Jimmy Jones'), (2, u'Bob Brown')] 


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() 
+0

謝謝你,很好的解決方案!我會認爲這是比普遍接受的答案更普遍的方法嗎? – Gesias 2016-10-23 10:06:48

+0

我認爲這是所有Django後端支持的,@Gesias。例如,我認爲接受的答案不適用於Sqlite3,因爲它與「||」運算符連接。公平地說,我沒有嘗試過。 – 2016-10-23 22:58:54

+0

很好的回答!你知道在這個過程中如何轉換類型嗎?例如,如果我想將id轉換爲一個字符串,然後將其與名稱連接起來怎麼辦? – 2017-02-08 21:35:08