Вместо использования null
для начального значения вы можете использовать пустой массив []
. Таким образом, ваша переменная состояния articles
никогда не находится в согласованном состоянии. Кроме того, вы можете избежать ручного связывания в своем обратном вызове и использовать функции стрелок, а затем сохранить текущую область. Таким образом, вы будете иметь правильное закрытие для использования this.state
.
parseString(response, (err, result) => {
this.setState({
articles: JSON.stringify(result.rss.channel[0].item)
})
});
Прежде всего, независимо от вашего вопроса, поле m2m ваших ролей должно быть обновлено следующим образом:
roles = models.ManyToManyField(Role, related_name='users')
related_name - это то, как вы ссылаетесь на текущую модель (User) из модели, переданной в ManyToManyField (Role). С моим предложением вы бы написали Role.objects.first().users
, а не Role.objects.first().roles
.
Во-вторых, если это возможно, я бы рекомендовал передать роли для создания / обновления пользователя в виде списка первичных ключей. Даже если это означает создание второго свойства сериализатора, которое предназначено только для записи. Например:
class UserSerializer(serializers.ModelSerializer):
roles = RoleSerializer(many=True, read_only=True)
role_ids = serializers.PrimaryKeyRelatedField(
queryset=Role.objects.all(),
many=True, write_only=True)
class Meta:
model = User
fields = ('url', 'username', 'password', 'email', 'roles', 'role_ids')
extra_kwargs = {'password': {'write_only': True}}
def create(self, validated_data):
password = validated_data.pop('password')
# Allow the serializer to handle the creation. Don't do it yourself.
instance = super().create(**validated_data)
if password is not None:
instance.set_password(password)
instance.save()
return instance
Когда ваш API выплевывает пользователей, он должен выглядеть следующим образом:
{
'url': '...',
'username': '...',
'email': '...',
'roles': [{'id': 1, 'name': 'client'}],
}
Когда вы POST к нему, вы должны использовать:
{
'url': '...',
'username': '...',
'email': '...',
'password': '...',
'role_ids': [1, 2],
}
Кроме того, причина, по которой вы получили ошибку User does not have an attribute named roles.
, заключается в том, что вы не можете передать roles
в конструктор User
. User.roles
необходимо установить после того, как у вас есть экземпляр. Вы должны были сделать:
user = User(**validated_data)
user.roles.set(roles) # If you need to re-write the entire list.
Несмотря на то, что у меня в голове, я не уверен, что это сработает. Возможно, вам придется сохранить его заранее. Вот почему я предлагаю вам использовать super().create
вместо этого.