Django - Difference between admin save_model() and post_save signal - django

For my application I need to do extra operations when a model is saved via form. In practice, I need to add a value in another model if certain conditions are present in the form.
To do this I have two options, but I want to understand the pros and cons of both.
Use the post_save signal
Overwrite the save_model method in admin.py, since it is said in the documentation that "Overriding this method allows doing pre- or post-save operations."
I currently use the latter in this way
def save_model(self, request, obj, form, change):
#some pre save operations....
#this call the save model method
super(MyModelAdmin, self).save_model(request, obj, form, change)
#some post save operations...
and it works
But what I want to understand is:
For what I must do, what are the differences between the two approaches and what is the most correct.
Is the save_model method related to the use of the admin interface? What happens if I use another frontend different from Django's admin?
In general, what is the difference between doing pre and post save operations overwriting save_model and using signals?

I think you got it right. And this might help you to understand the difference.
save_model method from ModelAdmin called when you are trying to create or update something from django admin only but signals are triggered regardless of place where actions happened. Which means pre or post operations in save_model method won't work if you change model from somewhere outside of django admin but signals will work for both from outside of admin views and from your custom written code blocks.

If possible i would prefer to add signals over overwriting the save_model. Signals allow certain senders to notify a set of receivers that some action has taken place. They're especially useful when many pieces of code may be interested in the same events. Also it is like event driven programming paradigm. That helps to make code organize and clean.

Let us take a rather regular example of the process. We want to register a new user and we also have created a profile model that we want a user's profile saved only when valid User information is saved.
We can create a new User in the Django's admin and use the saved_model method in the ModelAdmin to save other parts of the form to the Profile model. This is the "normal" way of doing it. But using this way, you can only access the User and the Profile from the Django Admin panel. A "User Registration" form outside of the Django Admin would not work since the User would have to be registered to access Django Admin controls.
But using the post_save signal, a new User and Profile can be created and updated whether you use the Django Admin panel or a custom form that saves to the User and Profile models.
Therefore using signals is the most flexible but you will now have to make sure you have a way of validating the information coming from the custom form.

Related

Django: Last modified by and created by user automatic saving

The age-old question: How can I automatically save last_modifed_user in django models?
I found in several places this general process how to do it using thread local. I'm hesitant to simply implement it that way because I'm not entirely sure of the consequences it has and because all these posts are old.
Is using thread local still the "recommended" way of doing this in django 3? Or does django3 have a better options of doing it?
No, this hasn't changed. Simply because separation of concern is an architectural principle of MVC (model-view-controller), which is also how Django (model-view-template) and most web frameworks with ORM are architected. Models know nothing about the request, it's not available (and in many cases there isn't a request at all when a model is saved, think of management commands or regular tasks running in the background).
The alternative to thread local is to make sure you implement it yourself in the controller layer (view layer in Django):
Create a view mixin that you can mix with all the generic views that use the ModelFormMixin to save the user into the model (ModelFormMixin.form_valid()). Or combine it with a form mixin where the user is passed to the form (FormMixin.get_form_kwargs()) and saved when the form is saved (ModelForm.save()).
Create a ModelAdmin mixin that does the same when saving a model in the django admin site.
This of course means someone on your team may forget to do it when creating new views and forms. The link you posted contains an answer as to the advantages and disadvantages of using thread local.

Whats the different between override the update method inside view and inside serializers?

I am new in django i know this is a naive question but im so confused about when exactly do we have to override update method located in view and when do we have to override update method located in serializer?
From the documentation:
1) Creating, Updating in views:
perform_create(self, serializer)
perform_update(self, serializer)
perform_destroy(self, serializer)
These hooks are particularly useful for setting attributes that are implicit in the request, but are not part of the request data. For instance, you might set an attribute on the object based on the request user, or based on a URL keyword argument.
These override points are also particularly useful for adding behavior that occurs before or after saving an object, such as emailing a confirmation, or logging the update.
You can also use these hooks to provide additional validation, by raising a ValidationError(). This can be useful if you need some validation logic to apply at the point of database save.
2) Creating, Updating in serializers:
If we want to be able to return complete object instances based on the validated data we need to implement one or both of the .create() and .update() methods.
If your object instances correspond to Django models you'll also want to ensure that these methods save the object to the database.
Also you can override create, update methods for nested operations.

Ajax - How to save automatically my Django form

i have an add_form under my django app. i want to add a feature this form which is saving form automatically after user starts to type.
like in gmail , or blogger.
what are the steps i should follow? which way or plugin? and how to use them?
any knowlenge can help me.thank you.
There's two useful jquery plugins to get you started
https://github.com/BenGriffiths/jquery-save-as-you-type which saves what you type locally to a cookie client-side. Using this plugin is simpler and you will only need to actually save into your django backend when the user hits your form's "save" button.
and
https://github.com/nervetattoo/jquery-autosave which requires that you set up an intermediary model (perhaps a Draft model) in django to keep track of updates along the way. And when the user finally hits save, a final copy of the data is then saved into the actual model.

Project platform suggestion for web application with proper User Auth and integration support

So, I have an idea to build a web app. I am new to this business but am a programmer. I liked Python and thought let me start with Django. I ran into a problem with the built-in Django User Auth system as pointed by this question of mine on SO.
In short, I am using Django's built-in User auth and thought that it will easily fill my user field (the foreignkey) in my model but it does not. I have Googled and asked questions but only got a very convoluted answer or that I have to use the Admin section if I want anything like that.
My simple need is that whenever user saves anything in their profile, the user field should get populated so that I can reference it. To me, it sounds like the most basic need for any web app.
Am I wrong. I need advice. If Django is not good for this then I am ready to learn any other good framework or platform if need be.
In short, I am using Django's built-in
User auth and thought that it will
easily fill my user field (the
foreignkey) in my model but it does
not.
This won't just magically happen. You will have make it happen. Models are separated from the request so this would happen in your view, or a model method (perhaps save) that is passed the active user.
MVC / MTV design separates the database from the view / control logic. I don't see what framework has to do with this: unless you write the functionality yourself, the database doesn't know what to do with some User table and the currently logged in user (also separated from the data). Building in this functionality would inconvenience a lot of people as well...
In general, the python/django philosophy is: Explicit is better than implicit.
Now the solutions:
If you wanted this behavior in the view, for any form, you could potentially write:
instance = MyForm.save(commit=False) # commit=False prevents DB save.
instance.user = request.user
instance.save()
You could overwrite the save method on the model that accepts an optional user argument as well.
def save(self, *args, **kwargs):
user = kwargs.pop(user, None)
self.user = user
super(MyModel, self).save(*args, **kwargs)
mymodel = MyModel()
mymodel.save(user=request.user)

Django databrowse with custom queryset?

Django's databrowse is very different from the rest of django in that the docs literally don't exist. Has anyone tried to do more that databrowse.site.register on a model? Any code examples?
In particular, I've got a model that has a ForeignKey to an auth.Group and I want databrowse to use this queryset instead of .all():
qs = Model.objects.filter(group__in=request.user.groups.all())
Bonus points for making it possible to have a button that does stuff with the current object (edit/delete/clone/etc). I basically need a simple way to browse and edit rows without giving users access to the admin.
It'd be even better if there was a way to do that on the admin, but I don't want to give users the staff privilege.
There's no way to do this through databrowse. You could try writing a custom Manager for your Model and return the required query set by default.