(modeladmin_reversing_urls)= # Reversing ModelAdmin URLs It's sometimes useful to be able to derive the `index` (listing) or `create` URLs for a model along with the `edit`, `delete` or `inspect` URL for a specific object in a model you have registered via the `modeladmin` app. Wagtail itself does this by instantiating each `ModelAdmin` class you have registered, and using the `url_helper` attribute of each instance to determine what these URLs are. You can take a similar approach in your own code too, by creating a `ModelAdmin` instance yourself, and using its `url_helper` to determine URLs. See below for some examples: ```{contents} --- local: depth: 1 --- ``` ## Getting the `edit` or `delete` or `inspect` URL for an object In this example, we will provide a quick way to `edit` the Author that is linked to a blog post from the admin page listing menu. We have defined an `AuthorModelAdmin` class and registered it with Wagtail to allow `Author` objects to be administered via the admin area. The `BlogPage` model has an `author` field (a `ForeignKey` to the `Author` model) to allow a single author to be specified for each post. ```python # file: wagtail_hooks.py from wagtail.admin.widgets import PageListingButton from wagtail.contrib.modeladmin.options import ModelAdmin, modeladmin_register from wagtail import hooks # Author & BlogPage model not shown in this example from models import Author # ensure our modeladmin is created class AuthorModelAdmin(ModelAdmin): model = Author menu_order = 200 # Creating an instance of `AuthorModelAdmin` author_modeladmin = AuthorModelAdmin() @hooks.register('register_page_listing_buttons') def add_author_edit_buttons(page, page_perms, next_url=None): """ For pages that have an author, add an additional button to the page listing, linking to the 'edit' page for that author. """ author_id = getattr(page, 'author_id', None) if author_id: # the url helper will return something like: /admin/my-app/author/edit/2/ author_edit_url = author_modeladmin.url_helper.get_action_url('edit', author_id) yield PageListingButton('Edit Author', author_edit_url, priority=10) modeladmin_register(AuthorModelAdmin) ``` As you can see from the example above, when using `get_action_url()` to generate object-specific URLs, the target object's primary key value must be supplied so that it can be included in the resulting URL (for example `"/admin/my-app/author/edit/2/"`). The following object-specific action names are supported by `get_action_url()`: - `'edit'` Returns a URL for updating a specific object. - `'delete'` Returns a URL for deleting a specific object. - `'inspect'` Returns a URL for viewing details of a specific object. - **NOTE:** This will only work if `inspect_view_enabled` is set to `True` on your `ModelAdmin` class. ```{note} If you are using string values as primary keys for you model, you may need to handle cases where the key contains characters that are not URL safe. Only alphanumerics (`[0-9a-zA-Z]`), or the following special characters are safe: `$`, `-`, `_`, `.`, `+`, `!`, `*`, `'`, `(`, `)`. `django.contrib.admin.utils.quote()` can be used to safely encode these primary key values before passing them to `get_action_url()`. Failure to do this may result in Wagtail not being able to recognise the primary key when the URL is visited, resulting in 404 errors. ``` ## Getting the `index` or `create` URL for a model There are URLs available for the model listing view (action is `'index'`) and the create model view (action is `'create'`). Each of these has an equivalent shortcut available; `url_helper.index_url` and `url_helper.create_url`. For example: ```python from .wagtail_hooks import AuthorModelAdmin url_helper = AuthorModelAdmin().url_helper index_url = url_helper.get_action_url('index') # OR we can use the 'index_url' shortcut also_index_url = url_helper.index_url # note: do not call this property as a function # both will output /admin/my-app/author create_url = url_helper.get_action_url('create') # OR we can use the 'create_url' shortcut also_create_url = url_helper.create_url # note: do not call this property as a function # both will output /admin/my-app/author/create ``` ```{note} If you have registered a page type with `modeladmin` (for example `BlogPage`), and pages of that type can be added to more than one place in the page tree, when a user visits the `create` URL, they'll be automatically redirected to another view to choose a parent for the new page. So, this isn't something you need to check or cater for in your own code. ``` To customise `url_helper` behaviour, see [](modeladmin_url_helper_class).