当我们在Django中定义模型时,我们会写类似..

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


其中,name = models.CharField()表示name将是models.CharField的对象。当我们不得不以学生为对象时,我们就简单地做..

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


其中my_namemy_age分别是stringinteger数据类型,而不是models.CharField / models.IntegerField的对象。尽管在分配值时会执行相应的验证(例如在max_length中检查CharField

我正在尝试为Django上Neo4j的抽象构建类似的模型,但无法获得此工作流。我该如何实施呢?

找到了类似的question,但发现它没有足够的帮助。

最佳答案

如何工作

首先,我们需要了解模型上的每个字段都有自己的验证,this one引用CharField(_check_max_length_attribute),它还从super类调用方法check上的Field进行验证一些基本的共同点。

考虑到这一点,我们现在转到create方法,该方法更加复杂并且完全不同,这是特定对象的基本操作:


创建一个python对象
致电save()
使用大量的getattr可以节省大量的验证时间
提交给数据库,如果数据库出了什么问题,则将其提升给用户


您需要了解的第三件事是,查询对象时,它首先从db获取数据,然后(经过长时间处理)将数据设置为对象。

简单的例子

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)


就像我们期望的那样:

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

显然,我不得不简化一些事情以使其成为几行代码,您可以对其进行很多改进(例如遍历属性而不是像obj.score = ...那样对其进行硬编码)

10-08 20:27