Question: i am working on a django powered web app, and i want to customize admin view of one of my models. i have made a custom template for the add page and overrides save function in admin class to process input file before saving. here i have the admin class of RMABGD: @admin.register(RMABGD) class RMABGDAdmin(BaseModelAdmin): list_display = ('name', 'code_RMA', 'type_BGD', 'Partenaire', 'date_creation', 'RMA_BGD_state') list_filter = ('type_BGD', 'RMA_BGD_state', 'city') search_fields = ('name', 'code_RMA', 'Partenaire') add_form_template = "admin/spatial_data/RMABGD/change_form.html" change_form_template = "admin/spatial_data/RMABGD/change_form.html" def process_excel_import(self, request): excel_file = request.FILES.get('excel_file') if not excel_file: messages.error(request, "No file was selected. Please choose an Excel file.") return False try: df = pd.read_excel(excel_file) required_headers = ["code RMA", "code ACAPS", "Dénomination RMA", "Ville", "Adresse", "Longitude", "Latitude", "Type BGD", "Partenaire", "Date création", "Etat BGD RMA"] missing_headers = [header for header in required_headers if header not in df.columns] if missing_headers: messages.error(request, f"Missing required fields: {', '.join(missing_headers)}") return False else: # If all headers are correct, process data rows_imported = 0 errors = 0 for index, row in df.iterrows(): try: # Process row data obj = RMABGD( code_ACAPS=row["code ACAPS"], code_RMA=row["code RMA"], name=row["Dénomination RMA"], address=row["Adresse"], city=row["Ville"], location=f'POINT({row["Longitude"]} {row["Latitude"]})', type_BGD=row["Type BGD"], Partenaire=row["Partenaire"], date_creation=row["Date création"], RMA_BGD_state=row["Etat BGD RMA"] ) obj.save() rows_imported += 1 except Exception as e: messages.error(request, f"Error in row {index + 1}: {str(e)}") errors += 1 if rows_imported > 0: messages.success(request, f"Successfully imported {rows_imported} rows") return True if errors > 0: messages.warning(request, f"Failed to import {errors} rows. See details above.") if rows_imported == 0: messages.error(request, "No rows were imported. Please check your file and try again.") return rows_imported > 0 except Exception as e: messages.error(request, f"Error processing file: {str(e)}") return False def save_model(self, request, obj, form, change): self.process_excel_import(request) super().save_model(request, obj, form, change)  and this is the corresponding template for add: {% extends "admin/base_site.html" %} {% load i18n admin_urls static %} {% block content %} <div id="content-main"> {% if messages %} <ul class="messagelist"> {% for message in messages %} <li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li> {% endfor %} </ul> {% endif %} <form action="." method="post" enctype="multipart/form-data"> {% csrf_token %} <div> <fieldset class="module aligned"> <div class="form-row"> <div class="fieldBox"> <label for="id_excel_file" class="required">Excel File:</label> <input type="file" name="excel_file" id="id_excel_file" accept=".xlsx,.xls" required> <div class="help">Upload an Excel file with the required columns</div> </div> </div> </fieldset> <div class="help-text"> <p><strong>{% trans 'Required fields in the imported file:' %}</strong></p> <ul> <li>code RMA</li> <li>code ACAPS</li> <li>Dénomination RMA</li> <li>Ville</li> <li>Adresse</li> <li>Longitude</li> <li>Latitude</li> <li>Type BGD</li> <li>Partenaire</li> <li>Date création</li> <li>Etat BGD RMA</li> </ul> </div> <div class="submit-row"> <input type="submit" value="{% trans 'Import Excel' %}" class="default" name="_import_file"> </div> </div> </form> </div> {% endblock %}  when I click import file, the page refreshes and no message is displayed as if the process file function isn't executed

Answer: Problem: Your custom <form> never hits Django admin’s add_view/changeform_view, so save_model/process_excel_import isn’t called and no messages ever display.  Option 1: Override the Admin View Intercept your “Import Excel” POST, run process_excel_import, then redirect so messages render: from django.contrib import admin, messages from django.http import HttpResponseRedirect import pandas as pd from .models import RMABGD @admin.register(RMABGD) class RMABGDAdmin(admin.ModelAdmin): add_form_template = 'admin/spatial_data/RMABGD/change_form.html' change_form_template = add_form_template # list_display, list_filter, search_fields … def process_excel_import(self, request): f = request.FILES.get('excel_file') if not f: messages.error(request, "Please choose an Excel file.") return False try: df = pd.read_excel(f) required = ["code RMA","code ACAPS","Dénomination RMA","Ville", "Adresse","Longitude","Latitude","Type BGD", "Partenaire","Date création","Etat BGD RMA"] missing = [h for h in required if h not in df.columns] if missing: messages.error(request, f"Missing columns: {', '.join(missing)}") return False imported = 0 for i, row in df.iterrows(): try: RMABGD.objects.create( code_ACAPS=row["code ACAPS"], code_RMA=row["code RMA"], name=row["Dénomination RMA"], address=row["Adresse"], city=row["Ville"], location=f'POINT({row["Longitude"]} {row["Latitude"]})', type_BGD=row["Type BGD"], Partenaire=row["Partenaire"], date_creation=row["Date création"], RMA_BGD_state=row["Etat BGD RMA"] ) imported += 1 except Exception as e: messages.error(request, f"Row {i+1}: {e}") if imported: messages.success(request, f"Imported {imported} rows") else: messages.warning(request, "No rows were imported") return imported > 0 except Exception as e: messages.error(request, f"Error processing file: {e}") return False def changeform_view(self, request, object_id=None, form_url='', extra_context=None): if request.method == 'POST' and '_import_file' in request.POST: self.process_excel_import(request) return HttpResponseRedirect(request.path) return super().changeform_view(request, object_id, form_url, extra_context)   If you only need it on the Add page, override add_view instead of changeform_view.   Option 2: Use django-import-export A battle-tested library that adds Import/Export buttons with preview, validation and messages:  Install pip install django-import-export   Enable in settings.py INSTALLED_APPS += ['import_export']   Define Resource & Admin from import_export import resources from import_export.admin import ImportExportModelAdmin from .models import RMABGD class RMABGDResource(resources.ModelResource): class Meta: model = RMABGD fields = ( 'code_ACAPS','code_RMA','name','address','city', 'location','type_BGD','Partenaire','date_creation', 'RMA_BGD_state', ) @admin.register(RMABGD) class RMABGDAdmin(ImportExportModelAdmin): resource_class = RMABGDResource # list_display, list_filter, search_fields …   Use Visit your model in the admin: you’ll now see Import/Export buttons, handle .xlsx/.xls, preview rows and errors, and get automatic Django-style messages.    Recommendation  Quick fix: go with Option 1.  Long-term/scale: prefer Option 2 (django-import-export) for best UX and maintainability.