How to override Django model creation without affecting update? - python

I overrided the save() method of my Fooclass so that when I create a Foo instance, some logic occurs. It works well.
Nevertheless, I have other methods in other classes that update Foo instances, and of course, I have to save changes calling the save() method. But I want them to directly update without passing into the logic I made for object creation.
Is there an elegant solution to that?
What about overriding __init__() method instead of save()? (I was told it was a bad practice, but not sure to understand why)
Thank you.

You should not override __init__, because that is called in all cases when a model is being instantiated, including when you load it from the database.
A good way to do what you want is to check the value of self.pk within your save method: if it is None, then this is a new instance being created.

Related

Advantages of using static methods over instance methods in python

My IDE keeps suggesting I convert my instance methods to static methods. I guess because I haven't referenced any self within these methods.
An example is :
class NotificationViewSet(NSViewSet):
def pre_create_processing(self, request, obj):
log.debug(" creating messages ")
# Ensure data is consistent and belongs to the sending bot.
obj['user_id'] = request.auth.owner.id
obj['bot_id'] = request.auth.id
So my question would be: do I lose anything by just ignoring the IDE suggestions, or is there more to it?
This is a matter of workflow, intentions with your design, and also a somewhat subjective decision.
First of all, you are right, your IDE suggests converting the method to a static method because the method does not use the instance. It is most likely a good idea to follow this suggestion, but you might have a few reasons to ignore it.
Possible reasons to ignore it:
The code is soon to be changed to use the instance (on the other hand, the idea of soon is subjective, so be careful)
The code is legacy and not entirely understood/known
The interface is used in a polymorphic/duck typed way (e.g. you have a collection of objects with this method and you want to call them in a uniform way, but the implementation in this class happens to not need to use the instance - which is a bit of a code smell)
The interface is specified externally and cannot be changed (this is analog to the previous reason)
The AST of the code is read/manipulated either by itself or something that uses it and expects this method to be an instance method (this again is an external dependency on the interface)
I'm sure there can be more, but failing these types of reasons I would follow the suggestion. However, if the method does not belong to the class (e.g. factory method or something similar), I would refactor it to not be part of the class.
I think that you might be mixing up some terminology - the example is not a class method. Class methods receive the class as the first argument, they do not receive the instance. In this case you have a normal instance method that is not using its instance.
If the method does not belong in the class, you can move it out of the class and make it a standard function. Otherwise, if it should be bundled as part of the class, e.g. it's a factory function, then you should probably make it a static method as this (at a minimum) serves as useful documentation to users of your class that the method is coupled to the class, but not dependent on it's state.
Making the method static also has the advantage this it can be overridden in subclasses of the class. If the method was moved outside of the class as a regular function then subclassing is not possible.

Is there an easy way to "reload" an object's methods without re-instantiating it entirely?

This is typical pattern that I run into in Python but probably applies to most other multi-paradigm languages.
I write a bunch of functions. Some of these are like load_data() and some are like do_something_with_data(). That is the latter acts on the data that is read in with the first function. Let's say it takes 1 minute to read in the data.
After a while I refactor the code so that these are both methods within a class. While this seems neater, it is also harder to develop on. That is, if I fix a bug in do_something_with_data() the object that is already instantiated is not fixed. I have to re-instantiate it which might take a minute or so since it has to read the data.
object=my_object();object.load_data();object.do_something_with_data()
I am wondering if there is a good pattern for handling this issue. Can you update an object's methods without refreshing the data? Should I write a method that takes an old object and copies in all the data fields from an object that has been saved? Other ideas?
Methods are looked up on the class. On module reload, existing instances end up referencing a class that no longer exists; their __class__ points to an object that was the old module.classname, and is not the same object as the new module.classname.
You have two options:
Update the old class to have your new method:
existing_instance.__class__.methodname = module.classname.methodname.__func__
Replace the class references on the existing objects:
existing_instance.__class__ = module.classname

Dangers of dynamically modifying entity Model in App Engine

I have a class from which all my entity definitions inherit:
class Model(db.Model):
"""Superclass for all others; contains generic properties and methods."""
created = db.DateTimeProperty(auto_now_add=True)
modified = db.DateTimeProperty(auto_now=True)
For various reasons I want to be able to occasionally modify an entity without changing its modified property. I found this example:
Model.__dict__["modified"].__dict__["auto_now"] = False
db.put(my_entity)
Model.__dict__["modified"].__dict__["auto_now"] = True
When I test this locally, it works great. My question is this: could this have wider ramifications for any other code that happens to be saving entities during the small period of time Model is altered? I could see that leading to incredibly confusing bugs. But maybe this little change only affects the current process/thread or whatever?
Any other request coming in to the same instance and being handled whilst the put is in progress will also get auto_now=False, whilst unlikely it is possible
Something else other thing to consider
You don't have try block around this code, if you get a timeout or error during the put() your code will leave the model in the modified state with auto_now=False .
Personally in think its a bad idea and will definatley be a source of errors.
There are a number of ways of achieving this without manipulating models,
consider setting the default behaviour to auto_now=False, and then have two methods you use for updating. The primary method sets the modified time to datetime.now() just before you do the put(), e.g save() and save_without_modified()
A better method would to override put() in your class, then set modified and then call super put() have put() accept a new argument like modified=False so you don't set the modified date before you call super.
Lastly you could use _pre_put hook to run code before the put() call, but you need to annotate the instance in some way so the _pre_put method can determine if modified needs to be set or not.
I think each of these strategies is a lot more safe than hacking the model

Real world example of overriding __new__ method in Python

I'm familiar with the theory about __new__ vs __init__. The former one defines how an instance of a class is created (new object inside the memory), whereas the latter one initializes it (assigns initial state attributes - fields). There is a couple of articles in the web about this, such as this one:
Use __new__ when you need to control the creation of a new instance.
Use __init__ when you need to control initialization of a new
instance.
As I said, I do understand the difference, yet, I can't imagine a real world example of situation when I need to use __new__ instead of __init__. If I can customize something during object creation, I can move it to object initialization - as long as it's the same object. The mentioned link says:
In general, you shouldn't need to override __new__ unless you're
subclassing an immutable type like str, int, unicode or tuple.
And here comes my question - can someone give an example of situation, when overriding __new__ is in fact the right solution that can't be done using __init__ and why is that?
Singletone pattern - the most obvious example.
When you've created one more object - it is not the singletone, right?
Thus, you have to handle this when you're creating your object. One variant of the solution - to use __new__() method.

Conditional use of __setstate__ in unpickling

So I have a class that remembers its instances based on an ID. When unpickling such an object there are two cases I'd like to handle:
No other instance with that ID exists, so a new instance is generated and __setstate__ should be called normally.
When another instance of that ID exists, that object is returned and I want to avoid calling __setstate__ on it.
Please take a look at this class definition.
You will notice that currently I update only attributes that evaluate to False as a workaround.
I can think of two general strategies to solve this:
As in this previous answer, I could define another function that is called with the result from __getnewargs__ and attach some attribute that tells me whether to run __setstate__ or not.
If I can tell whether the class' __call__ method was called from within pickle I could do the same.
I do not know if it's possible to further interfere with the pickling machinery and I don't want to subclass the unpickler.
Thoughts, recommendations, completely different solutions? Thank you.

Categories

Resources