5

I know I can change the display title for a model in Django Admin using

    class Meta:
        verbose_name='Custom Model Name Here'

However, is there a way to display which app heading a model is displayed under?

For example, if I create a custom user model Users in a new app also called users then the default user model goes from Authentication and Authorization > Users to Users > Users.

I would like to retain it under the original heading Authentication and Authorization > Users.

enter image description here

I have read this answer which suggests changes the app verbose_name, however it only changes the verbose name of the app associated with the model. I want to show the model in a different group on the admin panel. You can see the issue that approach takes here:

enter image description here

alias51
  • 8,178
  • 22
  • 94
  • 166

4 Answers4

9

You could set up a proxy model

In app_1.models.py

class MyModel(models.Model):
    ...

In app_2.models.py

from app_1.models import MyModel

class MyModelProxy(MyModel):
    class Meta:
        proxy = True

Then register the MyModelProxy in admin as normal

HenryM
  • 5,557
  • 7
  • 49
  • 105
  • This solution also works with Django suit. Currently I checked it only on old Django 1.11, but I will update this code in next week. I am assuming that: this solution also working on the newest Django version, isn't it? – dannydedog Jan 21 '21 at 09:38
  • I'm using in Django 2.x. I've not tried with Django 3 but don't see why it wouldn't – HenryM Jan 22 '21 at 08:21
  • This is a great solution for generic cases. However in the case of the original poster, he would surely have to change `django.auth`? And we all know how good of an idea that is. – run_the_race Aug 07 '21 at 07:06
1

There is no simple way of doing what you're intending, check out the Django code/template that generates the view:

@never_cache
def index(self, request, extra_context=None):
    """
    Display the main admin index page, which lists all of the installed
    apps that have been registered in this site.
    """
    app_list = self.get_app_list(request)

    context = {
        **self.each_context(request),
        'title': self.index_title,
        'app_list': app_list,
        **(extra_context or {}),
    }

    request.current_app = self.name

    return TemplateResponse(request, self.index_template or 'admin/index.html', context)

templates/admin/index.html:

{% for app in app_list %}
    <div class="app-{{ app.app_label }} module">
    <table>
    <caption>
        <a href="{{ app.app_url }}" class="section" title="{% blocktrans with name=app.name %}Models in the {{ name }} application{% endblocktrans %}">{{ app.name }}</a>
    </caption>
    {% for model in app.models %}
        <tr class="model-{{ model.object_name|lower }}">
        {% if model.admin_url %}
            <th scope="row"><a href="{{ model.admin_url }}">{{ model.name }}</a></th>
        {% else %}
            <th scope="row">{{ model.name }}</th>
        {% endif %}

        {% if model.add_url %}
            <td><a href="{{ model.add_url }}" class="addlink">{% trans 'Add' %}</a></td>
        {% else %}
            <td>&nbsp;</td>
        {% endif %}

        {% if model.admin_url %}
            {% if model.view_only %}
            <td><a href="{{ model.admin_url }}" class="viewlink">{% trans 'View' %}</a></td>
            {% else %}
            <td><a href="{{ model.admin_url }}" class="changelink">{% trans 'Change' %}</a></td>
            {% endif %}
        {% else %}
            <td>&nbsp;</td>
        {% endif %}
        </tr>
    {% endfor %}
    </table>
    </div>
{% endfor %}

As you can see, Django admin template is looping your app_list directy, so the only way of doing it would be to override the admin/index.html template to place your models in your desired order.

From Django docs:

For those templates that cannot be overridden in this way, you may still override them for your entire project. Just place the new version in your templates/admin directory. This is particularly useful to create custom 404 and 500 pages.

https://docs.djangoproject.com/en/2.2/ref/contrib/admin/#overriding-vs-replacing-an-admin-template

Hagyn
  • 922
  • 7
  • 14
  • If you create a custom user model can you include it in the original Django code rather than a new app, or is this a bad idea? – alias51 Jul 20 '19 at 14:53
  • It is always a bad idea to edit the Django code directly because it could stop working as intended and cause you trouble. If you really want to do this just override the template, copy all the original code to the new template and change the template piece of code I posted. You could also add some other stuff to the `index.html` template with this approach. – Hagyn Jul 20 '19 at 14:56
0

In firstapp.models.py

class ActualModel(models.Model):

class DisplayModel(ActualModel):
    class Meta:
        proxy = True

in secondapp.admin.py

from firstapp.models import DisplayModel
admin.site.register(DisplayModel)
Sawan Chauhan
  • 621
  • 7
  • 9
0

Easier way to do that:

In model class Meta add

    app_label = 'app2'
    db_table = 'app1_modelname'

so you assigning model to another app with app_label and assigning db_table with old (current) table name to prevent making migrations and table renami