Лучший способ создать объект со многими во многих полях, используя Django RF API

Вместо использования null для начального значения вы можете использовать пустой массив []. Таким образом, ваша переменная состояния articles никогда не находится в согласованном состоянии. Кроме того, вы можете избежать ручного связывания в своем обратном вызове и использовать функции стрелок, а затем сохранить текущую область. Таким образом, вы будете иметь правильное закрытие для использования this.state.

parseString(response, (err, result) => {
  this.setState({
    articles: JSON.stringify(result.rss.channel[0].item)
  })
});
0
задан James 18 January 2019 в 18:36
поделиться

1 ответ

Прежде всего, независимо от вашего вопроса, поле 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 вместо этого.

0
ответ дан schillingt 18 January 2019 в 18:36
поделиться
Другие вопросы по тегам:

Похожие вопросы: