django之Model类

Posted on 2018-03-10 23:12  王将军之武库  阅读(439)  评论(0)    收藏  举报

Model是model的基类,该类的metaclass是modelbase,在生成model类对象时是采用modelbase的。django.setup()时,apps会把app建立app_config ,知道了每个app的models。每个model类属性_meta是Option类的对象。

field.name为关系field,比如多对多,多对一等。field.attrname为model定义时类变量名称。

@cached_property
    def fields(self):
        """
        Returns a list of all forward fields on the model and its parents,
        excluding ManyToManyFields.

        is_not_an_m2m_field = lambda f: not (f.is_relation and f.many_to_many)
        is_not_a_generic_relation = lambda f: not (f.is_relation and f.one_to_many)
        is_not_a_generic_foreign_key = lambda f: not (
            f.is_relation and f.many_to_one and not (hasattr(f.remote_field, 'model') and f.remote_field.model)
        )
        return make_immutable_fields_list(
            "fields",
            (f for f in self._get_fields(reverse=False) if
            is_not_an_m2m_field(f) and is_not_a_generic_relation(f)
            and is_not_a_generic_foreign_key
def concrete_fields(self):#获取当前model及其父的实体field
        """
        Returns a list of all concrete fields on the model and its parents.

        Private API intended only to be used by Django itself; get_fields()
        combined with filtering of field properties is the public API for
        obtaining this field list.
        """
        return make_immutable_fields_list(
            "concrete_fields", (f for f in self.fields if f.concrete)
        )

    @cached_property
    def local_concrete_fields(self):#获取当前model的实体field
        """
        Returns a list of all concrete fields on the model.

        Private API intended only to be used by Django itself; get_fields()
        combined with filtering of field properties is the public API for
        obtaining this field list.
        """
        return make_immutable_fields_list(
            "local_concrete_fields", (f for f in self.local_fields if f.concrete)
        )
获取model的所有field
def
_get_fields(self, forward=True, reverse=True, include_parents=True, include_hidden=False, seen_models=None): """ Internal helper function to return fields of the model. * If forward=True, then fields defined on this model are returned.正向,自己的field * If reverse=True, then relations pointing to this model are returned.逆向,关联的对象 * If include_hidden=True, then fields with is_hidden=True are returned.在model隐藏的field * The include_parents argument toggles if fields from parent models包括父的field should be included. It has three values: True, False, and PROXY_PARENTS. When set to PROXY_PARENTS, the call will return all fields defined for the current model or any of its parents in the parent chain to the model's concrete model. """ if include_parents not in (True, False, PROXY_PARENTS): raise TypeError("Invalid argument for include_parents: %s" % (include_parents,)) # This helper function is used to allow recursion in ``get_fields()`` # implementation and to provide a fast way for Django's internals to # access specific subsets of fields. # We must keep track of which models we have already seen. Otherwise we # could include the same field multiple times from different models. topmost_call = False if seen_models is None: seen_models = set() topmost_call = True seen_models.add(self.model) # Creates a cache key composed of all arguments cache_key = (forward, reverse, include_parents, include_hidden, topmost_call) try: # In order to avoid list manipulation. Always return a shallow copy # of the results. return self._get_fields_cache[cache_key] except KeyError: pass fields = [] # Recursively call _get_fields() on each parent, with the same # options provided in this call. if include_parents is not False: for parent in self.parents: # In diamond inheritance it is possible that we see the same # model from two different routes. In that case, avoid adding # fields from the same parent again. if parent in seen_models: continue if (parent._meta.concrete_model != self.concrete_model and include_parents == PROXY_PARENTS): continue for obj in parent._meta._get_fields( forward=forward, reverse=reverse, include_parents=include_parents, include_hidden=include_hidden, seen_models=seen_models): if hasattr(obj, 'parent_link') and obj.parent_link:#如果field有父link,不加入 continue fields.append(obj) if reverse: # Tree is computed once and cached until the app cache is expired. # It is composed of a list of fields pointing to the current model # from other models. all_fields = self._relation_tree for field in all_fields: # If hidden fields should be included or the relation is not # intentionally hidden, add to the fields dict. if include_hidden or not field.remote_field.hidden: fields.append(field.remote_field)#如果远程field不隐藏的话就加入 if forward: fields.extend( field for field in chain(self.local_fields, self.local_many_to_many) ) # Virtual fields are recopied to each child model, and they get a # different model as field.model in each child. Hence we have to # add the virtual fields separately from the topmost call. If we # did this recursively similar to local_fields, we would get field # instances with field.model != self.model. if topmost_call: fields.extend( f for f in self.virtual_fields ) # In order to avoid list manipulation. Always # return a shallow copy of the results fields = make_immutable_fields_list("get_fields()", fields) # Store result into cache for later access self._get_fields_cache[cache_key] = fields return fields

 

博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3