def update(self, instance, validated_data): causes = validated_data.pop('causes', []) address_data = validated_data.pop('address', None) # Iterate and save fields as drf default info = model_meta.get_field_info(instance) for attr, value in validated_data.items(): if attr in info.relations and info.relations[ attr].to_many: # pragma: no cover set_many(instance, attr, value) else: setattr(instance, attr, value) # Save related resources if address_data: address_sr = address_serializers[0](data=address_data) address = address_sr.create(address_data) instance.address = address # Associate causes if causes: instance.causes.clear() for cause in causes: c = Cause.objects.get(pk=cause['id']) instance.causes.add(c) instance.save() return instance
def setUp(self): self.user = User.objects.create(username='******', email='*****@*****.**') self.groups = [ Group.objects.create(name='a'), Group.objects.create(name='b') ] set_many(self.user, 'groups', self.groups) self.user.save()
def create(self, validated_data): """ We have a bit of extra checking around this in order to provide descriptive messages when something goes wrong, but this method is essentially just: return ExampleModel.objects.create(**validated_data) If there are many to many fields present on the instance then they cannot be set until the model is instantiated, in which case the implementation is like so: example_relationship = validated_data.pop('example_relationship') instance = ExampleModel.objects.create(**validated_data) instance.example_relationship = example_relationship return instance The default implementation also does not handle nested relationships. If you want to support writable nested relationships you'll need to write an explicit `.create()` method. """ raise_errors_on_nested_writes('create', self, validated_data) ModelClass = self.Meta.model # Remove many-to-many relationships from validated_data. # They are not valid arguments to the default `.create()` method, # as they require that the instance has already been saved. info = model_meta.get_field_info(ModelClass) many_to_many = {} for field_name, relation_info in info.relations.items(): if relation_info.to_many and (field_name in validated_data): many_to_many[field_name] = validated_data.pop(field_name) try: instance = ModelClass.objects.create(**validated_data) except TypeError: tb = traceback.format_exc() msg = ('Got a `TypeError` when calling `%s.objects.create()`. ' 'This may be because you have a writable field on the ' 'serializer class that is not a valid argument to ' '`%s.objects.create()`. You may need to make the field ' 'read-only, or override the %s.create() method to handle ' 'this correctly.\nOriginal exception was:\n %s' % (ModelClass.__name__, ModelClass.__name__, self.__class__.__name__, tb)) raise TypeError(msg) # Save many-to-many relationships after the instance is created. if many_to_many: for field_name, value in many_to_many.items(): set_many(instance, field_name, value) return instance
def setUp(self): self.foreign_key_target = ForeignKeyTargetModel.objects.create( name='foreign_key') self.one_to_one_target = OneToOneTargetModel.objects.create( name='one_to_one') self.many_to_many_targets = [ ManyToManyTargetModel.objects.create(name='many_to_many (%d)' % idx) for idx in range(3) ] self.instance = RelationalModel.objects.create( foreign_key=self.foreign_key_target, one_to_one=self.one_to_one_target, ) set_many(self.instance, 'many_to_many', self.many_to_many_targets) self.instance.save()
def update(self, instance, validated_data): raise_errors_on_nested_writes('update', self, validated_data) info = model_meta.get_field_info(instance) # Simply set each attribute on the instance, and then save it. # Note that unlike `.create()` we don't need to treat many-to-many # relationships as being a special case. During updates we already # have an instance pk for the relationships to be associated with. for attr, value in validated_data.items(): if attr in info.relations and info.relations[attr].to_many: set_many(instance, attr, value) else: setattr(instance, attr, value) instance.save() return instance
def update(self, instance, validated_data): print("========== CALLED UPDATE! ===========") print(str(validated_data)) print(str(instance.id)) fields = ModelSerializer.get_fields(self) info = model_meta.get_field_info(instance) for attr, value in validated_data.items(): if attr in info.relations and info.relations[attr].to_many: print("setting multiple " + str(instance) + " " + str(attr) + " " + str(value)) set_many(instance, attr, value) else: print("setting single " + str(instance) + " " + str(attr) + " " + str(value)) setattr(instance, attr, value) instance.save() print(fields) return ModelSerializer.update(self, instance, validated_data)
def setUp(self): User.objects.create_user('disallowed', '*****@*****.**', 'password') user = User.objects.create_user('permitted', '*****@*****.**', 'password') set_many(user, 'user_permissions', [ Permission.objects.get(codename='add_basicmodel'), Permission.objects.get(codename='change_basicmodel'), Permission.objects.get(codename='delete_basicmodel') ]) user = User.objects.create_user('updateonly', '*****@*****.**', 'password') set_many(user, 'user_permissions', [ Permission.objects.get(codename='change_basicmodel'), ]) self.permitted_credentials = basic_auth_header('permitted', 'password') self.disallowed_credentials = basic_auth_header('disallowed', 'password') self.updateonly_credentials = basic_auth_header('updateonly', 'password') BasicModel(text='foo').save()
def setUp(self): self.foreign_key_target = ForeignKeyTargetModel.objects.create( name='foreign_key' ) self.one_to_one_target = OneToOneTargetModel.objects.create( name='one_to_one' ) self.many_to_many_targets = [ ManyToManyTargetModel.objects.create( name='many_to_many (%d)' % idx ) for idx in range(3) ] self.instance = RelationalModel.objects.create( foreign_key=self.foreign_key_target, one_to_one=self.one_to_one_target, ) set_many(self.instance, 'many_to_many', self.many_to_many_targets) self.instance.save()
def create(self, validated_data): raise_errors_on_nested_writes('create', self, validated_data) ModelClass = self.Meta.model # Remove many-to-many relationships from validated_data. # They are not valid arguments to the default `.create()` method, # as they require that the instance has already been saved. info = model_meta.get_field_info(ModelClass) many_to_many = {} for field_name, relation_info in info.relations.items(): if relation_info.to_many and (field_name in validated_data): many_to_many[field_name] = validated_data.pop(field_name) try: if 'comment' in validated_data: if validated_data['comment'].comment_top: instance = ModelClass.objects.create( **validated_data, comment_top=validated_data['comment'].comment_top) else: instance = ModelClass.objects.create( **validated_data, comment_top=validated_data['comment']) else: instance = ModelClass.objects.create(**validated_data) except TypeError: tb = traceback.format_exc() msg = ('Got a `TypeError` when calling `%s.objects.create()`. ' 'This may be because you have a writable field on the ' 'serializer class that is not a valid argument to ' '`%s.objects.create()`. You may need to make the field ' 'read-only, or override the %s.create() method to handle ' 'this correctly.\nOriginal exception was:\n %s' % (ModelClass.__name__, ModelClass.__name__, self.__class__.__name__, tb)) raise TypeError(msg) # Save many-to-many relationships after the instance is created. if many_to_many: for field_name, value in many_to_many.items(): set_many(instance, field_name, value) return instance
def setUp(self): self.user = User.objects.create(username='******', email='*****@*****.**') self.groups = [Group.objects.create(name='a'), Group.objects.create(name='b')] set_many(self.user, 'groups', self.groups) self.user.save()