问题
How can I distinguish between, for example, a post_save that comes from a regular view and one that comes from the admin?
回答1:
By overriding ModelAdmin.response_add you may get a similar functionality, as it seems that the django admin does not sent any signals.
The response_add function gets called after it successfully validated and added all data, such as related fields but also the object itself.
So by overriding the response_add method in our own ModelAdmin class we can execute code after something in the admin got added successfully, but won't be executed somewhere else.
I did the following way in django 1.4, any comments or feedback greatly appreciated! It seems to be working well in my case, but I'm not so familiar with all the internals in Django yet and if it's a suggested way to do it. But it sounds better than a threadlocal hack to me.
Side note: I guess you could also fire signals yourself by overriding the ModelAdmin, but not experience with that.
This is the code I used to override response_add, which will execute product_get_initial_info(obj.id) only a product was successfully added in the admin:
class ProductAdmin(admin.ModelAdmin):
prepopulated_fields = {"slug": ("title",)}
inlines = [
ProductInline,
]
def response_add(self, request, obj, post_url_continue='../%s/'):
if obj and obj.id:
tasks.product_get_initial_info(obj.id)
return super(ProductAdmin, self).response_add(request, obj, post_url_continue='../%s/')
The related django source code is here: django/contrib/admin/options.py
class ModelAdmin(BaseModelAdmin):
def add_view(self, request,...)
# .... Many lines of code ...... not putting them here as they're not so relevant
if all_valid(formsets) and form_validated:
self.save_model(request, new_object, form, False)
self.save_related(request, form, formsets, False)
self.log_addition(request, new_object)
# After saving everything response_add gets called with the newly created object
return self.response_add(request, new_object)
回答2:
There's not a straightforward way to do this, which implies to me you might not putting your code in the right place by using the post_save signal.
That said, if you really want to, you could use a threadlocal hack to get access to the request object and figure out if the currently running view is an admin view. To read about how to do the threadlocal hack, start in the django cookbook but just save the whole request instead of the user. Note that lots of people think threadlocal hacks are an abomination. Here's a discussion. I think they have a very useful place, but without knowing more, I'd guess there's a better solution for you.
来源:https://stackoverflow.com/questions/5305520/django-signals-from-admin