Facundo Casco
Facundo Casco

Reputation: 10605

Django: making relationships in memory without saving to DB

I have some models with relationships like this:

class Item(model.Model):
    name = models.CharField()

class Group(models.Model):
    item = models.ManyToManyField(Item)

class Serie(models.Model):
    name = models.CharField()
    chart = models.ForeignKey(Chart)
    group = models.ForeignKey(Group)

class Chart(models.Model):
    name = models.CharField()

I need to create a Chart object on the fly, without saving to the DB. But I can't do it because Django tries to use the objects primary keys when assigning the relationships.

I just want Group.add(Item()) to work without having to save the objects to the DB.

Is there any simple way around this?

Upvotes: 10

Views: 2221

Answers (2)

Alvaro
Alvaro

Reputation: 12037

Reviving here for the sake of future readers:

I've gotten around this use case by defining a private attribute that represents the relationship inside the classes and a property to inspect wether the object can be retrieved from the DB or resides in memory.

Here is a simple example:

class Parent(models.Model):
    _children = []
    name = models.CharField(max_length=100)

    @property
    def children(self):
        if _children:
            return self._children
        else:
            return self.children_set.all()

    def set_virtual_children(self, value):  # could use a setter for children
        self._children = value  # Expose _children to modification

    def some_on_the_fly_operation(self):
        print(','.join([c.name for c in self.children]))   


 class Children(models.Model):
     parent = models.ForeignKey(Parent)
     name = models.CharField(max_length=100)

This way, I can set the "virtual children" and use all the defined methods "on the fly"

Upvotes: 6

Lycha
Lycha

Reputation: 10187

EDIT: It seems that approach described here isn't enough for django to allow adding to the ManyToMany relationship.

Have you tried to add primary_key=True and unique=True to the name attribute of the Item model. Then doing Group.add(Item("item_name_here")) should work if you have the possibility to create the name on the fly.

I didn't test it, but I think your way failed because add() wants to use the primary-key which by default is the autoincrementing id that is assigned when it is saved to the database.

Upvotes: 0

Related Questions