Pass parameters in URL to Django Admin add_view

Question:

I need to pass a parameter in the URL to the Django Admin add view, so that when I type the URL: http://localhost:8000/admin/myapp/car/add?brand_id=1, the add_view reads the brand_id parameter. I want to use this so that I can set a default value for the brand attribute of Car.

def get_form(self, request, obj=None, **kwargs):
    form = super(CarAdmin, self).get_form(request, obj, **kwargs)
    form.base_fields['brand'].initial = <<GET['brand_id']>>
    return form

Use case: I want this because in my BrandsAdmin, I have added a "+" button for each brand, that should add a Car with that Brand as FK.

I’ve tried getting it from request in get_form, but when that code is executed, Django has already changed my URL as I guess it doesn’t understand it as a "legal" parameter.

Thanks a lot!

Asked By: matiszz

||

Answers:

You can find a full explanation here, but shortly:

You can access query parameters directly from the view, the request object has a method. I suppose it is a GET request, so an example for your implementation would be:

request.GET.getlist("brand_id")

or

request.GET.get("brand_id")
Answered By: videap

Mainly, for what I wanted to do, it’s as easy as two steps.

First, add a column in list_display to show the link to the add_view:

Brand.py

@admin.display(description='Link', ordering='url')
def get_add_link(self):
    url = f"{reverse('admin:myapp_car_add')}?brand={self.id}"
    return format_html(f"<a href='{url}'><i class='fas fa-plus'></i></a>")

Note that I add the URL as the reverse of admin:<app>_<model>_<action> and pass the brand ID as parameter.

CarAdmin.py

def get_changeform_initial_data(self, request):
    brand_id = request.GET.get('brand')
    return {'brand': brand_id}

By adding this method in the CarAdmin class, I am able to set the brand as the default value.

Answered By: matiszz

Using django 3 i did it overriding get_form in CarAdmin.py like you did, and its working for me, maybe the trick is in Brand.py:

Brand.py

readonly_fields = ('get_add_link',)
def get_add_link(self, obj):
  url = f"{reverse('admin:myapp_car_add')}?brand={self.id}"
  return format_html(f"<a href='{url}'><i class='fas fa-plus'></i></a>")

CarAdmin.py

def get_form(self, request, obj=None, **kwargs):
    form = super(CarAdmin, self).get_form(request, obj, **kwargs)
    brand_id = request.GET.get('brand')
    if brand_id and len(brand_id) > 0:
        form.base_fields['brand'].initial = brand_id
Answered By: user3486626

I did not have to do anything with the Model. The only change needed was in the ModelAdmin:

def get_changeform_initial_data(self, request):
  brand = None
  brand_id = request.GET.get('brand')
  if (brand_id):
    brand = Brand.objects.get(id=brand_id)
  return {'brand': brand}

Docs link here: https://docs.djangoproject.com/en/4.1/ref/contrib/admin/#django.contrib.admin.ModelAdmin.get_changeform_initial_data

Answered By: Nathan Clement
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.