如何在 Django 中更新 m2m 字段

use*_*125 6 sql django many-to-many

我有:

class MyUser(Model):
    today_ref_viewed_ips = ManyToManyField(
        UniqAddress, 
        related_name='today_viewed_users', 
        verbose_name="Adresses visited referal link today")
    ...
Run Code Online (Sandbox Code Playgroud)

在一些老生常谈的日常要求中,我这样做:

for u in MyUser.objects.all():
    u.today_ref_viewed_ips.clear()
Run Code Online (Sandbox Code Playgroud)

可以通过更新在数据库服务器上完成吗?

MyUser.objects.all().update(...)
Run Code Online (Sandbox Code Playgroud)

好的,我无法更新,谢谢。但我唯一需要的是 TRUNCATE m2m 内部表,是否可以从 django 执行?如何在没有 mysql 控制台“SHOW TABLES”的情况下知道它的名称?

sga*_*uri 8

如果您只想更新 m2m 字段并且不想删除 m2m 对象,您可以使用以下命令:

#if you have **list of pk** for new m2m objects

today_ref_pk = [1,2,3]
u = MyUser.objects.get(pk=1)
u.today_ref_viewed_ips.clear()
u.today_ref_viewed_ips.add(*today_ref_pk)
Run Code Online (Sandbox Code Playgroud)

对于 Django >=1.11文档

# if you have the **list of objects** for new m2m and you dont have the 
# issue of race condition, you can do the following:

today_ref_objs = [obj1, obj2, obj3]
u = MyUser.objects.get(pk=1)
u.today_ref_viewed_ips.set(today_ref_objs, clear=True)
Run Code Online (Sandbox Code Playgroud)


Rah*_*pta 6

查询1:

不,您不能使用.update()方法来更新ManyToManyField.

Django的.update()方法不支持ManyToManyField。

根据有关一次更新多个对象部分的文档:

使用此方法只能设置非关系字段和ForeignKey字段。要更新非关系字段,请提供新值作为常量。要更新ForeignKey字段,请将新值设置为您想要指向的新模型实例。

查询2:

如果要删除m2m表的所有对象,可以使用.delete()queryset方法。

MyModel.objects.all().delete() # deletes all the objects
Run Code Online (Sandbox Code Playgroud)

另一种方法是直接执行原始 SQL。这种方法比前一种方法更快。

from django.db import connection
cursor = connection.cursor()
cursor.execute("TRUNCATE TABLE table_name")
Run Code Online (Sandbox Code Playgroud)

查询3:

要获取模型的表名称,可以使用db_tablemodelMeta选项。

my_model_object._meta.db_table # gives the db table name
Run Code Online (Sandbox Code Playgroud)