How to know if a model instance was modified by another user - python

I am writing a Django application where users manipulate a Model. A typical session for users is this :
they get the model ;
they do some actions (vizualise the model's datas, change these datas..);
then, they save the model if they modified something.
But, if two users are manipulating the same instance of the model, and one save his modification after the second loaded it, I want to be able to "notify" the second that the model has changed, so he can reload it.
I could perform a get to check if there was a modification in the database every time a view is called, but it doesn't seems optimal.
I have looked at Django's signals too, but I don't know how to send a signal to users manipulating a specific instance of the model.
Do you have any ideas on how I can do it ?

Related

How to use the data about objects modifications in Django?

Django stores a history of the modification for every object, it is something we can access to through the Django admin:
It contains data about when the object was created/modified, the user who performed the action and the timestamp of the action:
By giving a look at the database, I can guess this data is stored in a default table called django_admin_log:
I am wondering if we can make use of this data in any way through the instance of a model ? I got used to adding manually my timestamps on every models through an Abstract Base Class, but I am wondering if it is useful in any way ?
Or this table records only the modification taking place in the Django admin panel, which would makes the custom timestamp still needed for when the models instance were to be updated outside it.
The history is only related to actions done in the admin view. To add metadata you can also use model_utils, which also offers some other handy functionalities: https://django-model-utils.readthedocs.io/en/latest/
Let us assume every action would be stored in a history table. This would indicate that you always have make a join in the db to get a view where each row also has created and updated information. This is quite some overhead. Therefore, keep it simple and add the timestamp to each model :)

How do I ensure that certain model instances are always present in django database?

My django-application requires a few model instances to always be present in the database to function properly.
I currently create the model instances that I require in the Appconfig.ready(self) method for the corresponding app. This way the instances are always present on boot of the django-application. This works but not as well as I'd like, I have to be careful when deleting objects so that I do not delete the required objects.
I would like the required model instances to be undeletable or preferably, be created whenever they are not present in the database.
I agree with your solution about protecting certain objects from deletion in you problem. To do this there are two ways I can think of:
When deletion is happening check to see if object is protected or not
Tweak admin permissions and do not let anyone delete the object from admin panel
The main difference is in first way your only way to delete protected objects is from your database command line interface, However in second way the model can be deleted in code.
For the first way you need to override delete method of the model and check something like this
assert pk != self.protected_objects
Where protected objects list is a property of your model class.
For second way you would do
class YourModel(admin.ModelAdmin):
protected_objects = [1,2,...]
def has_delete_permission(self, request, obj=None):
return obj.pk not in self.protected_objects

set initial values of ModelForm in Django

I use "msignup" model for user signups. after signup is complete which works just fine, in the profile of the user I want to let them change some basic information that they used during the signup (which are saved in database in msignup model) using modelform named "accountSettingsForm".
Obviously the original user information must be there in the "accountSettingsForm " and the user would change any piece of information he/she likes.
I know it is possible to set the initial value of the accountSettingsForm:
form = accountSettingsForm(initial={'someFieldName':snomeVariable})
But I assume there is a better way of doing this that I don't know about.
Probably using __init__ methods is more appropriate.
Any helps will be greatly appreciated.

Saving data on server side using REST

I'm using django rest framework and trying to save some data so it will be accessible by GET, PUT, DELETE.
So when user send GET request server send some information (a random number, for example) and that information is needed after user sends PUT request on the same url. How would one save such information? I'm using class-based views.
So i want to save that information on GET method.
I tried saving that information to class variable self.information, but the problem is self.information is empty when PUT method is getting called.
I also tried saving it to session, but like class variable, session is also empty when PUT method is being executed.
class SampleClass(mixins.RetrieveModelMixin, mixins.UpdateModelMixin, generics.GenericAPIView):
serializer_class = SampleSerializer
def get(self, request):
random_number = random.randint(0, 10)
request.session['number'] = random_number;
content = {'random_number': random_number}
return Response(content)
def put(self, request):
number = request.session['number'] # key doesn't exists
process_number(number)
# ...
Before I begin, it's important to note that HTTP is a stateless protocol, and you are looking to add state into the mix. If you can rework what you are doing to not depend on previous requests, that will probably be better in the long run.
I tried saving that information to class variable self.information, but the problem is self.information is empty when PUT method is getting called.
This is because the class is re-initialized for each request. Because of that, the class variables don't persist across requests. Even if they did, that would mean everyone would get access to the persisted value, and it isn't made clear if that is what you are looking for.
I also tried saving it to session, but like class variable, session is also empty when PUT method is being executed
This doesn't work because Django sessions are persisted through the use of cookies. While this might work for SessionAuthentication, it won't work for any authentication that happens outside of the browser. This is because the session cookies won't be included, so Django will think the new requests are under a different session.
Now, just because HTTP is mostly stateless and doing this might lead to future trouble, that doesn't mean that you should never do it. The Django sessions wouldn't exist if there wasn't a need for it, and there are ways to save state without Django sessions.
Create a new model for the state - This is usually the best way to save state per-user and ensure that it doesn't fade away. The model needs a user field along with the fields that the state will be stored in, and all you need to do is have a query that retrieves the state object for the user.
Use the Django cache - This is the way I would recommend it for the case that you specified in your question. When you don't need to store much state, the state is shared among everyone, or you can live with it not existing (expiring), storing the data in a simple cache environment will probably work the best. You have much more control over what is stored, but at the expense of having to do more work.

Difference between Model and Form validation

I'm currently working on a model that has been already built and i need to add some validation managment. (accessing to two fields and checking data, nothing too dramatic)
I was wondering about the exact difference between models and forms at a validation point of view and if i would be able to just make a clean method raising errors as in a formview in a model view ?
for extra knowledge, why are thoses two things separated ?
And finnaly, what would you do ? There are already some methods written for the model and i don't know yet if i would rewrite it to morph it into a form and simply add the clean() method + i don't exactly know how they work.
Oh, and everything is in the admin interface, havn't yet worked a lot on it since i started django not so long ago.
Thanks in advance,
You should use model (field) validation to make sure the returning datatype meets your database's requirements. Usually you won't need this because django's builtin fields do this for you, so unless you've built some custom field or know what you are doing you shouldn't change things.
Form validation is where you clean the user's input, you can add a clean method for every form field by adding a clean_FIELD(self) method, e.g.
class ContactForm(forms.Form):
# Everything as before.
...
def clean_recipients(self):
data = self.cleaned_data['recipients']
if "fred#example.com" not in data:
raise forms.ValidationError("You have forgotten about Fred!")
# Always return the cleaned data, whether you have changed it or
# not.
return data
Before a Form's main clean method is ran, it checks for a field level clean for each of its fields
Generally models represent business entities which may be stored in some persistent storage (usually relational DB). Forms are used to render HTML forms which may retreive data from users.
Django supports creating forms on the basis of models (using ModelForm class). Forms may be used to fetch data which should be saved in persistent storage, but that's not only the case - one may use forms just to get data to be searched in persistent storage or passed to external service, feed some application counters, test web browser engines, render some text on the basis of data entered by user (e.g. "Hello USERNAME"), login user etc.
Calling save() on model instance should guarantee that data will be saved in persistent storage if and only data is valid - that will provide consistent mechanism of validation of data before saving to persistent storage, regardless whether business entity is to be saved after user clicks "Save me" button on web page or in django interactive shell user will execute save() method of model instance.

Categories