【发布时间】:2013-11-22 23:05:53
【问题描述】:
这个问题类似于Set model field choices attribute at run time? 但是,我的问题是我想在类级别更改选择属性的默认值。
我有这个
class Project(models.Model):
name = models.CharField(...)
@staticmethod
def getAllProjectsTuple():
return tuple([(p.id, p.name) for p in Project.objects.all()])
class Record(models.Model):
project = models.ForeignKey(
Project,
verbose_name='Project',
help_text='Project name',
blank=True, null=True,
on_delete=models.SET_NULL,
choices = Project.getAllProjectsTuple(),
class RecordForm(ModelForm):
class Meta:
model = Record
我的问题是,所有 RecordForm 都将使用 TypedChoiceField 创建,使用模块导入时模型中的可用选项。但是,用户可以创建更多项目,这些项目将永远不会出现在 RecordForm 中;删除也一样。
我尝试直接篡改RecordForm的init:
self.fields['project']._choices = [('', '---------'),] + [(p.id, p.name) for p in Project.objects.all()]
或使用记录的init:
self._meta.get_field('project')._choices = Project.getAllProjectsTuple()
但似乎没有任何效果。
感谢您的帮助。
【问题讨论】:
-
你为什么要使用选择而不是仅仅使用标准的
ModelSelectWidget和查询集?默认行为与您的getAllProjectsTuple行为相同。 -
choices = Project.objects.values_list('id', 'name')怎么样? -
@Peter,这实际上解决了它。我不确定我是怎么理解的。如果我不覆盖它,那是不是一些 Django 魔法会一直重新评估选择?谢谢!
-
@Karthikr,这不起作用。我认为与原始问题的原因相同:仅在模型导入时评估一次。
-
要改变这一点,您可以采用简单但范围更广的选项来更改
Project的__unicode__方法,或者采用更复杂的选项将字段子类化并覆盖其label_from_instance方法作为此处记录:docs.djangoproject.com/en/dev/ref/forms/fields/… - 后者仅影响该字段,而不影响 Django 可能代表您的Project实例的其他地方。
标签: python django oop django-models django-forms