2

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!

4 Answers 4

1

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
Sign up to request clarification or add additional context in comments.

Comments

0

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")

2 Comments

Not exactly sure how to apply this. I want to get it in my default edit_view view, which I've only configured in the CarAdmin class.
oh but the request object is the one that is already passed to the view. you need to put this exactly where you higlighted, so form.base_fields['brand'].initial = request.GET.get("brand_id")
0

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.

Comments

0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.