解释自定义模型字段机制

时间:2019-04-19 12:29:22

标签: django django-models

这不是第一次让自己陷入充满挑战的新事物中。  但这可能是第一个没有外部博客解释该主题的人,除了docs。 所以我希望能找到一些解释创建自定义Django模型字段的基础知识。 这是一个示例,如果您想知道我面临的问题

class OrderField(models.PositiveIntegerField):
def __init__(self, for_fields=None, *args, **kwargs):
    self.for_fields = for_fields
    super(OrderField, self).__init__(*args, **kwargs)

def pre_save(self, model_instance, add):
    if getattr(model_instance, self.attname) is None:
        # no current value
        try:
            qs = self.model.objects.all()
            if self.for_fields:
                # filter by objects with the same field values
                # for the fields in "for_fields"
                query = {field: getattr(model_instance, field)\
                for field in self.for_fields}
                qs = qs.filter(**query)
            # get the order of the last item
            last_item = qs.latest(self.attname)
            value = last_item.order + 1
        except ObjectDoesNotExist:
            value = 0
        setattr(model_instance, self.attname, value)
        return value
    else:
        return super(OrderField,
                     self).pre_save(model_instance, add)

我已经阅读了一些文档,但是可以自由地解释它,因为它适用于任何没有经验的人,所以每个人都会发现它有帮助

2 个答案:

答案 0 :(得分:0)

从外观上看,它继承了models.PositiveIntegerField的功能并修改为一个具有不断增加的数字的字段-因此pre-save会寻找最新值并将其递增1 < / p>

答案 1 :(得分:0)

class OrderField(PositiveIntegerField):
    def __init__(self, for_fields=None, *args, **kwargs):
        self.for_fields = for_fields
        super().__init__(*args, **kwargs)

    def pre_save(self, model_instance, add):
#if the field isn't existed yet in the object 
#(as we could have saved the object before and resaving it for some reason like updating )
        if getattr(model_instance, self.attname) is None: #self.attname is the name of the field in the model

            try:
                qs = self.model.objects.all()
                if self.for_fields:
                    # get objects that has the same fields(with same vlaues) in for_fields 
                    #it's like so 
                    #for_fields = 'course, module, title'
                    # the query will be the value of these fields on the instance which we work on now(and have this field(orderfield ) and will be saved)
                    # course = 1 we assume it's one in this instanse 
                    # module = 3 and so on for the title
                    query = {field: getattr(model_instance, field) for field in self.for_fields}                                                                          
                    qs = qs.filter(**query)                                
                last_item = qs.latest(self.attname)
                value = last_item.order + 1
            except ObjectDoesNotExist:
                value = 0
            setattr(model_instance, self.attname, value)
            return value
        else:
            return super(OrderField, self).pre_save(model_instance, add)