How to customize pickle for django model objects - python

My app uses a "per-user session" to allow multiple sessions from the same user to share state. It operates very similarly to the django session by pickling objects.
I need to pickle a complex object that refers to django model objects. The standard pickling process stores a denormalized object in the pickle. So if the object changes on the database between pickling and unpickling, the model is now out of date. (I know this is true with in-memory objects too, but the pickling is a convenient time to address it.)
Clearly it would be cleaner to store this complex in the database, but it's not practical. The code for it is necessarily changing rapidly as the project evolves. Having to update the database schema every time the object's data model changes would slow the project down a lot.
So what I'd like is a way to not pickle the full django model object. Instead just store its class and id, and re-fetch the contents from the database on load. Can I specify a custom pickle method for this class? I'm happy to write a wrapper class around the django model to handle the lazy fetching from db, if there's a way to do the pickling.

It's unclear what your goal is.
"But if I just store the id and class in a tuple then I'm necessarily going back to the database every time I use any of the django objects. I'd like to be able to keep the ones I'm using in memory over the course of a page request."
This doesn't make sense, since a view function is a page request and you have local variables in your view function that keep your objects around until you're finished.
Further, Django's ORM bas a cache.
Finally, the Django-supplied session is the usual place for "in-memory objects" between requests.
You shouldn't need to pickle anything.

You can overload the serialization methods. But it would be simpler to put the id and class in a tuple or dict and pickle that.

Related

How can I create multiple polymorphic Django models using the same table

I've got a situation where I have one base Django model Rolls, mapped to the table rolls. There are multiple types of rolls, controlled by a column called type. In the older codebase I'm writing a v2 for (used to be PHP), I created subclasses for each type, that controlled setting their own type value, and it worked fine. I can't figure out how to set this up in Django.
I'd like them all to use the same table, and each will derive methods from the base model, but have different implementations for many of those methods. I figure I can write a manager to handle getting back the right values, but I can't figure out how to setup the models.
I tried setting a single base model and then derived other models from it, but those created different tables for each of them. Using managed = False seems the wrong way to go, given the subclasses don't represent tables of their own.
You're on the right track, but I believe you want proxy models and not unmanaged ones, e.g. proxy = True:
Sometimes, however, you only want to change the Python behavior of a model – perhaps to change the default manager, or add a new method.
This is what proxy model inheritance is for: creating a proxy for the original model. You can create, delete and update instances of the proxy model and all the data will be saved as if you were using the original (non-proxied) model. The difference is that you can change things like the default model ordering or the default manager in the proxy, without having to alter the original.
Then you could override each subclass' save method to set the correct type, and each subclass' default query manager to filter on that type.

Creating a dynamic ORM resource in tastypie

I'm looking to create a dynamic resource in tastypie. Basically the idea is that there are a lot of models to hook up, so this may help save time with the standard no-frills resources.
I have most of this working, however I'm having trouble with the related fields being populated. I'm overriding the constructor for a class that inherits from ModelResource, and in this constructor I'm attempting to set the tastypie relationships. However when I review my resource the data is not being populated.
setattr(self, field, fields.ForeignKey(class_thing, attribute=field, full=True))
Basically I'm using setattr in the constructor to try and hook up what the relationship should be. If I'm goofing off with the instance I can see this object is getting created but the resource output is not changing. Is anyone familiar enough with tastypie/doing something like this to give me a clue?
Thanks for your time.
Edit: Nevermind, just overrode dehydrate and did this from there.
Rather than go through the constructor (which is messy since tastypie/django does stuff there anyway) I did this through a dehydrate override which is kind of designed to do this.
The bundle.obj has all the associated data there, so basically I just serialized the related objects and add them to the bundle.data dictionary before returning the bundle. Seemed cleaner and worked like a charm.

Is __new__ a good way to retrieve a SQLAlchemy object

