2010-12-23 174 views
11

我有一个可行的方法,但它看起来很笨拙,我认为有更好的方法来做到这一点。在Django中使用manytomany字段实例化模型实例

我有一个模型将用户在我的网站(一个用于学习目的的推特克隆)与其他用户列表相关联。

现在,当我创建一个新用户时,我想用该用户作为列表的成员初始化该列表。

我的模式是:

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()两次,但我似乎无法在文档或其他任何地方找到它。

回答

12

你并不需要调用many2many.add()

您还可以缩短代码为2行后保存:

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

的问题,当我做到这一点的是,我得到一个错误说的FollowerList对象必须有一个主键,然后它可以将ManyToManyField实例添加到它。我能看到的唯一方法是先实例化并保存,然后添加其他字段。 – 2010-12-23 06:13:39

+0

那么,FollowerList.objects.create(follower = user)会给它一个主键。它保存。 – 2010-12-23 06:15:09

4

虞姬的答案是正确的。在保存之前,您无法将对象添加到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()方法(由Yuki提到)仍然更好。

2

逾期回答这个:你也可以重写构造(__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) 

即在这里,我明确地处理在__init__功能followed关键字参数,而通过所有其他argskwargs默认的构造函数。 致电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) 
相关问题