4

I am putting together a Django app - created and registered the models and model forms.

When adding or editing a particular model record, I need to call an external service for some information. If the information is retrieved successfully I want to update a column on that model which the user is unaware of and save the model. If the call fails I need to prevent the save from occurring and a custom message returned to the user.

I have tried raising Exceptions, returning messages as String etc but nothing seems to work. Although I can stop the save from occurring I end up with a stack-trace if I don't return the model.

I have seen various solutions using the clean() method or signals but none seem to suit the need.

The order of things I need to happen:

  1. Validate the Form data being entered (happens automatically)

  2. Do the API call to the external service to retrieve the info

  3. Assign the info to the model prop and save the model

  4. If API call fails, cancel save() and display message to user telling them the save has failed with a reason why. If the save fails then the page should reload and not be redirected to the listing page.

I just cannot seem to find a simple solution out there - any help appreciated!

solo1977
  • 355
  • 3
  • 14

3 Answers3

2
from django.contrib import messages

class MyAdminView(admin.ModelAdmin):
    def save_model(self, request, obj, form, change):
        try:
            super(MyAdminView, self).save_model(request, obj, form, change)
        except Exception as e:
            messages.set_level(request, messages.ERROR)
            messages.error(request, e)
Sawan Chauhan
  • 621
  • 7
  • 9
1

You can overwrite save_model of ModelAdmin.

  class MyAdminView(admin.ModelAdmin):
       def save_model(self, request, obj, form, change):
           super(MyAdminView, self).save_model(request, obj, form, change)
Iakovos Belonias
  • 1,217
  • 9
  • 25
  • That doesn't quite suit the needs. Although I can prevent the save from occurring the page redirects to the listing page with a success message. I should add though I think that is on the right track and may be a route to the overall solution – solo1977 May 10 '19 at 16:13
  • What you can't do? What you wanted was not to save and inform with proper message – Iakovos Belonias May 10 '19 at 16:15
  • I have edited the question to make it a little clearer - apologies for the confusion. I need to stop the model being saved and to tell the user what the issue was (in this case the external API call failing) – solo1977 May 10 '19 at 16:19
  • Have you tried to raise an error? https://docs.djangoproject.com/en/2.2/ref/exceptions/ – Iakovos Belonias May 10 '19 at 16:23
  • 1
    Raising an Exception in either save() or save_model() results in a stacktrace being displayed in the browser. – solo1977 May 10 '19 at 19:17
  • Raising a ValidationError in the clean() method seems to be the only way, however I do not have access to the model being saved in that method. Although there is self.instance, the properties of the model are not populated. – solo1977 May 10 '19 at 19:21
0

It seems to me that a successful API call is part of the validation process. According to this point of view, you can just check the API connection in clean() and throw a yourForm.add_error(None, "sometext") that will appear on the form if this goes wrong.

You can then proceed overriding yourModelAdmin.save_model(), including a new API call that will get and process the data this time, with confidence that everything will work as expected.

Keep in mind that according to the documentation here, ModelAdmin.save_model() should not be used to prevent saving the object.

gkaravo
  • 133
  • 1
  • 8