【问题标题】:updating a field in model according to count "many to many" field根据计数“多对多”字段更新模型中的字段
【发布时间】:2015-07-17 08:53:28
【问题描述】:

我有一个名为 Friend 的 django 模型,其中包含一个名为 friends 的多对多字段,以及另一个名为 FriendshipInfo 的模型。出于性能原因,我决定保留一个包含每个人拥有的朋友数量的字段。所以现在在迁移脚本中我需要更新我的数据库中的现有朋友。我就是这样做的:

def forward(...):
    # ... adding the new count field ...
    for person in Friend.objects.all():
        person.friends_count = len(persion.friends.all())
        person.uupdate()

我想知道是否有任何方法可以更有效地执行此操作(以某种方式批量更新?)
技术信息:

  1. 我使用的是 Python 2.7
  2. 我使用的是 django 1.6
  3. 对于我使用南的迁移

【问题讨论】:

  • 至少使用person.friends.count() 而不是len(person.friends.all())。来自 django 的文档:“count() 调用在幕后执行 SELECT COUNT(*),因此您应该始终使用 count() 而不是将所有记录加载到 Python 对象中并在结果上调用 len()(除非您无论如何都需要将对象加载到内存中,在这种情况下 len() 会更快)。”

标签: python django django-models migration


【解决方案1】:

我很想使用extra 查询集方法来获取朋友的数量并批量更新您的Friend 对象,例如:

def forward(...):
    # adding the new count field
    Friend.objects.extra(select = {
        'friends_number': 'SELECT COUNT(*) FROM <your_many_to_many_table_name> WHERE <your_many_to_many_table_name>.<your_FriendshipInfo_related_name> = <your_Friend_table_name>.id'
    }).update(friends_count=F('friends_number'))

但是,by the look of things,这是不可能的。但是,您可以使用 raw 方法 custom SQL queriesupdate from count query

from django.db import connection

def forward(...):
    # adding the new count field
    cursor = connection.cursor()
    cursor.execute('\
        UPDATE <your_Friend_table_name>\
        SET friends_count = \
        (SELECT COUNT(*) FROM <your_many_to_many_table_name> WHERE <your_many_to_many_table_name>.<your_FriendshipInfo_related_name> = <your_Friend_table_name>.id)')

【讨论】:

  • 谢谢 - 我想知道是否有一种纯粹的“django orm”方式来做这件事,就像不写一个 sql 查询一样。
  • 我想要实现的解决方案是这样的:Friend.objects.all().update(firends_count=Count(F('friends'))) - 当我尝试这样做时,我收到错误 TypeError: int() argument must be a string or a number, not 'Count' - 有什么想法吗?
  • Friend.objects.all().annotate(my_friends_count=Count('friends')).update(friends_count=F('my_friends_count')) 工作吗?
【解决方案2】:

迁移文件中的正确方式进行数据迁移 (.py) 在那里你可以毫无问题地放置sql查询,方法是migrations.RUNSQL 这是一个例子:

类迁移(migrations.Migration):

dependencies = [
    ('procesos', '0020_auto_20150703_1656'),
]

operations = [
    migrations.RunSQL("UPDATE procesos_busquedainmueble SET tipo_inmueble_id=(filtros::json->>'tipo_inmueble')::int;"),

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-08-08
    • 1970-01-01
    • 2013-07-13
    • 2022-10-24
    • 1970-01-01
    • 2020-08-13
    • 2021-11-27
    • 1970-01-01
    相关资源
    最近更新 更多