django-shop icon indicating copy to clipboard operation
django-shop copied to clipboard

Reverse admin url of Customer Model

Open pydrogo opened this issue 5 years ago • 5 comments

how can I get the reverse admin URL of the customer model? I tried: reverse('admin:shop_customer_changelist') but could not get it. could anyone help me, please?

pydrogo avatar Nov 13 '19 07:11 pydrogo

It's admin:shop_customerproxy_changelist

Small hint to find out yourself:

  • Go to the admin page you are looking for.
  • Copy the URL without the site part, here /en/admin/shop/customerproxy/.
  • Run ./manage.py shell
  • Use that URL in function resolve.
  • Recheck with reverse if the URL is the same.
>>> from django.urls import *
>>> resolve('/en/admin/shop/customerproxy/')
ResolverMatch(func=django.contrib.admin.options.changelist_view, args=(), kwargs={}, url_name=shop_customerproxy_changelist, app_names=['admin'], namespaces=['admin'])
>>> reverse('admin:shop_customerproxy_changelist')
'/en/admin/shop/customerproxy/'

jrief avatar Nov 13 '19 08:11 jrief

I really appreciated your comprehensive answer. I could get the URL using your solution. I wanted to ask your idea about getting this URL dynamically using the Customer model. I have this in my admin.py:

@admin.register(AnswerSheetModel)
class AnswerSheetModelAdmin(admin.ModelAdmin):
    list_display = ('get_customer')

    @admin_link('customer', 'Customer')
    def get_customer(self, customer):
        return customer

and here is my decorator:

def admin_change_url(obj):
    app_label = obj._meta.app_label
    model_name = obj._meta.model.__name__.lower()
    return reverse('admin:{}_{}_change'.format(
        app_label, model_name
    ), args=(obj.pk,))

def admin_link(attr, short_description, empty_description="-"):
    def wrap(func):
        def field_func(self, obj):
            related_obj = getattr(obj, attr)
            if related_obj is None:
                return empty_description
            url = admin_change_url(related_obj)
            return format_html(
                '<a href="{}">{}</a>',
                url,
                func(self, related_obj)
            )
        field_func.short_description = short_description
        field_func.allow_tags = True
        return field_func
    return wrap

It gives the admin URL for change model page. Is adding an if statement for determining the Customer model only solution? like this:

def admin_change_url(obj):
    app_label = obj._meta.app_label
    model_name = obj._meta.model.__name__.lower()
    if model_name == 'customer':
        return reverse('admin:shop_customerproxy_change', args=(obj.pk,))
    return reverse('admin:{}_{}_change'.format(
        app_label, model_name
    ), args=(obj.pk,))

Is there any better solution?

pydrogo avatar Nov 13 '19 09:11 pydrogo

What shall AnswerSheetModelAdmin do?

BTW, if you are using a tuple in list_display = ('get_customer'), don't forget the comma – you did. It is better to use lists anyway.

jrief avatar Nov 13 '19 09:11 jrief

Here is my AnswerSheetModel:

class AnswerSheetModel(BaseModel):
    questionnaire = models.ForeignKey(QuestionnaireModel, on_delete=models.DO_NOTHING, related_name='answers')
    customer = models.ForeignKey(Customer, on_delete=models.DO_NOTHING, null=False, blank=False)
    ip = models.CharField(null=True, max_length=20)

    def __str__(self):
        return self.questionnaire.name + ': ' + self.customer.first_name + ' ' + self.customer.last_name

BTW, if you are using a tuple in list_display = ('get_customer'), don't forget the comma – you did.

thank you very much, yes I have trailing comma, I deleted it Here for simplicity :-)

pydrogo avatar Nov 13 '19 10:11 pydrogo

It's admin:shop_customerproxy_changelist

Small hint to find out yourself:

  • Go to the admin page you are looking for.
  • Copy the URL without the site part, here /en/admin/shop/customerproxy/.
  • Run ./manage.py shell
  • Use that URL in function resolve.
  • Recheck with reverse if the URL is the same.
>>> from django.urls import *
>>> resolve('/en/admin/shop/customerproxy/')
ResolverMatch(func=django.contrib.admin.options.changelist_view, args=(), kwargs={}, url_name=shop_customerproxy_changelist, app_names=['admin'], namespaces=['admin'])
>>> reverse('admin:shop_customerproxy_changelist')
'/en/admin/shop/customerproxy/'

Regarding that URL, I have problems accessing the following addresses:

http://localhost:8000/es/admin/shop/customerproxy/4/change/ or http://localhost:8000/es/admin/shop/customerproxy/add/

I have the following error:

TypeError at /es/admin/shop/customerproxy/4/change/

has_add_permission() takes 2 positional arguments but 3 were given

Request Method: 	GET
Request URL: 	http://localhost:8000/es/admin/shop/customerproxy/4/change/
Django Version: 	3.0.7
Exception Type: 	TypeError
Exception Value: 	

has_add_permission() takes 2 positional arguments but 3 were given

Exception Location: 	/home/ikki/.virtualenvs/vmedexample/lib/python3.6/site-packages/django/contrib/admin/options.py in get_inline_instances, line 596
Python Executable: 	/home/ikki/.virtualenvs/vmedexample/bin/python
Python Version: 	3.6.0
Python Path: 	

['/home/ikki/Desarrollo/implementacion/medexample',
 '/home/ikki/Desarrollo/implementacion/medexample',
 '/home/ikki/Desarrollo/ide/pycharm-2020.1.1/plugins/python/helpers/pycharm_display',
 '/home/ikki/.pyenv/versions/3.6.0/lib/python36.zip',
 '/home/ikki/.pyenv/versions/3.6.0/lib/python3.6',
 '/home/ikki/.pyenv/versions/3.6.0/lib/python3.6/lib-dynload',
 '/home/ikki/.virtualenvs/vmedexample/lib/python3.6/site-packages',
 '/home/ikki/Desarrollo/ide/pycharm-2020.1.1/plugins/python/helpers/pycharm_matplotlib_backend']

Server time: 	Lun, 15 Jun 2020 16:33:36 +0000

I have made from the installation cookiecutter-django-shop by default with all the sample data.

what is the solution?

jhonvidal avatar Jun 15 '20 16:06 jhonvidal