apps.py 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. from psycopg2.extras import (
  2. DateRange, DateTimeRange, DateTimeTZRange, NumericRange,
  3. )
  4. from django.apps import AppConfig
  5. from django.db import connections
  6. from django.db.backends.signals import connection_created
  7. from django.db.migrations.writer import MigrationWriter
  8. from django.db.models import CharField, OrderBy, TextField
  9. from django.db.models.functions import Collate
  10. from django.db.models.indexes import IndexExpression
  11. from django.test.signals import setting_changed
  12. from django.utils.translation import gettext_lazy as _
  13. from .indexes import OpClass
  14. from .lookups import SearchLookup, TrigramSimilar, Unaccent
  15. from .serializers import RangeSerializer
  16. from .signals import register_type_handlers
  17. RANGE_TYPES = (DateRange, DateTimeRange, DateTimeTZRange, NumericRange)
  18. def uninstall_if_needed(setting, value, enter, **kwargs):
  19. """
  20. Undo the effects of PostgresConfig.ready() when django.contrib.postgres
  21. is "uninstalled" by override_settings().
  22. """
  23. if not enter and setting == 'INSTALLED_APPS' and 'django.contrib.postgres' not in set(value):
  24. connection_created.disconnect(register_type_handlers)
  25. CharField._unregister_lookup(Unaccent)
  26. TextField._unregister_lookup(Unaccent)
  27. CharField._unregister_lookup(SearchLookup)
  28. TextField._unregister_lookup(SearchLookup)
  29. CharField._unregister_lookup(TrigramSimilar)
  30. TextField._unregister_lookup(TrigramSimilar)
  31. # Disconnect this receiver until the next time this app is installed
  32. # and ready() connects it again to prevent unnecessary processing on
  33. # each setting change.
  34. setting_changed.disconnect(uninstall_if_needed)
  35. MigrationWriter.unregister_serializer(RANGE_TYPES)
  36. class PostgresConfig(AppConfig):
  37. name = 'django.contrib.postgres'
  38. verbose_name = _('PostgreSQL extensions')
  39. def ready(self):
  40. setting_changed.connect(uninstall_if_needed)
  41. # Connections may already exist before we are called.
  42. for conn in connections.all():
  43. if conn.vendor == 'postgresql':
  44. conn.introspection.data_types_reverse.update({
  45. 3904: 'django.contrib.postgres.fields.IntegerRangeField',
  46. 3906: 'django.contrib.postgres.fields.DecimalRangeField',
  47. 3910: 'django.contrib.postgres.fields.DateTimeRangeField',
  48. 3912: 'django.contrib.postgres.fields.DateRangeField',
  49. 3926: 'django.contrib.postgres.fields.BigIntegerRangeField',
  50. })
  51. if conn.connection is not None:
  52. register_type_handlers(conn)
  53. connection_created.connect(register_type_handlers)
  54. CharField.register_lookup(Unaccent)
  55. TextField.register_lookup(Unaccent)
  56. CharField.register_lookup(SearchLookup)
  57. TextField.register_lookup(SearchLookup)
  58. CharField.register_lookup(TrigramSimilar)
  59. TextField.register_lookup(TrigramSimilar)
  60. MigrationWriter.register_serializer(RANGE_TYPES, RangeSerializer)
  61. IndexExpression.register_wrappers(OrderBy, OpClass, Collate)