如何为具有多对多字段的 Django 模型创建对象?
我的模型:
class Sample(models.Model):
users = models.ManyToManyField(User)
我想在该模型中保存 user1
和 user2
:
user1 = User.objects.get(pk=1)
user2 = User.objects.get(pk=2)
sample_object = Sample(users=user1, users=user2)
sample_object.save()
我知道这是错误的,但我确信您明白我想要做的事情。你会怎么做?
My model:
class Sample(models.Model):
users = models.ManyToManyField(User)
I want to save both user1
and user2
in that model:
user1 = User.objects.get(pk=1)
user2 = User.objects.get(pk=2)
sample_object = Sample(users=user1, users=user2)
sample_object.save()
I know that's wrong, but I'm sure you get what I want to do. How would you do it ?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
您无法从未保存的对象创建 M2M 关系。如果您有
pk
,请尝试以下操作:更新:阅读saverio 的回答,我决定调查这个问题更深入一点。这是我的发现。
这是我最初的建议。它有效,但不是最佳的。 (注意:我使用
Bar
和Foo
而不是User
和Sample
,但是您明白了)。它总共生成了 7 个查询:
我确信我们可以做得更好。您可以将多个对象传递给
add()
方法:正如我们所见,传递多个对象可以节省一个
SELECT
:我不知道您还可以分配一个列表对象数:
不幸的是,这会创建一个额外的
SELECT
:让我们尝试分配一个
pk
列表,正如 saverio 建议的那样:因为我们不获取两个
酒吧,我们省了两个
SELECT
语句,总共 5 个:获胜者是:
将
pk
传递给add()
给我们总共 4 个查询:You cannot create m2m relations from unsaved objects. If you have the
pk
s, try this:Update: After reading the saverio's answer, I decided to investigate the issue a bit more in depth. Here are my findings.
This was my original suggestion. It works, but isn't optimal. (Note: I'm using
Bar
s and aFoo
instead ofUser
s and aSample
, but you get the idea).It generates a whopping total of 7 queries:
I'm sure we can do better. You can pass multiple objects to the
add()
method:As we can see, passing multiple objects saves one
SELECT
:I wasn't aware that you can also assign a list of objects:
Unfortunately, that creates one additional
SELECT
:Let's try to assign a list of
pk
s, as saverio suggested:As we don't fetch the two
Bar
s, we save twoSELECT
statements, resulting in a total of 5:And the winner is:
Passing
pk
s toadd()
gives us a total of 4 queries:对于未来的访问者,您可以使用 bulk_create。请注意,只有当您不需要使用 save() 方法或信号对数据进行任何预处理或后处理时,这才可用。您插入的内容正是数据库中的内容
您可以执行此操作,而无需在字段上指定“通过”模型。为了完整起见,下面的示例创建了一个空白的 Users 模型来模仿原始发帖者的要求。
现在,在 shell 或其他代码中,创建 2 个用户,创建一个示例对象,然后将用户批量添加到该示例对象。
For future visitors, you can create an object and all of its m2m objects in 2 queries using bulk_create. Note that this is only usable if you don't require any pre or post-processing on the data with save() methods or signals. What you insert is exactly what will be in the DB
You can do this without specifying a "through" model on the field. For completeness, the example below creates a blank Users model to mimic what the original poster was asking.
Now, in a shell or other code, create 2 users, create a sample object, and bulk add the users to that sample object.
Django 1.9
一个简单的例子:
Django 1.9
A quick example:
相关对象管理器是与模型中的字段不同的“属性”。实现您正在寻找的内容的最简单方法是
与分配用户列表相同,无需额外的查询和模型构建。
如果查询的数量让您烦恼(而不是简单),那么最佳解决方案需要三个查询:
这会起作用,因为我们已经知道“用户”列表是空的,因此我们可以无意识地创建。
RelatedObjectManagers are different "attributes" than fields in a Model. The simplest way to achieve what you are looking for is
That's the same as assigning a User list, without the additional queries and the model building.
If the number of queries is what bothers you (instead of simplicity), then the optimal solution requires three queries:
This will work because we already know that the 'users' list is empty, so we can create mindlessly.
您可以通过这种方式替换相关对象集(Django 1.9 中的新功能):
You could replace the set of related objects in this way (new in Django 1.9):
如果有人希望在自引用 ManyToMany 字段上做 David Marbles 的回答。直通模型的 id 称为:
“to_'model_name_id”和
“来自_'型号_名称'_id”。
如果这不起作用,你可以检查 django 连接。
If someone is looking to do David Marbles answer on a self referring ManyToMany field. The ids of the through model are called:
"to_'model_name_id" and
"from_'model_name'_id".
If that doesn't work you can check the django connection.