PageRenderTime 44ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/django_mongodb_engine/base.py

https://github.com/bhomnick/mongodb-engine
Python | 184 lines | 140 code | 33 blank | 11 comment | 25 complexity | 2064aacdb8ae1674da1c42a7e2c17aac MD5 | raw file
  1. import copy
  2. from django.core.exceptions import ImproperlyConfigured
  3. from django.db.backends.signals import connection_created
  4. from django.conf import settings
  5. from pymongo.connection import Connection
  6. from pymongo.collection import Collection
  7. from .creation import DatabaseCreation
  8. from .utils import CollectionDebugWrapper
  9. from djangotoolbox.db.base import (
  10. NonrelDatabaseFeatures,
  11. NonrelDatabaseWrapper,
  12. NonrelDatabaseValidation,
  13. NonrelDatabaseIntrospection,
  14. NonrelDatabaseOperations
  15. )
  16. from datetime import datetime
  17. def _warn_deprecated(opt):
  18. import warnings
  19. warnings.warn("The %r option is deprecated as of version 0.4 in flavor of "
  20. "the 'OPERATIONS' setting" % opt, PendingDeprecationWarning)
  21. class DatabaseFeatures(NonrelDatabaseFeatures):
  22. supports_microsecond_precision = False
  23. string_based_auto_field = True
  24. supports_dicts = True
  25. supports_long_model_names = False
  26. class DatabaseOperations(NonrelDatabaseOperations):
  27. compiler_module = __name__.rsplit('.', 1)[0] + '.compiler'
  28. def max_name_length(self):
  29. return 254
  30. def check_aggregate_support(self, aggregate):
  31. import aggregations
  32. try:
  33. getattr(aggregations, aggregate.__class__.__name__)
  34. except AttributeError:
  35. raise NotImplementedError("django-mongodb-engine does not support %r "
  36. "aggregates" % type(aggregate))
  37. def sql_flush(self, style, tables, sequence_list):
  38. """
  39. Returns a list of SQL statements that have to be executed to drop
  40. all `tables`. No SQL in MongoDB, so just clear all tables here and
  41. return an empty list.
  42. """
  43. for table in tables:
  44. if table.startswith('system.'):
  45. # do not try to drop system collections
  46. continue
  47. self.connection.database[table].remove()
  48. return []
  49. def value_to_db_date(self, value):
  50. if value is None:
  51. return None
  52. return datetime(value.year, value.month, value.day)
  53. def value_to_db_time(self, value):
  54. if value is None:
  55. return None
  56. return datetime(1, 1, 1, value.hour, value.minute, value.second,
  57. value.microsecond)
  58. class DatabaseValidation(NonrelDatabaseValidation):
  59. pass
  60. class DatabaseIntrospection(NonrelDatabaseIntrospection):
  61. def table_names(self):
  62. return self.connection.database.collection_names()
  63. def sequence_list(self):
  64. # Only required for backends that use integer primary keys
  65. pass
  66. class DatabaseWrapper(NonrelDatabaseWrapper):
  67. def __init__(self, *args, **kwargs):
  68. self.collection_class = kwargs.pop('collection_class', Collection)
  69. super(DatabaseWrapper, self).__init__(*args, **kwargs)
  70. self.features = DatabaseFeatures(self)
  71. self.ops = DatabaseOperations(self)
  72. self.creation = DatabaseCreation(self)
  73. self.introspection = DatabaseIntrospection(self)
  74. self.validation = DatabaseValidation(self)
  75. self.connected = False
  76. del self.connection
  77. # Public API: connection, database, get_collection
  78. def get_collection(self, name, **kwargs):
  79. collection = self.collection_class(self.database, name, **kwargs)
  80. if settings.DEBUG:
  81. collection = CollectionDebugWrapper(collection, self.alias)
  82. return collection
  83. def __getattr__(self, attr):
  84. if attr in ['connection', 'database']:
  85. assert not self.connected
  86. self._connect()
  87. return getattr(self, attr)
  88. raise AttributeError(attr)
  89. def _connect(self):
  90. settings = copy.deepcopy(self.settings_dict)
  91. def pop(name, default=None):
  92. return settings.pop(name) or default
  93. db_name = pop('NAME')
  94. host = pop('HOST')
  95. port = pop('PORT')
  96. user = pop('USER')
  97. password = pop('PASSWORD')
  98. options = pop('OPTIONS', {})
  99. if port:
  100. try:
  101. port = int(port)
  102. except ValueError:
  103. raise ImproperlyConfigured("If set, PORT must be an integer "
  104. "(got %r instead)" % port)
  105. self.operation_flags = options.pop('OPERATIONS', {})
  106. if not any(k in ['save', 'delete', 'update'] for k in self.operation_flags):
  107. # flags apply to all operations
  108. flags = self.operation_flags
  109. self.operation_flags = {'save' : flags, 'delete' : flags, 'update' : flags}
  110. # Compatibility to version < 0.4
  111. if 'SAFE_INSERTS' in settings:
  112. _warn_deprecated('SAFE_INSERTS')
  113. self.operation_flags['save']['safe'] = settings['SAFE_INSERTS']
  114. if 'WAIT_FOR_SLAVES' in settings:
  115. _warn_deprecated('WAIT_FOR_SLAVES')
  116. self.operation_flags['save']['w'] = settings['WAIT_FOR_SLAVES']
  117. # lower-case all remaining OPTIONS
  118. for key in options.iterkeys():
  119. options[key.lower()] = options.pop(key)
  120. try:
  121. self.connection = Connection(host=host, port=port, **options)
  122. self.database = self.connection[db_name]
  123. except TypeError:
  124. import sys
  125. exc_info = sys.exc_info()
  126. raise ImproperlyConfigured, exc_info[1], exc_info[2]
  127. if user and password:
  128. if not self.database.authenticate(user, password):
  129. raise ImproperlyConfigured("Invalid username or password")
  130. self._add_serializer()
  131. self.connected = True
  132. connection_created.send(sender=self.__class__, connection=self)
  133. def _reconnect(self):
  134. if self.connected:
  135. del self.connection
  136. del self.database
  137. self.connected = False
  138. self._connect()
  139. def _add_serializer(self):
  140. for option in ['MONGODB_AUTOMATIC_REFERENCING',
  141. 'MONGODB_ENGINE_ENABLE_MODEL_SERIALIZATION']:
  142. if getattr(settings, option, False):
  143. from .serializer import TransformDjango
  144. self.database.add_son_manipulator(TransformDjango())
  145. return
  146. def _commit(self):
  147. pass
  148. def _rollback(self):
  149. pass
  150. def close(self):
  151. pass