简体   繁体   中英

Django pre_save signal and ModelAdmin custom error message

I have a model whose pre_save() signal is connected to a remove service (json, REST, etc.) in the following way:

  1. before saving locally, query the remote service, asking for remote insertion
  2. remote service does its things, the main being checking that a relevant entry does not already exist.
  3. On success (HTTP 201), all is good, the local model uses the remote service response to populate the db.
  4. on failure, the service returns an HTTP 400 (the status code is debatable but that is for a different question on SO :-) )
  5. The error response is in the following form:

    {'local_model_field': [u'This element already exists']}

  6. The local model pre_save signal then raises a ValidationError :

    raise ValidationError(json_response['local_model_field'][0])

This works nicely.

Now, on the django admin, when I try to simulate the remote insertion of an already-existing object, I get a 500 page, which is fine but not ideal.

Is there any way to have the pre_save() error bubble all the way up to the ModelAdmin and be displayed as a standard error message, populated with the relevant content?

I have tried the following but to no avail:

def changeform_view(self, request, object_id=None, form_url='', extra_context=None):
    """
    trying to display the right message when pre_save() fails on model save() method (after asking CC)
    """
    try:
        return super(ObjectAdmin, self).changeform_view(request, object_id, form_url, extra_context)
    except IntegrityError as e:
        self.message_user(request, e, level=messages.ERROR)
        return HttpResponseRedirect(form_url)

Is a ValidationError the right thing to do? Knowing that the pre_save() must lock out any chance of ending with with duplicates both locally and remotely. The main reason is that the local/remote object creation can be made form the admin but also from other website instances/types (front-end, end-user facing, for example).

Thanks

Not sure if this is still relevant. But the way I solved this is by creating a ModelForm:

class AuthorAdminForm(forms.ModelForm):

    def clean(self):
        # or some api calls here
        if self.instance.id > 4:
            self.instance.name = "4+"
        else:
            ValidationError("Id is bigger that 4")
        return super().clean()

And then by adding the form to the admin model:

class AuthorAdmin(admin.ModelAdmin):
    form = AuthorAdminForm

This clean() method will ensure that you could add/modify fields before you hit the model save() method and still throw a ValidationError if something goes south like a 404 error when hitting a url

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM