How are ModelFields assigned in Django Models?
<p>When we define a model in django we write something like..</p>

<pre><code>class Student(models.Model):
    name = models.CharField(max_length=64)
    age = models.IntegerField()
    ...
</code></pre>

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

<pre><code>my_name = "John Doe"
my_age = 18
s = Student.objects.create(name=my_name, age=my_age)
</code></pre>

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

<p>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 ?</p>

<p>Found a similar <a href="http://stackoverflow.com/questions/12006267/how-do-django-models-work">question</a> but didn't find it helpful enough.</p>

<h1>How things work</h1>

<p>First thing I we need to understand that each field on your models has own validation, <a href="https://github.com/django/django/blob/master/django/db/models/fields/__init__.py#L1040" rel="nofollow">this one</a> refer to the CharField(<code>_check_max_length_attribute</code>) and it also calling the <code>super</code> on method <code>check</code> from the <code>Field</code> class to validate some basic common things.</p>

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

<ol>
<li>Create a python object</li>
<li>Call <code>save()</code></li>
<li>Using a lot of <code>getattr</code>s the save does tons of validation</li>
<li>Commit to the DB, if anything wrong goes from the DB, raise it to the user</li>
</ol>

<p>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.</p>

<h1>Simple Example</h1>

<pre><code>class BasicCharField:
    def __init__(self, max_len):
        self.max_len = max_len

    def validate(self, value):
        if value &gt; 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)
</code></pre>

<p>And like we was expecting:</p>

<p><code>&gt;&gt;&gt; ValueError: the value must be lower than 4</code></p>

<p>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 <code>obj.score = ...</code>)</p>

python django oop django-models