根据字段值更改Django Model中的选项

时间:2015-07-15 21:35:31

标签: python django django-models

例如,如果我有一个类摘要,

每个班级摘要的实例,可以是一个主题:

    subjects = (
        ('english', 'אנגלית'),
        ('bible', 'תנ"ך'),
        ('history', 'היסטוריה'),
        ('civics', 'אזרחות'),
        ('language', 'לשון'),
        ('literature', 'ספרות'),
    )


class Summary(models.Model):
...
subject = models.CharField(max_length=20, choices=subjects)
...

现在我已经决定要为每个主题硬编码一些主题,所以如果Summary.subject = "literature"我要添加一个字段

subtopic = models.CharField(choices=literature_subtopics)

并使选择等于:

literature_subtopics = (
    ('poems', 'שירה'),
    ('short_stories', 'סיפורים קצרים'),
    ('plays', 'מחזות'),
    ('novels', 'נובלות'),
)

如果主题是英语,那么english_subtopics将用于选择字段。

我想对所有这些部门进行硬编码,因为它们每隔几年就不会改变一次,如果有的话,将它们存储在数据库中是没有意义的。

我需要以某种方式为每个主题设置所有这些分区,并使Django适当地设置子主题的选择字段。

我可以覆盖init方法以某种方式完成此操作吗?我听说这是一个坏主意,可以破坏事情。

2 个答案:

答案 0 :(得分:3)

您可以使用函数动态设置选项。

# models.py

def get_choices():
    choices_tuple_list = []
    ... # your logic to define choices
    return choices_tuple_list

class Summary(models.Model):
    ... # Summary definition
    subject = models.CharField(max_length=20, blank=True)

    def __init__(self, *args, **kwargs):
        super(Summary, self).__init__(*args, **kwargs)
        self._meta.get_field_by_name('subject')[0]._choices = get_choices()

See docs

答案 1 :(得分:3)

即使数据不经常变化,将数据放入数据库并将Python放入Python文件中也是最自然的。您提出的解决方案似乎与Django想要做事的方式相抗衡。

如何看待数据库解决方案?

class Subject(models.Model):
    parent = models.ForeignKey("self")
    name = models.CharField(max_length=100)
    hebrew_name = models.CharField(max_length=100)

class Summary(models.Model):
    ...
    subject = models.ForeignKey("Subject")
    ...

class SubjectForm(forms.Form):
    subject = forms.ModelChoiceField(queryset=Subject.objects.none())
    ...

    def __init__(self, *args, **kwargs): # see http://stackoverflow.com/a/4880869/1477364
        sub = kwargs.pop('parent_subject')
        super(SubjectForm, self).__init__(*args, **kwargs)
        parent_subject = Subject.objects.get(name=sub)
        sub_subjects = Subject.objects.filter(parent=parent_subject)
        self.fields['subject'].queryset = forms.ModelChoiceField(queryset=sub_subjects)

请注意,代码表示始终会有一个父Subject传递给SubjectForm。 (你需要一个" root" Subject。)