Django-Admin : Override add-URL of the Foreign Key Auto-Complete "add" button / + green cross

Viewed 35

Is there a simple way of overriding/pass a parameter to the popup url automatically created by django-admin built-in autocomplete/select2 widget to create a new foreign key object? This url is embedded in the green cross (see picture). I didn't come across any well described solutions.

So the default url is pointing towards admin/app/model/add/?_to_field=id&_popup=1 but I would like to add a parameter admin/app/model/add/?_to_field=id&_popup=1&field_1=100 in order to pre-populate some fieds on the popup add_view.

Any leads?

add foreign key django admin

As per Maxim's answer :

    def formfield_for_dbfield(self, db_field, request, **kwargs):
    if db_field.name == "clinical_exam":
        widget = super(ConsultationAdmin, self).formfield_for_dbfield(db_field, request, **kwargs).widget
        widget.template_name = 'admin/related_widget_wrapper_with_id.html'
        widget.attrs.update({'your_parameter': 'you can use it after in template'})
        print(db_field)
        return db_field.formfield(widget=widget)
    return super(ConsultationAdmin, self).formfield_for_dbfield(db_field, request, **kwargs)
1 Answers

'change + -' this is a result of render RelatedFieldWidgetWrapper from django.contrib.admin.widgets

You can change attributes of this widget, but it is a little bit complicated.

in ModelAdmin.formfield_for_dbfield:

def formfield_for_dbfield(self, *args, **kwargs):
    widget = super.formfield_for_dbfield(self, *args, **kwargs).widget 
    if isinstance(widget, RelatedFieldWidgetWrapper):
        old_context = widget.get_context
        widget.get_context = my_function(widget.get_context, *args, **kwargs)

my function is a decorator for old function:

def my_function(func, *initargs, **initkwargs):
    def wrapped(*args, **kwargs):
        context = func(*args, **kwargs)
        your_keys_vals_to_add_in_url = 'something in form key=val&'
        context['url_params'] = f'{context['url_params']}&{your_keys_vals_to_add_in_url}'
        return context
    return wrapped

Other possibility is - to change template related_widget_wrapper.html from django.admin.contrib.templates.admin.widgets You can hardcoded your values there.

in ModelAdmin.formfield_for_dbfield:

def formfield_for_dbfield(self, *args, **kwargs):
    widget = super.formfield_for_dbfield(self, *args, **kwargs).widget
    if isinstance(widget, RelatedFieldWidgetWrapper):
        widget.template_name = 'path/to/your_overriden_related_widget_wrapper.html'
        widget.attrs.update('your_parameter' : 'you can use it after in template')  # this is not work right now in django

and after it in own template:

# example for change link
# this is not work right now in django
<a ... data-href-template="{{ change_related_template_url }}?{{ url_params }}&{{ attr.your_parameter|dafault:'' }}" .. >

The last part not works in Django right now. I made an issue in Django project about this possibility.

Related