Подтвердить что ты не робот

Выполнить экземпляр модели с помощью многогодового поля в Django

У меня есть метод, который работает, но он кажется очень неуклюжим, и я думаю, что есть лучший способ сделать это.

У меня есть модель, которая связывает пользователя на моем сайте (клон 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(), но я не могу найти его в документации или где-либо еще.

4b9b3361

Ответ 1

Вам не нужно вызывать save после many2many.add()

Вы также можете сократить код до двух строк:

flst = FollowerList.objects.create(follower=user)
flst.followed.add(user)

Ответ 2

Ответ 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() (упомянутый Юки) еще приятнее.

Ответ 3

Поздний ответ на этот вопрос: вы можете также переопределить конструктор (__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)