def find_serializer_fields(self, serializer_name): nodes = self.serializer_registry.nodes if serializer_name in self.memo_dict: return self.memo_dict[serializer_name] class_node = nodes[serializer_name] fields = Fields() init_node = None # Look at own class variables first, this trumps everything else for node in class_node.body: if self.is_class_var(node): # explicit class var trumps Meta fields.add(Resolver.drf_field_assignment(node), overwrite=True) elif self.is_meta(node): fields.extend(Resolver.drf_meta_fields(node)) elif self.is_init_method(node): init_node = node # add fields from bases, in left to right order. The bases of the base # trumps the neighbour of the base if there's overlap. for base in class_node.bases: base = Resolver.resolve(base) if base == 'object': continue if base not in nodes: # TODO: ??? continue base_class_vars = self.find_serializer_fields(base) fields.extend(base_class_vars) # Check for dynamic fields that were inherited from direct ancestors. # TODO: Find a better way to support inheritance parent_in_dynamic_fields = any( getattr(parent_class, 'attr', None) in self.dynamic_fields or getattr(parent_class, 'id', None) in self.dynamic_fields for parent_class in class_node.bases) # dynamic fields trump or augment existing fields if serializer_name in self.dynamic_fields or parent_in_dynamic_fields: if init_node: dynamic_fields = Resolver.init_method(init_node) for field_name, field in dynamic_fields.iteritems(): if field_name not in fields: fields.add(field) continue previous_field = fields[field_name] augmented_field = self.augment_field(previous_field, field) fields.add(augmented_field, overwrite=True) self.memo_dict[serializer_name] = fields return fields
def find_serializer_fields(self, serializer_name): nodes = self.serializer_registry.nodes if serializer_name in self.memo_dict: return self.memo_dict[serializer_name] class_node = nodes[serializer_name] fields = Fields() init_node = None # Look at own class variables first, this trumps everything else for node in class_node.body: if self.is_class_var(node): # explicit class var trumps Meta fields.add(Resolver.class_var_drf_field(node), overwrite=True) elif self.is_meta(node): fields.extend(Resolver.drf_meta_fields(node)) elif self.is_init_method(node): init_node = node # add fields from bases, in left to right order. The bases of the base # trumps the neighbour of the base if there's overlap. for base in class_node.bases: base = Resolver.resolve(base) if base == 'object': continue if base not in nodes: # TODO: ??? continue base_class_vars = self.find_serializer_fields(base) fields.extend(base_class_vars) # dynamic fields trump or augment existing fields if serializer_name in self.dynamic_fields: if not init_node: msg = ('Did not find __init__ in {} but view specifies dynamic' ' fields.').format(serializer_name) raise Exception(msg) dynamic_fields = Resolver.init_method(node) for field in dynamic_fields: if field not in fields: fields.add(field) continue previous_field = fields[field['field_name']] augmented_field = self.augment_field(previous_field, field) fields.add(augmented_field, overwrite=True) self.memo_dict[serializer_name] = fields return fields