pgutils.py 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071
  1. from django.db.migrations.operations import RunSQL
  2. from django.core.paginator import Paginator
  3. class CreatePartialIndex(RunSQL):
  4. CREATE_SQL = """
  5. CREATE INDEX %(index_name)s ON %(table)s (%(field)s)
  6. WHERE %(condition)s;
  7. """
  8. REMOVE_SQL = """
  9. DROP INDEX %(index_name)s
  10. """
  11. def __init__(self, field, index_name, condition):
  12. self.model, self.field = field.split('.')
  13. self.index_name = index_name
  14. self.condition = condition
  15. @property
  16. def reversible(self):
  17. return True
  18. def state_forwards(self, app_label, state):
  19. pass
  20. def database_forwards(self, app_label, schema_editor,
  21. from_state, to_state):
  22. apps = from_state.render()
  23. model = apps.get_model(app_label, self.model)
  24. statement = self.CREATE_SQL % {
  25. 'index_name': self.index_name,
  26. 'table': model._meta.db_table,
  27. 'field': self.field,
  28. 'condition': self.condition,
  29. }
  30. schema_editor.execute(statement)
  31. def database_backwards(self, app_label, schema_editor,
  32. from_state, to_state):
  33. schema_editor.execute(
  34. self.REMOVE_SQL % {'index_name': self.index_name})
  35. def describe(self):
  36. message = "Create PostgreSQL partial index on field %s in %s for %s"
  37. formats = (self.field, self.model_name, self.values)
  38. return message % formats
  39. def batch_update(queryset, step=50):
  40. """
  41. Util because psycopg2 iterators aren't really memory effective
  42. """
  43. paginator = Paginator(queryset, step)
  44. for page_number in paginator.page_range:
  45. print page_number
  46. for obj in paginator.page(page_number).object_list:
  47. yield obj
  48. def batch_delete(queryset, step=50):
  49. """
  50. Another util cos paginator goes bobbins when you are deleting
  51. """
  52. queryset_exists = True
  53. while queryset_exists:
  54. for obj in queryset[:step]:
  55. yield obj
  56. queryset_exists = queryset.exists()