2011-08-04 146 views
2

我想爲CharField選擇拉取模型類的過濾列表。我明白這些選擇可以是任何可迭代的,只要它包含2個元素元組。Django動態選擇

代碼是這樣的:

WORKFLOWAWARE_MODELS = [(m.__name__, m.__name__) for m in models.get_models() if 'WorkflowAware' in [b.__name__ for b in m.__bases__]] 
class Workflow(models.Model): 
    """ Workflow controls who does what where """ 
    workflow_content_type = models.CharField(max_length=64, choices=WORKFLOWAWARE_MODELS, unique=True, blank=True) 

列表理解返回類似這樣的2個元組的列表:

 
    >>> x = [(m.__name__, m.__name__) for m in models.get_models() if 'WorkflowAware' in [b.__name__ for b in m.__bases__]] 
    >>> x 
    [('ActivityContent', 'ActivityContent')] 
    >>> x.__class__ 
    type 'list' 
    >>> x[0].__class__ 
    type 'tuple' 
    >>> x[0][0].__class__ 
    type 'str' 

所有我在管理界面得到的是一個標準CharField渲染,沒有選擇。

當我剪切和粘貼由列表理解管理員的返回值呈現的選擇:

WORKFLOWAWARE_MODELS = [('ActivityContent', 'ActivityContent')] 

我在想什麼?

PS tuple()沒有區別。

回答

4

問題是在正確的上下文初始化之前,WORKFLOWAWARE_MODELS值可能(也可能會)被計算。例如。在導入此模塊期間,ActivityContent和ActivityContent尚未加載。您需要的是使WORKFLOWAWARE_MODELS成爲可調用的,例如通過使用lambda。事情是這樣的:

WORKFLOWAWARE_MODELS = lambda: [(m.__name__, m.__name__) for m in models.get_models() if 'WorkflowAware' in [b.__name__ for b in m.__bases__]] 

這樣每WORKFLOWAWARE_MODELS被調用時它就會被評估。

+0

謝謝Mizi。無法得到那個工作。我最終從James Bennett找到了DjangoSnippet(見下文)。 –

0
class WorkflowForm(forms.ModelForm): 
    content_type = forms.ChoiceField(choices=()) 
    def __init__(self, *args, **kwargs): 
     super(WorkflowForm, self).__init__(*args, **kwargs) 
     self.fields['content_type'].choices = [('', '---')] + WORKFLOWAWARE_MODELS()