简体   繁体   中英

Django: Parent categories doesn't shown in admin interface

Problem: Dash signs display in 'Parent category' column before I open any menu item. I get 'Parent category' items when open menu item profile(see admin.py below)

Before and after opening of menu profile: picture1 and picture2 (pay attention on Parent Category column)

My models.py : (attention on parent_id )

class Menu(models.Model):

    cat_title = models.CharField(max_length=150, verbose_name='Category title')
    menu_title = models.CharField(max_length=150, verbose_name='Menu title')
    parent_id = models.IntegerField(blank=True, null=True, verbose_name='Parent category', choices=(('',''),))
    url = models.CharField(max_length=255, verbose_name='URL', blank=True)
    named_url = models.CharField(max_length=255, verbose_name='Named URL', blank=True)
    level = models.IntegerField(default=0, editable=False)

My admin.py : ()

class MyMenu(admin.ModelAdmin):

    def get_choices(self):
        choices = (('',''),)
        categories = models.Menu.objects.all().values()
        for i in categories:
            choices += ((i['id'], i['cat_title']),)
        return choices

    def formfield_for_choice_field(self, db_field, request):
        if db_field.name == 'parent_id':
            db_field.choices = self.get_choices()

        return super().formfield_for_choice_field(db_field, request)
    list_display = ('cat_title', 'menu_title', 'parent_id', 'level')
    list_display_links = ('cat_title', 'menu_title')

    admin.site.register(models.Menu, MyMenu)

Question: How could I rewrite my admin.py to show parent_id items without opening any menu item profile?

I've already tried Model.get_FOO_display() but it doesn't work in right way. Any help would be appreciated.

Without changing your model, the simplest solution is probably to add a parent method in your admin and use it instead of "parent_id" in the list_display list:

class MyMenu(admin.ModelAdmin):
    # ....
    def parent(self, obj):
        if obj.parent_id:
            return Menu.objects.get(pk=obj.parent_id).cat_title
        return ""

    list_display = ('cat_title', 'menu_title', 'parent', 'level')


    # Unrelated but you may also want to rewrite `get_choices`
    # in a simpler and more performant way:
    def get_choices(self):
        choices = models.Menu.objects.values_list("id", "cat_title"))
        return (('',''),) + tuple(choices) 

Or to make parent a method or property on your Menu model:

class Menu(models.Model):
    # ...

    # you may want to use django's `cached_property` instead
    # but then you'll have to invalidate the cache when setting
    # (or unsetting) `.parent_id`
    @property
    def parent(self):
        if not self.parent_id:
            return None
        return Menu.objects.get(pk=self.parent_id)

and add "parent" to your admin's list_display .

BUT since Menu.parent_id is actually a foreign key on Menu , the proper solution is to declare it as such in your model:

class Menu(models.Model):
    cat_title = models.CharField(max_length=150, verbose_name='Category title')
    menu_title = models.CharField(max_length=150, verbose_name='Menu title')
    parent = models.ForeignKey("self", blank=True, null=True, related_name="children")
    # etc

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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