Mr T.
Mr T.

Reputation: 4508

updating a field in model according to count "many to many" field

I have a django model called Friend that contains a many to many field called friends through another model called FriendshipInfo. For performance reasons i decided to hold a field that holds the number of friends each person has. So now in the migration scripts i need to update the existing friends in my db. This is how i did it:

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

I was wondering if there is any way to do this in a much more efficient way (bulk update somehow?)
Tech info:

  1. I am using Python 2.7
  2. I am using django 1.6
  3. For migrations I'm using south

Upvotes: 1

Views: 316

Answers (2)

Hetdev
Hetdev

Reputation: 1525

the right way it's in the migration file do the data migration (.py) there you can put the sql query without a problem, the method is migrations.RUNSQL here it's a example:

class Migration(migrations.Migration):

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

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

Upvotes: 0

301_Moved_Permanently
301_Moved_Permanently

Reputation: 4186

I was tempted to use the extra queryset method to grab the count of friends and bulk update your Friend objects like:

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'))

But, by the look of things, it is not possible. However, you can use the raw method custom SQL queries with an update 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)')

Upvotes: 1

Related Questions