I am using SQLAlchemy and I just read about the __new__ function. I also read the other posts here about __new__ so I am aware of the difference to __init__, the order they get called and their purpose and the main message for me was: Use __new__ to control the creation of a new instance.
So with that in mind, when I work with SQLAlchemy and want to retrieve an instance (and create one if it does not already exist, e.g. retrieve a User object, I normally do this:
user = DBSession.query(User).filter(User.id==user_id).first()
if not user:
user = User()
This would either return the current user or give me a new one. Now with my new knowledge about magic, I thought something like this could be a good idea:
user = User(id=user_id)
And in my database class, I would call:
def __new__(cls, id=0):
if id:
user = DBSession.query(User).filter(User.id==id).first()
if not id or not user:
user = super(User, cls).__new__(cls, id=id)
return user
Now this code is only a quick draft (e.g. a call to super is missing) but it should clearly point out the idea.
Now my question: Is this a good practice or should I avoid this? If it should be avoided: Why?
Based on your question and your comments, I would suggest you not do this, because it doesn't appear you have any reason to do so, and you don't seem to understand what you're doing.
You say that you will put certain code __new__. But in the __new__ of what? If you have this:
class User(Base):
def __new__(cls, id=0):
if id:
user = DBSession.query(User).filter(User.id==id).first()
if not user:
user = User()
return user
. . . then when you try to create a User instance, its __new__ will try to create another instance, and so on, leading to infinite recursion.
Using user = User.__init__() solves nothing. __init__ always returns None, so you will just be trying to create a None object.
The appropriate use case for __new__ is when you want to change what kind of object is returned when you instantiate a class by doing SomeClass(). It is rare to need to do this. The most common case is when you want to create a user-defined class that mimics a builtin type such as dict, but even then you might not need to do this.
If your code works without overriding __new__, don't override __new__. Only override it if you have a specific problem or task that can't be solved in another way.
From what I see and unterstand, there is no reason why not to put your code into __init__ instead of __new__. There are only a few and very limited - but valid - uses cases for __new__ and you should really know what you are doing. So unless you have a very good reason, stick with __init__.
There is a very distinct difference between the first example (checking the return value) and the second (using the constructor immediately); and that difference is the free variable: DBSession.
In some cases, this difference is not interesting; If you are only using your sqlalchemy mapped objects for database persistence; and then only in contexts where sqlalchemy.orm.scopedsession is permissible (exactly one session per thread). then the difference is not very interesting.
I have found it unusual for both of these conditions to hold, and often neither holds.
By doing this you are preventing the objects from being useful outside the context of database persistence. By disconnecting your models from the database, your application can answer questions like "what if this object had this attribute?" in addition to questions like "does this object have this attribute?" This gets to the crux of why we map database values as python objects, so that they can have interesting behaviors, instead of just as dicts, which are merely bags of attributes.
For instance, in addition to using a regular database persistent login; you might allow users to log into your site with something like OAuth. Although you don't need to persist the users' name and password to your database, you still need to create the User object for the rest of your application to work (so that the user's gravatar shows up in the template).
The other question of implicitly accessing a particular database context by default is usually a bad idea. As applications grow, the need to manage how a database gets more complicated. Objects may be partitioned across several database hosts; you may be managing several concurrent transactions in the same thread; you might want to reuse a particular session for caching performance reasons. The sqlalchemy Session class exists to address all of these peculiarities; managing them explicitly, even when you are just using the most common pattern; makes dealing with the occasional variation much easier.
A really common example of that in web apps is start-up code; Sometimes it's neccesary to pull some key bits of data out of the database before an application is ready to serve any requests; but since there is no request to serve, where does the database connection come from? How do you get rid of it once you've finished starting up? These questions are usually non-issues with explicitly managed sessions.

How to use a python class with data objects in mysql

I am beginning to learn Python and Django. I want to know how if I have a simple class of "player" with some properties, like: name, points, inventory, how would I make the class also write the values to the database if they are changed. My thinking is that I create Django data models and then call the .save method within my classes. Is this correct?
You are correct that you call the save() method to save models to your db, But you don't have to define the save method within your model classes if you don't want to. It would be extremely helpful to go through the django tutorial which explains all.
https://docs.djangoproject.com/en/dev/intro/tutorial01/
https://docs.djangoproject.com/en/dev/topics/db/models/
Explains django models
django uses its own ORM (object-relational mapping)
This does exacxtly what it sounds like maps your django/python objects (models) to your backend.
It provides a sleek, intuitive, pythonic, very easy to use interface for creating models (tables in your rdbms) adding data and retrieving data.
First you would define your model
class Player(models.Model):
points = models.IntegerField()
name = models.CharField(max_length=255)
django provides commands for chanign this python object into a table.
python manage.py syncdb
you could also use python manage.py sql <appname> to show the actual sql that django is generating to turn this object into a table.
Once you have a storage for this object you can create new ones in the same manner you would create python objects
new_player = Player(points=100, name='me')
new_player.save()
Calling save() actually writes the object to your backend.
You're spot on...
Start at https://docs.djangoproject.com/en/dev/intro/tutorial01/
Make sure you have the python bindings for MySQL and work your way through it... Then if you have specific problems, ask again...

Django model attribute to refer to arbitrary model instance

I'm working on a logging app in Django to record when models in other apps are created, changed, or deleted. All I really need to record is the user who did it, a timestamp, a type of action, and the item that was changed. The user, timestamp, and action type are all easy, but I'm not sure what a good way to store the affected item is beyond storing an id value and a class name so the item can be retrieved later. I imagine that storing the class name will result in a bit of a hacky solution in order to find the actual class, so I'm wondering if there's a better way. Does anyone know of one?
Use generic relations which do just that (use instance id and model class) but are integrated in Django and you also get a shortcut attribute that returns related instance so you don't have to query it yourself. Example usage.
Check out generic relations.

Categories