Ankit Chaurasia
Ankit Chaurasia

Reputation: 165

Django admin site: how to change admin URL based on verbose_name

class Meta: verbose_name only changes its displayed name. But when its clicked. i want its url changed too based on verbose name

Here's my code:

Models:

tables = [f.id for f in StockId.objects.raw(
    "SELECT TABLE_NAME AS id FROM INFORMATION_SCHEMA.tables WHERE TABLE_NAME LIKE 'my_project_auth_stockid%%'")]

table_map = {}
for tbl in tables:
    class Stocks(models.Model):
        user_id = models.IntegerField()
        product_name = models.CharField(max_length=100)
        mrp = models.IntegerField()
        selling_price = models.IntegerField()


        class Meta:
            db_table = tbl
            managed = False
            verbose_name = _(tbl)
            verbose_name_plural = _(tbl)

    table_map[tbl] = Stocks

Admin.py

from my_project_auth.models import *

class AllStocksAdmin(AdminSite):
    site_header = 'All User Stocks'


stockadmin = AllStocksAdmin(name="stockadmin")

for tbl in tables:
    class StocksAdmin(ImportExportModelAdmin):
        resource_class = StocksAdminResource
        list_display = ["product_name"]


    stockadmin.register(table_map[tbl], StocksAdmin)

What I am trying to do is in above to make multiple stock table out of single model. But Admin panel for each stocks is not working. All stocks table is pointing towards single table because of admin URL is based on model's class name.

I'm trying to do something like this in Admin.py, please suggest changes:

for tbl in tables:
    class StocksAdmin(ImportExportModelAdmin):
        resource_class = StocksAdminResource
        list_display = ["product_name"]


    def get_urls(self):                                                   # Not Working
        urls = super(StocksAdmin, self).get_urls()

        my_urls = path(f'stockadmin/{tbl}/', self.admin_view(stockadmin))

        return my_urls + urls

Upvotes: 0

Views: 210

Answers (1)

Iain Shelvington
Iain Shelvington

Reputation: 32244

To solve the problem of having multiple models with the same name we can generate then dynamically with unique names using the three argument form of type

from django.db import models

tables = [f.id for f in StockId.objects.raw(
    "SELECT TABLE_NAME AS id FROM INFORMATION_SCHEMA.tables WHERE TABLE_NAME LIKE 'my_project_auth_stockid%%'")]


class StockBase(models.Model):
    user_id = models.IntegerField()
    product_name = models.CharField(max_length=100)
    mrp = models.IntegerField()
    selling_price = models.IntegerField()

    class Meta:
        abstract = True


for tbl in tables:
    class Meta:
        db_table = tbl
        managed = False
        verbose_name = tbl
        verbose_name_plural = tbl
    locals()[f'Stocks{tbl}'] = type(f'Stocks{tbl}', (StockBase,), {'Meta': Meta, '__module__': StockBase.__module__})

This will result in multiple models with the same fields, from the base class, and all with unique names.

I used __subclasses__ in the admin to get all the created models but it's pretty much the same, just register all the models.

from django.contrib import admin

from . import models


class StocksAdmin(admin.ModelAdmin):
    list_display = ["product_name"]


for cls in models.StockBase.__subclasses__():
    admin.site.register(cls, StocksAdmin)

Now your admin should be full of tens/hundreds/thousands of duplicate but named slightly different models

Upvotes: 1

Related Questions