Django使用自定义值管理外键下拉列表

lin*_*ndy 9 python django django-admin

我有3个Django型号:

class Test(models.Model):
    pass

class Page(models.Model):
    test = models.ForeignKey(Test)

class Question(model.Model):
    page = models.ForeignKey(Page)
Run Code Online (Sandbox Code Playgroud)

如果我将Question模型注册到管理员,我会得到一个所需的下拉列表Page.现在,做我必须要修改,以显示所需Page 加上该页面的相应的Test

再说了,如果我有三个页面创建,下拉菜单将会包含这些值:Page1,Page2,Page3.我想看看:Page1 - Test1,Page2 - Test1,Page3 - Test1

roc*_*ier 11

2选项.

选项1:

创建一个新的field,复制forms.ModelChoiceField和覆盖label_from_instance.

# From the source
class PageModelChoiceField(forms.ModelChoiceField():
    def label_from_instance(self, obj):
        """
        This method is used to convert objects into strings; it's used to
        generate the labels for the choices presented by this object. Subclasses
        can override this method to customize the display of the choices.
        """
        # Then return what you'd like to display
        return "Page{0} - Test{1}".format(obj.pk, obj.test.pk)
Run Code Online (Sandbox Code Playgroud)

这只会更改该特定下拉字段的文本.当您访问Test列表中每个项目的对象时,您可能希望确保queryset传递给PageModelChoiceFieldhas select_related('test'),否则它将为列表中的每个项目命中数据库.

我没有测试过这个确切的代码,但逻辑就在那里.我会在以后尝试

class QuestionForm(forms.ModelForm):

    page = PageModelChoiceField(
        queryset=Page.objects.select_related('test').all()
    )

    class Meta:
        model = Page


class QuestionAdmin(ModelAdmin):
    class Meta:
        model = Question
        form = QuestionForm
Run Code Online (Sandbox Code Playgroud)

选项B.

更改的unicode()表示形式Page.

class Page(models.Model):
    test = models.ForeignKey(Test)

    def __unicode__(self):
        return "Page{0} - Test{1}".format(obj.pk, obj.test.pk)
Run Code Online (Sandbox Code Playgroud)

这将改变Page在打印页面对象的任何地方显示s的方式print(page_object),{{ page_object }}.


我个人更喜欢选项1