简体   繁体   English

带有自定义值的 Django 管理外键下拉列表

[英]Django admin foreign key dropdown with custom value

I have 3 Django models:我有 3 个 Django 模型:

class Test(models.Model):
    pass

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

class Question(model.Model):
    page = models.ForeignKey(Page)

If I register the Question model to the admin, I get a dropdown with the desired Page .如果我向管理员注册Question模型,我会得到一个下拉列表,其中包含所需的Page Now, what do I have to modify to display the desired Page plus that page's corresponding Test ?现在,我必须修改什么才能显示所需的Page加上该页面的相应Test

Say, if I have three pages created, the dropdown will contain these values: Page1 , Page2 , Page3 .假设我创建了三个页面,下拉列表将包含以下值: Page1Page2Page3 I would like to see: Page1 - Test1 , Page2 - Test1 , Page3 - Test1我想看: Page1 - Test1Page2 - Test1Page3 - Test1

2 Options. 2 选项。

Option 1:选项1:

Create a new field , copy forms.ModelChoiceField and override label_from_instance .创建一个新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)

This will only change the text for that particular dropdown field.这只会更改该特定下拉字段的文本。 As you are accessing the Test object for each item in the list, you may want to ensure the queryset you pass to the PageModelChoiceField has select_related('test') , otherwise it will make a DB hit for each item on the list.当您正在访问的Test对象为每个项目在列表中,您可能希望确保queryset将传递给PageModelChoiceField已经select_related('test')否则会令一个DB命中列表上的每个项目。

I've not tested this exact code but the logic is there.我没有测试过这个确切的代码,但逻辑就在那里。 Will try it later when I can以后有空再试试

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

Option B.选项 B。

Change the unicode () representation of Page .更改的Unicode()表示Page

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

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

This will change how Page s are displayed everywhere you print a page object, print(page_object) , {{ page_object }} .这将改变Page s 在您打印页面对象print(page_object) , {{ page_object }}


Personally I prefer Option 1我个人更喜欢选项 1

For some reason Option B in the accepted answer didn't work for me so I figured I'd update this page with what worked well for me.出于某种原因,接受的答案中的选项 B 对我不起作用,所以我想我会用对我有用的东西更新这个页面。

You can overload the __str__ function for the Page model to get what you're wanting.您可以重载 Page 模型的 __str__ 函数以获得您想要的。 So, something along the lines of this所以,类似这样的事情

class Page(models.Model):
   test = models.ForeignKey(Test)
   def __str__(self):
      return f'Page{self.pk} - Test{self.test.pk}'

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM