我想为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元组()没有区别。
答案 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()