119 lines
4.0 KiB
Python
119 lines
4.0 KiB
Python
from datetime import datetime
|
|
import inspect
|
|
|
|
import django
|
|
from django.conf import settings
|
|
from django.db import connection
|
|
|
|
from django.contrib.auth.tokens import PasswordResetTokenGenerator
|
|
|
|
try:
|
|
from django.contrib.auth import get_user_model
|
|
except ImportError:
|
|
from django.contrib.auth.models import User
|
|
get_user_model = lambda: User
|
|
|
|
try:
|
|
from django.db.transaction import atomic
|
|
commit_on_success = atomic
|
|
except ImportError:
|
|
from django.db.transaction import commit_on_success
|
|
|
|
user_model_label = getattr(settings, 'AUTH_USER_MODEL', 'auth.User')
|
|
|
|
default_token_generator = PasswordResetTokenGenerator()
|
|
|
|
|
|
def has_postgresql_support():
|
|
if not settings.DATABASES['default'].get('NAME'):
|
|
return False
|
|
return connection.vendor == 'postgresql' and connection.pg_version > 90400
|
|
|
|
|
|
def use_django_native_field():
|
|
return has_postgresql_support() and django.VERSION >= (1, 11)
|
|
|
|
|
|
class JSONField(object):
|
|
__dj11_field = None
|
|
__jsonfield_field = None
|
|
__name = None
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
self.__args = args
|
|
self.__kwargs = kwargs
|
|
if django.VERSION >= (1, 11):
|
|
try:
|
|
from django.contrib.postgres.fields import JSONField
|
|
self.__dj11_field = JSONField(*args, **kwargs)
|
|
except ImportError:
|
|
pass
|
|
try:
|
|
from jsonfield.fields import JSONField
|
|
self.__jsonfield_field = JSONField(*args, **kwargs)
|
|
except ImportError:
|
|
pass
|
|
|
|
def __real_field__(self):
|
|
if use_django_native_field():
|
|
assert self.__dj11_field
|
|
return self.__dj11_field
|
|
assert self.__jsonfield_field
|
|
return self.__jsonfield_field
|
|
|
|
def __getattr__(self, key):
|
|
return getattr(self.__real_field__(), key)
|
|
|
|
def __setattr__(self, key, value):
|
|
if key.startswith('_JSONField__'):
|
|
super(JSONField, self).__setattr__(key, value)
|
|
else:
|
|
setattr(self.__real__field(), key, value)
|
|
|
|
# we need to implement contribute_to_class so that the direct
|
|
# implementation from the two sub-fields is not used directly
|
|
def contribute_to_class(self, cls, name, private_only=False, virtual_only=False, **kwargs):
|
|
assert not virtual_only and not private_only, 'virtual_only / private_only are not supported'
|
|
assert not kwargs, 'new arguments to contribute_to_class not supported'
|
|
self.__name = name
|
|
if self.__dj11_field:
|
|
self.__dj11_field.set_attributes_from_name(name)
|
|
self.__dj11_field.model = cls
|
|
if self.__jsonfield_field:
|
|
self.__jsonfield_field.set_attributes_from_name(name)
|
|
self.__jsonfield_field.model = cls
|
|
cls._meta.add_field(self)
|
|
|
|
# the next two methods are useful for compatibilit with the migration engine
|
|
# inspect is used because migration autodetector cannot recognize this class
|
|
# as a subclass of models.Field.
|
|
def deconstruct(self):
|
|
d = (self.__name, 'authentic2.compat.JSONField', self.__args, self.__kwargs)
|
|
previous_frame = inspect.currentframe().f_back
|
|
if inspect.getframeinfo(previous_frame)[2] in ('serialize', 'deep_deconstruct'):
|
|
d = d[1:]
|
|
return d
|
|
|
|
def clone(self):
|
|
from copy import copy
|
|
new = copy(self)
|
|
if self.__dj11_field:
|
|
new.__dj11_field = new.__dj11_field.clone()
|
|
if self.__jsonfield_field:
|
|
new.__jsonfield_field = new.__jsonfield_field.clone()
|
|
return new
|
|
|
|
|
|
try:
|
|
from jsonfield import fields
|
|
except ImportError:
|
|
pass
|
|
else:
|
|
# prevent django-jsonfield from modifying postgresql connection when we are
|
|
# not using it
|
|
def configure_database_connection(connection, **kwargs):
|
|
if django.VERSION < (1, 11):
|
|
fields.configure_database_connection(connection, **kwargs)
|
|
fields.connection_created.disconnect(fields.configure_database_connection)
|
|
fields.connection_created.connect(configure_database_connection)
|