Nasgar
Nasgar

Reputation: 951

Create a property that work similar to Django fields(The property wrongly acts as class attribute)

I created a function that instantiates a property that encapsulates some communication:

def orion_field(name, field=None):
    def getter(self,):
        return self.get(name)

    def setter(self, value):
        self.set(name, value)

    return property(getter, setter)

I want to include it in my Django models in a similar way to Django fields:

class KPI(models.Model):
    orion_id = models.CharField(primary_key=True, unique=True, 
                                max_length=10)
    data = JSONField(blank=True, default={})
    name = orion_field("name")

    def set(self, attribute, value):
        self.data[attribute]= value
        # Ugly code removed that send stuff to server

    def get(self, attribute):
        # Ugly code removed that may(or may not) bring stuff from server
        return self.data[attribute]

The communication code works great but I noticed that these new properties work at class level.

    orion_entity1 = KPI()
    orion_entity2 = KPI()
    orion_entity1.name = "Babar"
    print(orion_entity2.name) 
    >>> Babar

I suppose at some point Django converts class fields into instance fields. I searched their code but I got lost.

Upvotes: 0

Views: 45

Answers (1)

Alasdair
Alasdair

Reputation: 309109

The problem is that you are using a mutable dict {} as the default. Use dict instead, then a separate empty dictionary will be instantiated for each instance.

data = JSONField(blank=True, default=dict)

See the note in the JSONField docs for more info.

Upvotes: 3

Related Questions