I would like to add a hyperlink to the related model Training
It would be nice to have declarative solution, since I want to use this at several places.
The "pencil" icon opens the related model in a popup window. That's not what I want. I want a plain hyperlink to the related model.
BTW, if you use "raw_id_fields", then the result is exactly what I was looking for: There is a hyperlink to the corresponding admin interface of this ForeignKey.
The class named RelatedFieldWidgetWrapper
is showing the icons on the Django Admin page and thus you need to override the same. So, create a custom class as below,
from django.contrib.admin.widgets import RelatedFieldWidgetWrapper
class CustomRelatedFieldWidgetWrapper(RelatedFieldWidgetWrapper):
template_name = 'admin/widgets/custom_related_widget_wrapper.html'
@classmethod
def create_from_root(cls, root_widget: RelatedFieldWidgetWrapper):
# You don't need this method of you are using the MonkeyPatch method
set_attr_fields = [
"widget", "rel", "admin_site", "can_add_related", "can_change_related",
"can_delete_related", "can_view_related"
]
init_args = {field: getattr(root_widget, field) for field in set_attr_fields}
return CustomRelatedFieldWidgetWrapper(**init_args)
def get_context(self, name, value, attrs):
context = super().get_context(name, value, attrs)
rel_opts = self.rel.model._meta
info = (rel_opts.app_label, rel_opts.model_name)
context['list_related_url'] = self.get_related_url(info, 'changelist')
return context
See, the context variable list_related_url
is the relative path that we need here. Now, create an HTML file to render the output,
#File: any_registered_appname/templates/admin/widgets/custom_related_widget_wrapper.html
{% extends "admin/widgets/related_widget_wrapper.html" %}
{% block links %}
{{ block.super }}
<a href="{{list_related_url}}">- Link To Related Model -</a>
{% endblock %}
# admin.py
# other imports
from ..widgets import CustomRelatedFieldWidgetWrapper
from django.contrib.admin import widgets
widgets.RelatedFieldWidgetWrapper = CustomRelatedFieldWidgetWrapper # monket patch
# admin.py
class AlbumAdmin(admin.ModelAdmin):
hyperlink_fields = ["related_field_1"]
def formfield_for_dbfield(self, db_field, request, **kwargs):
formfield = super().formfield_for_dbfield(db_field, request, **kwargs)
if db_field.name in self.hyperlink_fields:
formfield.widget = CustomRelatedFieldWidgetWrapper.create_from_root(
formfield.widget
)
return formfield
There are several ways to go. Here is one.
Add some javascript that changes the existing link behavior. Add the following script at the end of the overridden admin template admin/widgets/related_widget_wrapper.html
. It removes the class which triggers the modal and changes the link to the object.
It will only be triggered for id_company
field. Change to your needs.
{% block javascript %}
<script>
'use strict';
{
const $ = django.jQuery;
function changeEditButton() {
const edit_btn = document.getElementById('change_id_company');
const value = edit_btn.previousElementSibling.value;
const split_link_template = edit_btn.getAttribute('data-href-template').split('?');
edit_btn.classList.remove('related-widget-wrapper-link');
edit_btn.setAttribute('href', split_link_template[0].replace('__fk__', value));
};
$(document).ready(function() {
changeEditButton();
$('body').on('change', '#id_company', function(e) {
changeEditButton();
});
});
}
</script>
{% endblock %}
This code can also be modified to be triggered for all edit buttons and not only for the company edit button.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With