Ответ 1
Вам не нужно вызывать save после many2many.add()
Вы также можете сократить код до двух строк:
flst = FollowerList.objects.create(follower=user)
flst.followed.add(user)
У меня есть метод, который работает, но он кажется очень неуклюжим, и я думаю, что есть лучший способ сделать это.
У меня есть модель, которая связывает пользователя на моем сайте (клон Twitter в учебных целях) со списком других пользователей.
Прямо сейчас, когда я создаю нового пользователя, я хочу инициализировать этот список с пользователем в качестве члена списка.
Моя модель:
class FollowerList(models.Model)
follower = models.ForeignKey(User,related_name="follower")
followed = models.ManyToManyField(User,related_name="followed")
На мой взгляд, код, который я сейчас использую, -
user = User.objects.get(username=uname)
flst = FollowerList()
flst.follower = user
flst.save()
flst.followed.add(user)
flst.save()
Мне кажется, что должен быть метод для создания этого без двойного вызова save()
, но я не могу найти его в документации или где-либо еще.
Вам не нужно вызывать save после many2many.add()
Вы также можете сократить код до двух строк:
flst = FollowerList.objects.create(follower=user)
flst.followed.add(user)
Ответ Yuji верен. Вы не можете добавить объект в поле M2M, пока он не будет сохранен. Я хотел бы упомянуть о более коротком способе создания экземпляров.
user = User.objects.get(username=uname)
flst = FollowerList(follower=user) #use key word args to assign fields
flst.save()
flst.followed.add(user)
# don't need to save after adding an object to many to many field.
Я нахожу этот синтаксис немного приятнее, чем создание пустого экземпляра и назначение полей. Хотя метод objects.create() (упомянутый Юки) еще приятнее.
Поздний ответ на этот вопрос: вы можете также переопределить конструктор (__init__
) следующим образом:
class FollowerList(models.Model):
follower = models.ForeignKey(User,related_name="follower")
followed = models.ManyToManyField(User,related_name="followed"
def __init__(*args, followed=[], **kwargs):
super(FollowerList, self).__init__(*args, **kwargs)
self.save()
for user in followed:
self.followed.add(user)
т.е. здесь я явно обработал аргумент ключевого слова followed
в функции __init__
, передав все остальные args
и kwargs
в конструктор по умолчанию.
Вызов save
гарантирует, что объект был зарегистрирован и поэтому может использоваться в отношении m2m.
Затем вы можете создать FollowerList
с одной строкой, например
flst = FollowerList(follower=user, followed=[user,])
В качестве альтернативы, как указал Йоханнес, сохранение модели в __init__
не ожидается. Предпочтительным подходом было бы создать метод Manager
- см. Здесь для деталей: https://docs.djangoproject.com/en/1.9/topics/db/managers/
а затем создать FollowerList
:
fl = FollowerList.objects.create(*args, followed, **kwargs)