Django с социальным аутентификатором: Прямое назначение на прямую сторону множества "многие ко многим" запрещено
При попытке аутентификации (создания) пользователя в Django я получаю следующую ошибку:
Direct assignment to the forward side of a many-to-many set is prohibited. Use gave_mangoes.set() instead.
Код:
models.py
...
from waters.models import Water
class User(AbstractUser):
id = models.AutoField(primary_key=True)
posts = models.ManyToManyField(Water) # MANY TO MANY FIELD CAUSING ERROR
...
oauth.py
from social_core.backends.oauth import BaseOAuth2
class <name>Oauth2(BaseOAuth2):
name = "<name>"
AUTHORIZATION_URL = "<url>"
ACCESS_TOKEN_URL = "<url>"
ACCESS_TOKEN_METHOD = "POST"
EXTRA_DATA = [("refresh_token", "refresh_token", True), ("expires_in", "expires")]
def get_scope(self):
return ["read"]
def get_user_details(self, response):
profile = self.get_json("<url>", params={"access_token": response["access_token"]})
return {
"id": profile["id"],
"username": profile["username"],
...
}
def get_user_id(self, details, response):
return details["id"]
Я прочитал этот ответ , в котором рассматривается та же ошибка:
Вам необходимо сохранить корзину, прежде чем вы сможете добавить элементы в поле "многие ко многим".
Однако, поскольку я использую Python Social Auth, он создает пользователя в бэкенде, поэтому я не могу сохранить его и изменить поле позже. Как я могу исправить эту ошибку?
Я смог обойти ошибку, расширив конвейер социальной аутентификации (документация). Во-первых, я сделал метод для создания пользователя соответствующим образом, чтобы обойти ошибку (как указано в ответе, связанном с вопросом):
authentication/pipeline.py
from authentication.models import User
def create_user(backend, user, response, *args, **kwargs):
u = User()
for k, v in kwargs["details"].items():
setattr(u, k, v)
u.save()
# Optionally update many to many field here
и поместил это перед методом create_user
социального аута:
settings.py
...
SOCIAL_AUTH_PIPELINE = (
"social_core.pipeline.social_auth.social_details",
"social_core.pipeline.social_auth.social_uid",
"social_core.pipeline.social_auth.auth_allowed",
"social_core.pipeline.social_auth.social_user",
"social_core.pipeline.social_auth.associate_by_email",
"authentication.pipeline.create_user", #ADDED
"social_core.pipeline.user.create_user",
"social_core.pipeline.social_auth.associate_user",
"social_core.pipeline.social_auth.load_extra_data",
)
...