fields.py 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. """This module provides SQL Server specific fields for Django models."""
  2. from __future__ import unicode_literals
  3. import datetime
  4. from django.db import models
  5. from django.forms import ValidationError
  6. from django.utils import six, timezone
  7. from django.utils.translation import ugettext_lazy as _
  8. if six.PY3:
  9. long = int
  10. __all__ = (
  11. 'BigAutoField',
  12. 'BigForeignKey',
  13. 'BigIntegerField',
  14. 'DateField',
  15. 'DateTimeField',
  16. 'DateTimeOffsetField',
  17. 'LegacyTimeField',
  18. 'LegacyDateField',
  19. 'LegacyDateTimeField',
  20. 'TimeField',
  21. )
  22. class BigAutoField(models.AutoField):
  23. """A bigint IDENTITY field"""
  24. def get_internal_type(self):
  25. return "BigAutoField"
  26. def to_python(self, value):
  27. if value is None:
  28. return value
  29. try:
  30. return long(value)
  31. except (TypeError, ValueError):
  32. raise ValidationError(
  33. _("This value must be a long."))
  34. def get_db_prep_value(self, value, connection=None, prepared=False):
  35. if value is None:
  36. return None
  37. return long(value)
  38. class BigForeignKey(models.ForeignKey):
  39. """A ForeignKey field that points to a BigAutoField or BigIntegerField"""
  40. def db_type(self, connection=None):
  41. try:
  42. return models.BigIntegerField().db_type(connection=connection)
  43. except AttributeError:
  44. return models.BigIntegerField().db_type()
  45. BigIntegerField = models.BigIntegerField
  46. def convert_microsoft_date_to_isoformat(value):
  47. if isinstance(value, six.string_types):
  48. value = value.replace(' +', '+').replace(' -', '-')
  49. return value
  50. class DateField(models.DateField):
  51. """
  52. A DateField backed by a 'date' database field.
  53. """
  54. def get_internal_type(self):
  55. return 'NewDateField'
  56. def to_python(self, value):
  57. val = super(DateField, self).to_python(
  58. convert_microsoft_date_to_isoformat(value)
  59. )
  60. if isinstance(val, datetime.datetime):
  61. val = datetime.date()
  62. return val
  63. class DateTimeField(models.DateTimeField):
  64. """
  65. A DateTimeField backed by a 'datetime2' database field.
  66. """
  67. def get_internal_type(self):
  68. return 'NewDateTimeField'
  69. def to_python(self, value):
  70. from django.conf import settings
  71. result = super(DateTimeField, self).to_python(
  72. convert_microsoft_date_to_isoformat(value)
  73. )
  74. if result:
  75. if timezone.is_aware(result) and not settings.USE_TZ:
  76. result = timezone.make_naive(result, timezone.utc)
  77. elif settings.USE_TZ:
  78. result = timezone.make_aware(result, timezone.utc)
  79. return result
  80. def get_db_prep_value(self, value, connection, prepared=False):
  81. if not prepared:
  82. value = self.get_prep_value(value)
  83. return connection.ops._new_value_to_db_datetime(value)
  84. class DateTimeOffsetField(models.DateTimeField):
  85. """
  86. A DateTimeOffsetField backed by a 'datetimeoffset' database field.
  87. """
  88. def get_internal_type(self):
  89. return 'DateTimeOffsetField'
  90. def to_python(self, value):
  91. return super(DateTimeOffsetField, self).to_python(
  92. convert_microsoft_date_to_isoformat(value)
  93. )
  94. def get_db_prep_value(self, value, connection, prepared=False):
  95. if not prepared:
  96. value = self.get_prep_value(value)
  97. if value is None:
  98. return None
  99. return value.isoformat()
  100. class TimeField(models.TimeField):
  101. """
  102. A TimeField backed by a 'time' database field.
  103. """
  104. def get_internal_type(self):
  105. return 'NewTimeField'
  106. def to_python(self, value):
  107. return super(TimeField, self).to_python(
  108. convert_microsoft_date_to_isoformat(value)
  109. )
  110. def get_db_prep_value(self, value, connection, prepared=False):
  111. if not prepared:
  112. value = self.get_prep_value(value)
  113. return connection.ops._new_value_to_db_time(value)
  114. class LegacyDateField(models.DateField):
  115. """
  116. A DateField that is backed by a 'datetime' database field.
  117. """
  118. def get_internal_type(self):
  119. return 'LegacyDateField'
  120. def to_python(self, value):
  121. val = super(LegacyDateField, self).to_python(
  122. convert_microsoft_date_to_isoformat(value)
  123. )
  124. if isinstance(val, datetime.datetime):
  125. val = datetime.date()
  126. return val
  127. class LegacyDateTimeField(models.DateTimeField):
  128. """
  129. A DateTimeField that is backed by a 'datetime' database field.
  130. """
  131. def get_internal_type(self):
  132. return 'LegacyDateTimeField'
  133. def to_python(self, value):
  134. return super(LegacyDateTimeField, self).to_python(
  135. convert_microsoft_date_to_isoformat(value)
  136. )
  137. def get_db_prep_value(self, value, connection, prepared=False):
  138. if not prepared:
  139. value = self.get_prep_value(value)
  140. return connection.ops._legacy_value_to_db_datetime(value)
  141. class LegacyTimeField(models.TimeField):
  142. """
  143. A TimeField that is backed by a 'datetime' database field.
  144. """
  145. def get_internal_type(self):
  146. return 'LegacyTimeField'
  147. def to_python(self, value):
  148. val = super(LegacyTimeField, self).to_python(
  149. convert_microsoft_date_to_isoformat(value)
  150. )
  151. if isinstance(val, datetime.datetime):
  152. val = val.time()
  153. return val
  154. def get_db_prep_value(self, value, connection, prepared=False):
  155. if not prepared:
  156. value = self.get_prep_value(value)
  157. return connection.ops._legacy_value_to_db_time(value)