1

When we define a model in django we write something like..

class Student(models.Model):
    name = models.CharField(max_length=64)
    age = models.IntegerField()
    ...

where, name = models.CharField() implies that name would be an object of models.CharField. When we have to make an object of student we simple do..

my_name = "John Doe"
my_age = 18
s = Student.objects.create(name=my_name, age=my_age)

where my_name and my_age are string and integer data types respectively, and not an object of models.CharField/models.IntegerField. Although while assigning the values the respective validations are performed (like checking on the max_length for CharField)

I'm trying to build similar models for an abstraction of Neo4j over Django but not able to get this workflow. How can I implement this ?

Found a similar question but didn't find it helpful enough.

Community
  • 1
  • 1
esquarer
  • 373
  • 1
  • 4
  • 12

1 Answers1

1

How things work

First thing I we need to understand that each field on your models has own validation, this one refer to the CharField(_check_max_length_attribute) and it also calling the super on method check from the Field class to validate some basic common things.

That in mind, we now move to the create method which is much more complicated and total different thing, the basics operations for specific object:

  1. Create a python object
  2. Call save()
  3. Using a lot of getattrs the save does tons of validation
  4. Commit to the DB, if anything wrong goes from the DB, raise it to the user

A third thing you need to understand that when you query an object it first get the data from the db, and then(after long process) it set the data to the object.

Simple Example

class BasicCharField:
    def __init__(self, max_len):
        self.max_len = max_len

    def validate(self, value):
        if value > self.max_len:
            raise ValueError('the value must be lower than {}'.format(self.max_len))


class BasicModel:
    score = BasicCharField(max_len=4)

    @staticmethod
    def create(**kwargs):
        obj = BasicModel()
        obj.score = kwargs['score']
        obj.save()
        return obj

    def save(self):
        # Lots of validations here
        BasicModel.score.validate(self.score)
        # DB commit here

BasicModel.create(score=5)

And like we was expecting:

>>> ValueError: the value must be lower than 4

Obviously I had to simplify things to make it into few lines of code, you can improve this by a lot (like iterate over the attribute and not hardcode it like obj.score = ...)

Or Duan
  • 13,142
  • 6
  • 60
  • 65