Django动态选择

时间:2011-08-04 02:02:04

标签: django django-forms

我想为CharField选项提取已过滤的模型类列表。我理解选择可以是任何可迭代的,只要它包含2个元素元组。

代码是这样的:

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)

list comprehension返回一个包含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渲染,没有选择。

当我剪切并粘贴列表推导返回的值时,admin会呈现以下选项:

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

我错过了什么?

PS元组()没有区别。

2 个答案:

答案 0 :(得分: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时都会对其进行评估。

答案 1 :(得分: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()