def _serialize_value(self, attr_name, ignore_serializers=None): obj_serializer = self._get_related_serializer(attr_name) # To prevent infinite recursion, allow serializers to be ignored if ignore_serializers and obj_serializer in ignore_serializers: return None val = get_property(self.instance, attr_name) # If we have one or more related models if obj_serializer and hasattr(val, 'all'): return [obj_serializer(instance=o).serialize(ignore_serializers=[self.__class__]) for o in val.all()] elif obj_serializer: return obj_serializer(instance=val).serialize(ignore_serializers=[self.__class__]) elif hasattr(self.opts.model, attr_name): # Check if the field is a relation of any kind field_type = getattr(self.opts.model, attr_name) # Reverse FK if isinstance(field_type, ReverseSingleRelatedObjectDescriptor): rel = get_property(self.instance, attr_name) if rel: val = rel.pk # FK elif isinstance(field_type, ForeignRelatedObjectsDescriptor): val = list(get_property(self.instance, attr_name).all().values_list('pk', flat=True)) elif isinstance(field_type, ReverseManyRelatedObjectsDescriptor): val = list(get_property(self.instance, attr_name).all().values_list('pk', flat=True)) elif isinstance(field_type, ManyRelatedObjectsDescriptor): val = list(get_property(self.instance, attr_name).all().values_list('pk', flat=True)) # Serialize the field return serialize_field(val)
def get_changed_fields(self): changed_fields = [] for k, v in self._pre_save_state.items(): val = get_property(self, k) if val != v: changed_fields.append(k) return changed_fields
def _serialize_value(self, attr_name, ignore_serializers=None): obj_serializer = self._get_related_serializer(attr_name) # To prevent infinite recursion, allow serializers to be ignored if ignore_serializers and obj_serializer in ignore_serializers: return None val = get_property(self.instance, attr_name) # If we have one or more related models if obj_serializer and hasattr(val, 'all'): return [ obj_serializer(instance=o).serialize( ignore_serializers=[self.__class__]) for o in val.all() ] elif obj_serializer: return obj_serializer(instance=val).serialize( ignore_serializers=[self.__class__]) elif hasattr(self.opts.model, attr_name): # Check if the field is a relation of any kind field_type = getattr(self.opts.model, attr_name) # Reverse FK if isinstance(field_type, ReverseSingleRelatedObjectDescriptor): rel = get_property(self.instance, attr_name) if rel: val = rel.pk # FK elif isinstance(field_type, ForeignRelatedObjectsDescriptor): val = list( get_property(self.instance, attr_name).all().values_list('pk', flat=True)) elif isinstance(field_type, ReverseManyRelatedObjectsDescriptor): val = list( get_property(self.instance, attr_name).all().values_list('pk', flat=True)) elif isinstance(field_type, ManyRelatedObjectsDescriptor): val = list( get_property(self.instance, attr_name).all().values_list('pk', flat=True)) # Serialize the field return serialize_field(val)
def _set_pre_save_state(self): """ Set the state of the model before any changes are done, so it's possible to determine what fields have changed. """ relevant_fields = self._get_relevant_fields() for field in relevant_fields: val = get_property(self, field) if hasattr(self._serializer, field): continue if val is None: self._pre_save_state[field] = None continue self._pre_save_state[field] = val
def test_get_property(self): text_model = TextModel.objects.create(text='test') val = model_tools.get_property(text_model, 'text') self.assertEqual(val, text_model.text)
def test_get_invalid_related_property(self): parent = ParentModel.objects.create(name='a parent') ChildModel.objects.create(number=12, parent=parent) self.assertIsNone( model_tools.get_property(parent, 'parent__invalid_property__p'))
def test_get_related_property(self): parent = ParentModel.objects.create(name='a parent') child = ChildModel.objects.create(number=12, parent=parent) val = model_tools.get_property(child, 'parent__name') self.assertEqual(val, parent.name)
def test_get_invalid_property(self): text_model = TextModel.objects.create(text='test') val = model_tools.get_property(text_model, 'invalidprop') self.assertIsNone(val)