From 39d2fdb7666d49f579ebb68eb1a7735136d03a2c Mon Sep 17 00:00:00 2001
From: Timm Fitschen <t.fitschen@indiscale.com>
Date: Tue, 22 Sep 2020 20:23:46 +0200
Subject: [PATCH] WIP

---
 djaosdb/__init__.py                           |  11 +-
 djaosdb/base.py                               |  85 ++---
 djaosdb/caosdb_client.py                      | 352 +++++++++++++++++-
 djaosdb/cursor.py                             |  15 +-
 djaosdb/database.py                           |  11 -
 djaosdb/exceptions.py                         |   4 +-
 djaosdb/introspection.py                      |   4 +-
 djaosdb/mockup_delegator.py                   |  32 ++
 djaosdb/sql2mongo/operators.py                |  16 +-
 djaosdb/sql2mongo/query.py                    | 210 ++++-------
 .../djaosdb_test}/__init__.py                 |   0
 example/djaosdb_test/settings.py              | 165 ++++++++
 example/djaosdb_test/urls.py                  |  21 ++
 example/djaosdb_test/wsgi.py                  |  16 +
 example/manage.py                             |  21 ++
 example/simple_test/__init__.py               |   0
 example/simple_test/admin.py                  |   3 +
 example/simple_test/apps.py                   |   5 +
 example/simple_test/models.py                 |  10 +
 .../simple_test/templates/testrt/create.html  |   4 +
 .../simple_test/templates/testrt/detail.html  |   7 +
 example/simple_test/tests.py                  |   3 +
 example/simple_test/urls.py                   |   7 +
 example/simple_test/views.py                  |  14 +
 setup.py                                      |   4 +-
 tests/djongo_tests/test_project/djongo-test   | Bin 188416 -> 0 bytes
 tests/djongo_tests/test_project/manage.py     |   2 +-
 .../test_project/simple/__init__.py           |   0
 .../djongo_tests/test_project/simple/apps.py  |   5 +
 .../test_project/simple/models/basic.py       |   8 +
 .../settings_loaded.py => settings.py}        |  63 +++-
 .../test_project/settings/settings_lite.py    | 130 -------
 .../settings/settings_loaded_formsets.py      | 125 -------
 .../settings/settings_precheckin.py           | 121 ------
 .../test_project/urls/urls_loaded.py          |   4 +-
 .../test_project/xtest_app/admin.py           |  14 +-
 36 files changed, 846 insertions(+), 646 deletions(-)
 create mode 100644 djaosdb/mockup_delegator.py
 rename {tests/djongo_tests/test_project/test_project/settings => example/djaosdb_test}/__init__.py (100%)
 create mode 100644 example/djaosdb_test/settings.py
 create mode 100644 example/djaosdb_test/urls.py
 create mode 100644 example/djaosdb_test/wsgi.py
 create mode 100755 example/manage.py
 create mode 100644 example/simple_test/__init__.py
 create mode 100644 example/simple_test/admin.py
 create mode 100644 example/simple_test/apps.py
 create mode 100644 example/simple_test/models.py
 create mode 100644 example/simple_test/templates/testrt/create.html
 create mode 100644 example/simple_test/templates/testrt/detail.html
 create mode 100644 example/simple_test/tests.py
 create mode 100644 example/simple_test/urls.py
 create mode 100644 example/simple_test/views.py
 delete mode 100644 tests/djongo_tests/test_project/djongo-test
 create mode 100644 tests/djongo_tests/test_project/simple/__init__.py
 create mode 100644 tests/djongo_tests/test_project/simple/apps.py
 create mode 100644 tests/djongo_tests/test_project/simple/models/basic.py
 rename tests/djongo_tests/test_project/test_project/{settings/settings_loaded.py => settings.py} (65%)
 delete mode 100644 tests/djongo_tests/test_project/test_project/settings/settings_lite.py
 delete mode 100644 tests/djongo_tests/test_project/test_project/settings/settings_loaded_formsets.py
 delete mode 100644 tests/djongo_tests/test_project/test_project/settings/settings_precheckin.py

diff --git a/djaosdb/__init__.py b/djaosdb/__init__.py
index cac0d26..91cfae3 100644
--- a/djaosdb/__init__.py
+++ b/djaosdb/__init__.py
@@ -1,10 +1 @@
-# This version of Djongo was made possible by
-# the generous contributions from:
-#
-#       * Zachary Sizemore
-#       * Wayne Van Son
-#       * Norman Niemer
-#       * Renz Ladia
-#       * thestick613
-
-__version__ = '1.3.3'
+__version__ = '0.1-dev'
diff --git a/djaosdb/base.py b/djaosdb/base.py
index 67bfd8a..f43deb8 100644
--- a/djaosdb/base.py
+++ b/djaosdb/base.py
@@ -14,30 +14,10 @@ from .features import DatabaseFeatures
 from .introspection import DatabaseIntrospection
 from .operations import DatabaseOperations
 from .schema import DatabaseSchemaEditor
+from .caosdb_client import CaosDBClient
+import caosdb
 
-logger = getLogger(__name__)
-
-
-class CachedCollections(set):
-
-    def __init__(self, database):
-        self.db = database
-        super().__init__()
-
-    def __contains__(self, item):
-        ans = super().__contains__(item)
-        if ans:
-            return ans
-        self.update(self.db.list_collection_names())
-        return super().__contains__(item)
-
-
-class DjongoClient:
-
-    def __init__(self, database, enforce_schema=True):
-        self.enforce_schema = enforce_schema
-        self.cached_collections = CachedCollections(database)
-
+LOGGER = getLogger(__name__)
 
 class DatabaseWrapper(BaseDatabaseWrapper):
     """
@@ -51,28 +31,28 @@ class DatabaseWrapper(BaseDatabaseWrapper):
         'BigAutoField': 'long',
         'BinaryField': 'binData',
         'BooleanField': 'bool',
-        'CharField': 'string',
-        'CommaSeparatedIntegerField': 'string',
-        'DateField': 'date',
-        'DateTimeField': 'date',
+        'CharField': caosdb.TEXT,
+        'CommaSeparatedIntegerField': caosdb.TEXT,
+        'DateField': caosdb.DATETIME,
+        'DateTimeField': caosdb.DATETIME,
         'DecimalField': 'decimal',
         'DurationField': 'long',
-        'FileField': 'string',
-        'FilePathField': 'string',
+        'FileField': caosdb.TEXT,
+        'FilePathField': caosdb.TEXT,
         'FloatField': 'double',
         'IntegerField': 'int',
         'BigIntegerField': 'long',
-        'IPAddressField': 'string',
-        'GenericIPAddressField': 'string',
+        'IPAddressField': caosdb.TEXT,
+        'GenericIPAddressField': caosdb.TEXT,
         'NullBooleanField': 'bool',
         'OneToOneField': 'int',
         'PositiveIntegerField': 'long',
         'PositiveSmallIntegerField': 'int',
-        'SlugField': 'string',
+        'SlugField': caosdb.TEXT,
         'SmallIntegerField': 'int',
-        'TextField': 'string',
-        'TimeField': 'date',
-        'UUIDField': 'string',
+        'TextField': caosdb.TEXT,
+        'TimeField': caosdb.DATETIME,
+        'UUIDField': caosdb.TEXT,
         'GenericObjectIdField': 'objectId',
         'ObjectIdField': 'objectId',
         'EmbeddedField': 'object',
@@ -130,11 +110,9 @@ class DatabaseWrapper(BaseDatabaseWrapper):
         default values to blank fields.
         """
         valid_settings = {
-            'NAME': 'name',
             'ENFORCE_SCHEMA': 'enforce_schema',
         }
         connection_params = {
-            'name': 'djaosdb_test',
             'enforce_schema': False
         }
         for setting_name, kwarg in valid_settings.items():
@@ -153,32 +131,33 @@ class DatabaseWrapper(BaseDatabaseWrapper):
         return connection_params
 
     def get_new_connection(self, connection_params):
-        """
-        Receives a dictionary connection_params to setup
+        """Receives a dictionary connection_params to setup
         a connection to the database.
 
         Dictionary correct setup is made through the
         get_connection_params method.
-        """
 
-        name = connection_params.pop('name')
-        es = connection_params.pop('enforce_schema')
+        Parameters
+        ----------
+        connection_params : dict
 
+        Returns
+        -------
+        connection : CaosDBClient
+        """
         connection_params['document_class'] = OrderedDict
         # connection_params['tz_aware'] = True
         # To prevent leaving unclosed connections behind,
         # client_conn must be closed before a new connection
         # is created.
-        if self.client_connection is not None:
-            self.client_connection.close()
-            logger.debug('Existing CaosDBClient connection closed')
+        if self.connection is not None:
+            self.connection.close()
+            LOGGER.debug('Existing CaosDBClient connection closed')
 
-        self.client_connection = Database.connect(db=name, **connection_params)
-        logger.debug('New Database connection')
+        self.connection = CaosDBClient(**connection_params)
+        LOGGER.debug('New Database connection')
 
-        database = self.client_connection[name]
-        self.djaosdb_connection = DjongoClient(database, es)
-        return self.client_connection[name]
+        return self.connection
 
     def _set_autocommit(self, autocommit):
         """
@@ -199,7 +178,7 @@ class DatabaseWrapper(BaseDatabaseWrapper):
         """
         Returns an active connection cursor to the database.
         """
-        return Cursor(self.client_connection, self.connection, self.djaosdb_connection)
+        return Cursor(self.connection)
 
     def _close(self):
         """
@@ -207,8 +186,8 @@ class DatabaseWrapper(BaseDatabaseWrapper):
         """
         if self.connection:
             with self.wrap_database_errors:
-                self.connection.client.close()
-                logger.debug('CaosDBClient connection closed')
+                self.connection.close()
+                LOGGER.debug('CaosDBClient connection closed')
 
     def _rollback(self):
         raise Error
diff --git a/djaosdb/caosdb_client.py b/djaosdb/caosdb_client.py
index d774115..819b8c1 100644
--- a/djaosdb/caosdb_client.py
+++ b/djaosdb/caosdb_client.py
@@ -1,7 +1,355 @@
+import caosdb
 from logging import getLogger
+from .mockup_delegator import MockupDelegatorConnection
 
 logger = getLogger(__name__)
 
-class CaosDBClient:
+
+class Result:
+    def __init__(self):
+        self.alive = True
+
+    def close(self):
+        """close"""
+        pass
+
+    def __next__(self):
+        """__next__"""
+        # TODO
+        raise StopIteration
+
+    def __iter__(self):
+        """__iter__"""
+        # TODO
+        return self
+
+class FindResult(Result):
+
+    def __init__(self, rows, columns):
+        self.alive = True
+        self._results = []
+
+        for row in rows:
+            self._results.append(dict(zip(columns, row)))
+
+    def __iter__(self):
+        return iter(self._results)
+
+class InsertManyResult(Result):
+    def __init__(self, container):
+        super(InsertManyResult, self).__init__()
+        self.inserted_ids = [e.id for e in container]
+
+    def __iter__(self):
+        return iter(self.inserted_ids)
+
+class CachedRecordTypes(set):
+
+    def __init__(self, connection):
+        self.connection = connection
+        super().__init__()
+
+    def __contains__(self, item):
+        ans = super().__contains__(item)
+        if ans:
+            return ans
+        self.update(self.connection.list_record_type_names())
+        return super().__contains__(item)
+
+class CachedProperties(set):
+
+    def __init__(self, connection):
+        self.connection = connection
+        super().__init__()
+
+    def __contains__(self, item):
+        ans = super().__contains__(item)
+        if ans:
+            return ans
+        self.update(self.connection.list_property_names())
+        return super().__contains__(item)
+
+class DefaultCaosDBClientDelegate:
+
     def __init__(self, **kwargs):
-        logger.info("New CaosDBClient: {}".format(kwargs))
+        self.cached_record_types = CachedRecordTypes(self)
+        self.cached_properties = CachedProperties(self)
+        self._connection = caosdb.configure_connection(**kwargs)
+
+    def find(self, record_type, *args, **kwargs):
+        filter_clause = ""
+        if "filter" in kwargs:
+            fil = kwargs["filter"]
+            n = ""
+            if fil["negation"] is True:
+                n = "NOT "
+            p = fil["p"]
+            o = fil["o"]
+            v = fil["v"]
+            filter_clause = f'WITH {n}{p}{o}"{v}"'
+
+        query = f'FIND RECORD "{record_type}"{filter_clause}'
+        res = caosdb.execute_query(query)
+
+        projection = kwargs["projection"]
+        rows = res.get_property_values(*projection)
+        return FindResult(rows, projection)
+
+    def list_record_type_names(self):
+        res = caosdb.execute_query("SELECT name FROM RECORDTYPE")
+        return [e.name for e in res if e.name is not None]
+
+    def list_property_names(self):
+        res = caosdb.execute_query("SELECT name FROM PROPERTY")
+        return [e.name for e in res if e.name is not None]
+
+    def create_record_type(self, name : str, properties : list):
+        c = caosdb.Container()
+        rt = caosdb.RecordType(name)
+        c.append(rt)
+        for p in properties:
+            name = p["name"]
+            datatype = p["datatype"]
+            if name not in self.cached_properties:
+                new_property = caosdb.Property(name=name, datatype=datatype)
+                c.append(new_property)
+
+            rt.add_property(name=name, datatype=datatype)
+
+        c.insert()
+
+    def insert_many(self, record_type : str, records : list):
+        c = caosdb.Container()
+        for rec in records:
+            name, description = None, None
+            if "name" in rec:
+                name = rec["name"]
+            if "description" in rec:
+                description = rec["description"]
+
+            new_rec = caosdb.Record(name=name, description=description)
+            new_rec.add_parent(record_type)
+            if "properties" in rec:
+                for prop in rec["properties"]:
+                    new_rec.add_property(**prop)
+            c.append(new_rec)
+        c.insert()
+        return InsertManyResult(c)
+
+class CaosDBClient:
+    def __init__(self, enforce_schema=True,
+                 delegate=DefaultCaosDBClientDelegate, **kwargs):
+        logger.info("New CaosDBClient: %s", kwargs)
+        self.enforce_schema = enforce_schema
+        self._delegate = delegate(**kwargs)
+
+    @property
+    def cached_record_types(self):
+        return self._delegate.cached_record_types
+
+    @property
+    def cached_properties(self):
+        return self._delegate.cached_properties
+
+    def list_record_type_names(self):
+        """list_record_types
+
+        List all record types names.
+
+        Returns
+        -------
+        record_types : list of str
+        """
+        logger.debug("list_record_type_names")
+        return self._delegate.list_record_type_names()
+
+    def close(self):
+        """close the connection to a CaosDB Server"""
+        logger.debug("close")
+
+    def create_record_type(self, name : str, properties : list):
+        """create_record_type
+
+        Parameters
+        ----------
+
+        name : str
+            name is the name of the new record type
+        properties : list of dict
+            properties is a list of {name: str, data_type: str} dicts.
+
+        Returns
+        -------
+        None
+        """
+        logger.debug("create_record_type(%s, %s)", name, properties)
+        self._delegate.create_record_type(name, properties)
+
+    def create_index(self, *args, **kwargs):
+        """create_index
+
+        Parameters
+        ----------
+
+        *args :
+        **kwargs :
+
+        Returns
+        -------
+        """
+        # TODO
+        raise Exception("NOT IMPLEMENTED")
+
+    def update_one(self, *args, **kwargs):
+        """update_one
+
+        Parameters
+        ----------
+
+        *args :
+        **kwargs :
+
+        Returns
+        -------
+        """
+        # TODO
+        raise Exception("NOT IMPLEMENTED")
+
+    def update_many(self, *args, **kwargs):
+        """update_many
+
+        Parameters
+        ----------
+
+        *args :
+        **kwargs :
+
+        Returns
+        -------
+        """
+        # TODO
+        raise Exception("NOT IMPLEMENTED")
+
+    def drop_record_type(self, *args, **kwargs):
+        """drop_record_type
+
+        Parameters
+        ----------
+
+        *args :
+        **kwargs :
+
+        Returns
+        -------
+        """
+        # TODO
+        raise Exception("NOT IMPLEMENTED")
+
+    def aggregate(self, *args, **kwargs):
+        """aggregate
+
+        Parameters
+        ----------
+
+        *args :
+        **kwargs :
+
+        Returns
+        -------
+        """
+        logger.debug("aggregate(%s, %s)", args, kwargs)
+        return self._delegate.aggregate(*args, **kwargs)
+
+    def insert_many(self, record_type : str, records : list):
+        """insert_many
+
+        Parameters
+        ----------
+
+        record_type : str
+            name of the record type
+        records : list of dict
+            list of properties for the new records
+
+        Returns
+        -------
+        result : InsertManyResult
+        """
+        logger.debug("insert_many(%s, %s)", record_type, records)
+        return self._delegate.insert_many(record_type, records)
+
+    def update(self, *args, **kwargs):
+        """update
+
+        Parameters
+        ----------
+
+        *args :
+        **kwargs :
+
+        Returns
+        -------
+        """
+        # TODO
+        raise Exception("NOT IMPLEMENTED")
+
+    def rename(self, *args, **kwargs):
+        """rename
+
+        Parameters
+        ----------
+
+        *args :
+        **kwargs :
+
+        Returns
+        -------
+        """
+        # TODO
+        raise Exception("NOT IMPLEMENTED")
+
+    def delete_many(self, *args, **kwargs):
+        """delete_many
+
+        Parameters
+        ----------
+
+        *args :
+        **kwargs :
+
+        Returns
+        -------
+        """
+        # TODO
+        raise Exception("NOT IMPLEMENTED")
+
+    def drop_index(self, *args, **kwargs):
+        """drop_index
+
+        Parameters
+        ----------
+
+        *args :
+        **kwargs :
+
+        Returns
+        -------
+        """
+        # TODO
+        raise Exception("NOT IMPLEMENTED")
+
+    def find(self, *args, **kwargs):
+        """find
+
+        Parameters
+        ----------
+
+        *args :
+        **kwargs :
+
+        Returns
+        -------
+        result : FindResult
+        """
+        logger.debug("find(%s, %s)", args, kwargs)
+        return self._delegate.find(*args, **kwargs)
diff --git a/djaosdb/cursor.py b/djaosdb/cursor.py
index f5a4f4b..08e9106 100644
--- a/djaosdb/cursor.py
+++ b/djaosdb/cursor.py
@@ -8,13 +8,8 @@ logger = getLogger(__name__)
 
 class Cursor:
 
-    def __init__(self,
-                 client_conn,
-                 db_conn,
-                 connection_properties):
-        self.db_conn = db_conn
-        self.client_conn = client_conn
-        self.connection_properties = connection_properties
+    def __init__(self, connection):
+        self.connection = connection
         self.result = None
 
     def __exit__(self, exc_type, exc_val, exc_tb):
@@ -31,7 +26,7 @@ class Cursor:
             pass
 
         try:
-            return getattr(self.db_conn, name)
+            return getattr(self.connection, name)
         except AttributeError:
             raise
 
@@ -49,9 +44,7 @@ class Cursor:
     def execute(self, sql, params=None):
         try:
             self.result = Query(
-                self.client_conn,
-                self.db_conn,
-                self.connection_properties,
+                self.connection,
                 sql,
                 params)
         except Exception as e:
diff --git a/djaosdb/database.py b/djaosdb/database.py
index fffa990..e5f591d 100644
--- a/djaosdb/database.py
+++ b/djaosdb/database.py
@@ -1,17 +1,6 @@
-from .caosdb_client import CaosDBClient
 from logging import getLogger
 
 logger = getLogger(__name__)
-clients = {}
-
-
-def connect(db, **kwargs):
-    try:
-        return clients[db]
-    except KeyError:
-        logger.debug('New CaosDBClient connection')
-        clients[db] = CaosDBClient(**kwargs, connect=False)
-    return clients[db]
 
 
 class Error(Exception):  # NOQA: StandardError undefined on PY3
diff --git a/djaosdb/exceptions.py b/djaosdb/exceptions.py
index 46a8656..e31534d 100644
--- a/djaosdb/exceptions.py
+++ b/djaosdb/exceptions.py
@@ -1,7 +1,7 @@
 from dataclasses import dataclass
 from typing import Sequence, Any
 
-djaosdb_access_url = 'https://nesdis.github.io/djaosdb/sponsor/'
+djaosdb_access_url = 'TODO'
 _printed_features = set()
 
 
@@ -41,4 +41,4 @@ def print_warn(feature=None, message=None):
         message = ((message or f'This version of djaosdb does not support "{feature}" fully. ')
                    + f'Visit {djaosdb_access_url}')
         print(message)
-        _printed_features.add(feature)
\ No newline at end of file
+        _printed_features.add(feature)
diff --git a/djaosdb/introspection.py b/djaosdb/introspection.py
index 1066f1a..59ed366 100644
--- a/djaosdb/introspection.py
+++ b/djaosdb/introspection.py
@@ -46,11 +46,9 @@ class DatabaseIntrospection(BaseDatabaseIntrospection):
     #     return sorted(cursor.m_cli_connection.collection_names(False))
 
     def get_table_list(self, cursor):
-
         return [
             TableInfo(c, 't')
-            for c in cursor.db_conn.list_collection_names()
-            if c != '__schema__'
+            for c in cursor.connection.list_record_type_names()
         ]
 
     def get_constraints(self, cursor, table_name):
diff --git a/djaosdb/mockup_delegator.py b/djaosdb/mockup_delegator.py
new file mode 100644
index 0000000..fd9ed2e
--- /dev/null
+++ b/djaosdb/mockup_delegator.py
@@ -0,0 +1,32 @@
+class MockupDelegatorConnection():
+
+    def __init__(self):
+        pass
+
+    def insert_many(self, table, *args, **kwargs):
+        from .caosdb_client import InsertManyResult
+        if "django_migrations" == table:
+            new_id = hash(args[0][0]["applied"]) + hash(args[0][0]["app"])
+            result = InsertManyResult()
+            result.inserted_ids = [new_id]
+            return result
+        if "django_content_type" == table:
+            new_id = hash(args[0][0]["model"]) + hash(args[0][0]["app_label"])
+            result = InsertManyResult()
+            result.inserted_ids = [new_id]
+            return result
+
+
+        return None
+
+    def list_record_type_names(self):
+        return ["django_migrations", "django_content_type", "auth_permission"]
+
+    def aggregate(self, *args, **kwargs):
+        from .caosdb_client import Result
+        if "auth_permission" == args[0]:
+            result = Result()
+            return result
+
+        return None
+
diff --git a/djaosdb/sql2mongo/operators.py b/djaosdb/sql2mongo/operators.py
index ed3637b..80f0626 100644
--- a/djaosdb/sql2mongo/operators.py
+++ b/djaosdb/sql2mongo/operators.py
@@ -526,18 +526,16 @@ class CmpOp(_Op):
         if self._field_ext:
             field += '.' + self._field_ext
 
-        if not self.is_negated:
-            return {field: {self._operator: self._constant}}
-        else:
-            return {field: {'$not': {self._operator: self._constant}}}
+        return {"negation": self.is_negated, "p": field, "o":
+                self._operator, "v": self._constant}
 
 
 OPERATOR_MAP = {
-    '=': '$eq',
-    '>': '$gt',
-    '<': '$lt',
-    '>=': '$gte',
-    '<=': '$lte',
+    '=': '=',
+    '>': '>',
+    '<': '<',
+    '>=': '>=',
+    '<=': '<=',
 }
 OPERATOR_PRECEDENCE = {
     'IS': 8,
diff --git a/djaosdb/sql2mongo/query.py b/djaosdb/sql2mongo/query.py
index 9ed8701..4c3705e 100644
--- a/djaosdb/sql2mongo/query.py
+++ b/djaosdb/sql2mongo/query.py
@@ -21,7 +21,6 @@ from sqlparse.sql import (
     Where,
     Statement)
 
-from ..caosdb_client import CaosDBClient
 from ..exceptions import SQLDecodeError, MigrationError, print_warn
 from .functions import SQLFunc
 from .sql_tokens import (SQLToken, SQLStatement, SQLIdentifier,
@@ -58,13 +57,11 @@ class TokenAlias:
 
 class BaseQuery(abc.ABC):
     def __init__(self,
-                 db: str,
-                 connection_properties: 'base.DjongoClient',
+                 connection: 'caosdb_client.CaosDBClient',
                  statement: Statement,
                  params: Sequence):
         self.statement = statement
-        self.db = db
-        self.connection_properties = connection_properties
+        self.connection = connection
         self.params = params
         self.token_alias = TokenAlias()
         self.nested_query: Optional[NestedInQueryConverter] = None
@@ -244,7 +241,7 @@ class SelectQuery(DQLQuery):
     def _get_cursor(self):
         if self._needs_aggregation():
             pipeline = self._make_pipeline()
-            cur = self.db[self.left_table].aggregate(pipeline)
+            cur = self.connection.aggregate(self.left_table, pipeline)
             logger.debug(f'Aggregation query: {pipeline}')
         else:
             kwargs = {}
@@ -259,11 +256,11 @@ class SelectQuery(DQLQuery):
 
             if self.order:
                 kwargs.update(self.order.to_mongo())
-            
+
             if self.offset:
                 kwargs.update(self.offset.to_mongo())
 
-            cur = self.db[self.left_table].find(**kwargs)
+            cur = self.connection.find(self.left_table, **kwargs)
             logger.debug(f'Find query: {kwargs}')
 
         return cur
@@ -281,14 +278,14 @@ class SelectQuery(DQLQuery):
                     try:
                         ret.append(doc[selected.column])
                     except KeyError:
-                        if self.connection_properties.enforce_schema:
+                        if self.connection.enforce_schema:
                             raise MigrationError(selected.column)
                         ret.append(None)
                 else:
                     try:
                         ret.append(doc[selected.table][selected.column])
                     except KeyError:
-                        if self.connection_properties.enforce_schema:
+                        if self.connection.enforce_schema:
                             raise MigrationError(selected.column)
                         ret.append(None)
             else:
@@ -335,8 +332,8 @@ class UpdateQuery(DMLQuery):
         self.kwargs.update(self.set_columns.to_mongo())
 
     def execute(self):
-        db = self.db
-        self.result = db[self.left_table].update_many(**self.kwargs)
+        db = self.connection
+        self.result = db.update_many(self.left_table, **self.kwargs)
         logger.debug(f'update_many: {self.result.modified_count}, matched: {self.result.matched_count}')
 
 
@@ -352,13 +349,13 @@ class InsertQuery(DMLQuery):
 
     def _table(self, statement: SQLStatement):
         tok = statement.next()
-        collection = tok.get_name()
-        if collection not in self.connection_properties.cached_collections:
-            if self.connection_properties.enforce_schema:
-                raise MigrationError(f'Table {collection} does not exist in database')
-            self.connection_properties.cached_collections.add(collection)
+        record_type = tok.get_name()
+        if record_type not in self.connection.cached_record_types:
+            if self.connection.enforce_schema:
+                raise MigrationError(f'RecordType {record_type} does not exist.')
+            self.connection.cached_record_types.add(record_type)
 
-        self.left_table = collection
+        self.left_table = record_type
 
     def _columns(self, statement: SQLStatement):
         tok = statement.next()
@@ -379,37 +376,20 @@ class InsertQuery(DMLQuery):
                 raise SQLDecodeError
 
     def execute(self):
-        docs = []
+        records = []
         num = len(self._values)
 
-        auto = self.db['__schema__'].find_one_and_update(
-            {
-                'name': self.left_table,
-                'auto': {
-                    '$exists': True
-                }
-            },
-            {'$inc': {'auto.seq': num}},
-            return_document=ReturnDocument.AFTER
-        )
-
         for i, val in enumerate(self._values):
-            ins = {}
-            if auto:
-                for name in auto['auto']['field_names']:
-                    ins[name] = auto['auto']['seq'] - num + i + 1
+            ins = {"properties": []}
             for _field, value in zip(self._cols, val):
-                if (auto and _field in auto['auto']['field_names']
-                        and value == 'DEFAULT'):
-                    continue
-                ins[_field] = value
-            docs.append(ins)
+                if _field in ["name", "description"]:
+                    ins[_field] = value
+                else:
+                    ins["properties"].append({"value": value, "name": _field})
+            records.append(ins)
 
-        res = self.db[self.left_table].insert_many(docs, ordered=False)
-        if auto:
-            self._result_ref.last_row_id = auto['auto']['seq']
-        else:
-            self._result_ref.last_row_id = res.inserted_ids[-1]
+        res = self.connection.insert_many(self.left_table, records)
+        self._result_ref.last_row_id = res.inserted_ids[-1]
         logger.debug('inserted ids {}'.format(res.inserted_ids))
 
     def parse(self):
@@ -472,10 +452,11 @@ class AlterQuery(DDLQuery):
 
         if not column:
             # Rename table
-            self.execute = self._rename_collection
+            self.execute = self._rename_record_type
 
     def _rename_column(self):
-        self.db[self.left_table].update(
+        self.connection.update(
+            self.left_table,
             {},
             {
                 '$rename': {
@@ -485,8 +466,8 @@ class AlterQuery(DDLQuery):
             multi=True
         )
 
-    def _rename_collection(self):
-        self.db[self.left_table].rename(self._new_name)
+    def _rename_record_type(self):
+        self.connection.rename(self.left_table, self._new_name)
 
     def _alter(self, statement: SQLStatement):
         self.execute = lambda: None
@@ -513,7 +494,7 @@ class AlterQuery(DDLQuery):
         print_warn(feature)
 
     def _flush(self):
-        self.db[self.left_table].delete_many({})
+        self.connection.delete_many(self.left_table, {})
 
     def _table(self, statement: SQLStatement):
         tok = statement.next()
@@ -538,26 +519,20 @@ class AlterQuery(DDLQuery):
                 raise SQLDecodeError
 
     def _drop_index(self):
-        self.db[self.left_table].drop_index(self._iden_name)
+        self.connection.drop_index(self.left_table, self._iden_name)
 
     def _drop_column(self):
-        self.db[self.left_table].update(
-            {},
-            {
-                '$unset': {
-                    self._iden_name: ''
-                }
-            },
-            multi=True
-        )
-        self.db['__schema__'].update(
-            {'name': self.left_table},
-            {
-                '$unset': {
-                    f'fields.{self._iden_name}': ''
-                }
-            }
-        )
+        print_warn("DROP COLUMN")
+        # self.connection.update(
+            # self.left_table,
+            # {},
+            # {
+                # '$unset': {
+                    # self._iden_name: ''
+                # }
+            # },
+            # multi=True
+        # )
 
     def _add(self, statement: SQLStatement):
         for tok in statement:
@@ -610,7 +585,8 @@ class AlterQuery(DDLQuery):
                                      err_sub_sql=statement)
 
     def _add_column(self):
-        self.db[self.left_table].update(
+        self.connection.update(
+            self.left_table,
             {
                 '$or': [
                     {self._iden_name: {'$exists': False}},
@@ -624,7 +600,8 @@ class AlterQuery(DDLQuery):
             },
             multi=True
         )
-        self.db['__schema__'].update(
+        self.connection.update(
+            '__schema__',
             {'name': self.left_table},
             {
                 '$set': {
@@ -636,15 +613,13 @@ class AlterQuery(DDLQuery):
         )
 
     def _index(self):
-        self.db[self.left_table].create_index(
+        self.connection.create_index(
+            self.left_table,
             self.field_dir,
             name=self._iden_name)
 
     def _unique(self):
-        self.db[self.left_table].create_index(
-            self.field_dir,
-            unique=True,
-            name=self._iden_name)
+        print_warn("UNIQUE INDEX")
 
     def _fk(self):
         pass
@@ -655,25 +630,9 @@ class CreateQuery(DDLQuery):
     def __init__(self, *args):
         super().__init__(*args)
 
-    def _create_table(self, statement):
-        if '__schema__' not in self.connection_properties.cached_collections:
-            self.db.create_collection('__schema__')
-            self.connection_properties.cached_collections.add('__schema__')
-            self.db['__schema__'].create_index('name', unique=True)
-            self.db['__schema__'].create_index('auto')
-
+    def _create_record_type(self, statement):
         tok = statement.next()
-        table = SQLToken.token2sql(tok, self).table
-        try:
-            self.db.create_collection(table)
-        # except CollectionInvalid:
-        except CaosDBException as e:
-            if self.connection_properties.enforce_schema:
-                raise
-            else:
-                return
-
-        logger.debug('Created table: {}'.format(table))
+        record_type = SQLToken.token2sql(tok, self).table
 
         tok = statement.next()
         if not isinstance(tok, Parenthesis):
@@ -684,61 +643,42 @@ class CreateQuery(DDLQuery):
             raise SQLDecodeError(f'Unexpected sql syntax'
                                  f' for column definition: {statement}')
 
-        _filter = {
-            'name': table
-        }
-        _set = {}
-        push = {}
-        update = {}
-
+        # collect properties
+        properties = []
         for col in SQLColumnDef.sql2col_defs(tok.value):
             if isinstance(col, SQLColumnConstraint):
                 print_warn('column CONSTRAINTS')
             else:
                 field = col.name
-                if field == '_id':
+                if field in ['id', "name", "description"]:
                     continue
 
-                _set[f'fields.{field}'] = {
-                    'type_code': col.data_type
-                }
+                properties.append({"name": field,
+                                   "datatype": col.data_type
+                                  })
 
                 if SQLColumnDef.autoincrement in col.col_constraints:
-                    try:
-                        push['auto.field_names']['$each'].append(field)
-                    except KeyError:
-                        push['auto.field_names'] = {
-                            '$each': [field]
-                        }
-                    _set['auto.seq'] = 0
+                    print_warn("AUTO INCREMENT")
 
                 if SQLColumnDef.primarykey in col.col_constraints:
-                    self.db[table].create_index(field, unique=True, name='__primary_key__')
+                    print_warn("PRIMARY KEY other than id")
 
                 if SQLColumnDef.unique in col.col_constraints:
-                    self.db[table].create_index(field, unique=True)
+                    print_warn("UNIQUE INDEX")
 
                 if (SQLColumnDef.not_null in col.col_constraints or
                         SQLColumnDef.null in col.col_constraints):
                     print_warn('NULL, NOT NULL column validation check')
 
-        if _set:
-            update['$set'] = _set
-        if push:
-            update['$push'] = push
-        if update:
-            self.db['__schema__'].update_one(
-                filter=_filter,
-                update=update,
-                upsert=True
-            )
+        self.connection.create_record_type(record_type, properties)
+        logger.debug('Created record_type: {}'.format(record_type))
 
     def parse(self):
         statement = SQLStatement(self.statement)
         statement.skip(2)
         tok = statement.next()
         if tok.match(tokens.Keyword, 'TABLE'):
-            self._create_table(statement)
+            self._create_record_type(statement)
         elif tok.match(tokens.Keyword, 'DATABASE'):
             pass
         else:
@@ -766,7 +706,7 @@ class DeleteQuery(DMLQuery):
             kw.update(where.to_mongo())
 
     def execute(self):
-        db_con = self.db
+        db_con = self.connection
         self.result = db_con[self.left_table].delete_many(**self.kw)
         logger.debug('delete_many: {}'.format(self.result.deleted_count))
 
@@ -777,16 +717,12 @@ class DeleteQuery(DMLQuery):
 class Query:
 
     def __init__(self,
-                 client_connection: CaosDBClient,
-                 db_connection: str,
-                 connection_properties: 'base.DjongoClient',
+                 connection: 'caosdb_client.CaosDBClient',
                  sql: str,
                  params: Optional[Sequence]):
 
         self._params = params
-        self.db = db_connection
-        self.cli_con = client_connection
-        self.connection_properties = connection_properties
+        self.connection = connection
         self._params_index_count = -1
         self._sql = re.sub(r'%s', self._param_index, sql)
         self.last_row_id = None
@@ -899,7 +835,7 @@ class Query:
 
     def _alter(self, sm):
         try:
-            query = AlterQuery(self.db, self.connection_properties, sm, self._params)
+            query = AlterQuery(self.connection, sm, self._params)
         except SQLDecodeError:
             logger.warning('Not implemented alter command for SQL {}'.format(self._sql))
             raise
@@ -908,7 +844,7 @@ class Query:
             return query
 
     def _create(self, sm):
-        query = CreateQuery(self.db, self.connection_properties, sm, self._params)
+        query = CreateQuery(self.connection, sm, self._params)
         query.execute()
         return query
 
@@ -923,27 +859,27 @@ class Query:
         elif tok.match(tokens.Keyword, 'TABLE'):
             tok = statement.next()
             table_name = tok.get_name()
-            self.db.drop_collection(table_name)
+            self.connection.drop_record_type(table_name)
         else:
             raise SQLDecodeError('statement:{}'.format(sm))
 
     def _update(self, sm):
-        query = UpdateQuery(self.db, self.connection_properties, sm, self._params)
+        query = UpdateQuery(self.connection, sm, self._params)
         query.execute()
         return query
 
     def _delete(self, sm):
-        query = DeleteQuery(self.db, self.connection_properties, sm, self._params)
+        query = DeleteQuery(self.connection, sm, self._params)
         query.execute()
         return query
 
     def _insert(self, sm):
-        query = InsertQuery(self, self.db, self.connection_properties, sm, self._params)
+        query = InsertQuery(self, self.connection, sm, self._params)
         query.execute()
         return query
 
     def _select(self, sm):
-        return SelectQuery(self.db, self.connection_properties, sm, self._params)
+        return SelectQuery(self.connection, sm, self._params)
 
     FUNC_MAP = {
         'SELECT': _select,
diff --git a/tests/djongo_tests/test_project/test_project/settings/__init__.py b/example/djaosdb_test/__init__.py
similarity index 100%
rename from tests/djongo_tests/test_project/test_project/settings/__init__.py
rename to example/djaosdb_test/__init__.py
diff --git a/example/djaosdb_test/settings.py b/example/djaosdb_test/settings.py
new file mode 100644
index 0000000..30388c4
--- /dev/null
+++ b/example/djaosdb_test/settings.py
@@ -0,0 +1,165 @@
+"""
+Django settings for djaosdb_test project.
+
+Generated by 'django-admin startproject' using Django 2.2.16.
+
+For more information on this file, see
+https://docs.djangoproject.com/en/2.2/topics/settings/
+
+For the full list of settings and their values, see
+https://docs.djangoproject.com/en/2.2/ref/settings/
+"""
+
+import os
+
+# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
+BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+
+
+# Quick-start development settings - unsuitable for production
+# See https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/
+
+# SECURITY WARNING: keep the secret key used in production secret!
+SECRET_KEY = 'bvye0b*i%_m(ec_qmlc0(t#fy+&z&#-kzljb36yh&^hzjz(b+n'
+
+# SECURITY WARNING: don't run with debug turned on in production!
+DEBUG = True
+
+ALLOWED_HOSTS = []
+
+
+# Application definition
+
+INSTALLED_APPS = [
+    "simple_test",
+    # 'django.contrib.admin',
+    # 'django.contrib.auth',
+    'django.contrib.contenttypes',
+    # 'django.contrib.sessions',
+    # 'django.contrib.messages',
+    # 'django.contrib.staticfiles',
+]
+
+MIDDLEWARE = [
+    # 'django.middleware.security.SecurityMiddleware',
+    # 'django.contrib.sessions.middleware.SessionMiddleware',
+    # 'django.middleware.common.CommonMiddleware',
+    # 'django.middleware.csrf.CsrfViewMiddleware',
+    # 'django.contrib.auth.middleware.AuthenticationMiddleware',
+    # 'django.contrib.messages.middleware.MessageMiddleware',
+    # 'django.middleware.clickjacking.XFrameOptionsMiddleware',
+]
+
+LOGGING = {
+    'version': 1,
+    'disable_existing_loggers': False,
+    'handlers': {
+        'console': {
+            'class': 'logging.StreamHandler',
+            'formatter': "verbose",
+        },
+    },
+    'formatters': {
+        'verbose': {
+            'format': '[{levelname}]({module}) {message}',
+            'style': '{',
+        },
+    },
+    'root': {
+        'handlers': ['console'],
+        'level': 'INFO',
+    },
+    'loggers': {
+        'django': {
+            'handlers': ['console'],
+            'level': os.getenv('DJANGO_LOG_LEVEL', 'INFO'),
+            'propagate': False,
+        },
+        'djaosdb': {
+            'handlers': ['console'],
+            'level': os.getenv('DJAOSDB_LOG_LEVEL', 'DEBUG'),
+            'propagate': False,
+        }
+    },
+}
+
+ROOT_URLCONF = 'djaosdb_test.urls'
+
+TEMPLATES = [
+    {
+        'BACKEND': 'django.template.backends.django.DjangoTemplates',
+        'DIRS': [],
+        'APP_DIRS': True,
+        # 'OPTIONS': {
+            # 'context_processors': [
+                # 'django.template.context_processors.debug',
+                # 'django.template.context_processors.request',
+                # 'django.contrib.auth.context_processors.auth',
+                # 'django.contrib.messages.context_processors.messages',
+            # ],
+        # },
+    },
+]
+
+WSGI_APPLICATION = 'djaosdb_test.wsgi.application'
+
+
+# Database
+# https://docs.djangoproject.com/en/2.2/ref/settings/#databases
+
+DATABASES = {
+    'default': {
+        'ENGINE': 'djaosdb',
+        'CLIENT': {
+            'url': 'https://localhost:10443',
+            'password_method': "plain",
+            'username': "admin",
+            "password": "caosdb",
+#            'authSource': 'admin',
+        },
+        'ENFORCE_SCHEMA': True
+    },
+    # 'default': {
+        # 'ENGINE': 'django.db.backends.sqlite3',
+        # 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
+    # }
+}
+
+
+# Password validation
+# https://docs.djangoproject.com/en/2.2/ref/settings/#auth-password-validators
+
+# AUTH_PASSWORD_VALIDATORS = [
+    # {
+        # 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
+    # },
+    # {
+        # 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
+    # },
+    # {
+        # 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
+    # },
+    # {
+        # 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
+    # },
+# ]
+
+
+# Internationalization
+# https://docs.djangoproject.com/en/2.2/topics/i18n/
+
+# LANGUAGE_CODE = 'en-us'
+
+# TIME_ZONE = 'UTC'
+
+# USE_I18N = True
+
+# USE_L10N = True
+
+# USE_TZ = True
+
+
+# Static files (CSS, JavaScript, Images)
+# https://docs.djangoproject.com/en/2.2/howto/static-files/
+
+# STATIC_URL = '/static/'
diff --git a/example/djaosdb_test/urls.py b/example/djaosdb_test/urls.py
new file mode 100644
index 0000000..47e7411
--- /dev/null
+++ b/example/djaosdb_test/urls.py
@@ -0,0 +1,21 @@
+"""djaosdb_test URL Configuration
+
+The `urlpatterns` list routes URLs to views. For more information please see:
+    https://docs.djangoproject.com/en/2.2/topics/http/urls/
+Examples:
+Function views
+    1. Add an import:  from my_app import views
+    2. Add a URL to urlpatterns:  path('', views.home, name='home')
+Class-based views
+    1. Add an import:  from other_app.views import Home
+    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
+Including another URLconf
+    1. Import the include() function: from django.urls import include, path
+    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
+"""
+#from django.contrib import admin
+from django.urls import path, include
+
+urlpatterns = [
+    path('simple_test/', include('simple_test.urls')),
+]
diff --git a/example/djaosdb_test/wsgi.py b/example/djaosdb_test/wsgi.py
new file mode 100644
index 0000000..d823842
--- /dev/null
+++ b/example/djaosdb_test/wsgi.py
@@ -0,0 +1,16 @@
+"""
+WSGI config for djaosdb_test project.
+
+It exposes the WSGI callable as a module-level variable named ``application``.
+
+For more information on this file, see
+https://docs.djangoproject.com/en/2.2/howto/deployment/wsgi/
+"""
+
+import os
+
+from django.core.wsgi import get_wsgi_application
+
+os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'djaosdb_test.settings')
+
+application = get_wsgi_application()
diff --git a/example/manage.py b/example/manage.py
new file mode 100755
index 0000000..1be2f33
--- /dev/null
+++ b/example/manage.py
@@ -0,0 +1,21 @@
+#!/usr/bin/env python
+"""Django's command-line utility for administrative tasks."""
+import os
+import sys
+
+
+def main():
+    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'djaosdb_test.settings')
+    try:
+        from django.core.management import execute_from_command_line
+    except ImportError as exc:
+        raise ImportError(
+            "Couldn't import Django. Are you sure it's installed and "
+            "available on your PYTHONPATH environment variable? Did you "
+            "forget to activate a virtual environment?"
+        ) from exc
+    execute_from_command_line(sys.argv)
+
+
+if __name__ == '__main__':
+    main()
diff --git a/example/simple_test/__init__.py b/example/simple_test/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/example/simple_test/admin.py b/example/simple_test/admin.py
new file mode 100644
index 0000000..8c38f3f
--- /dev/null
+++ b/example/simple_test/admin.py
@@ -0,0 +1,3 @@
+from django.contrib import admin
+
+# Register your models here.
diff --git a/example/simple_test/apps.py b/example/simple_test/apps.py
new file mode 100644
index 0000000..a1c4fbd
--- /dev/null
+++ b/example/simple_test/apps.py
@@ -0,0 +1,5 @@
+from django.apps import AppConfig
+
+
+class SimpleTestConfig(AppConfig):
+    name = 'simple_test'
diff --git a/example/simple_test/models.py b/example/simple_test/models.py
new file mode 100644
index 0000000..aeb697c
--- /dev/null
+++ b/example/simple_test/models.py
@@ -0,0 +1,10 @@
+from django.db import models
+
+class TestRecordType(models.Model):
+    id = models.CharField(primary_key=True, max_length=100, default=None)
+    name = models.CharField(max_length=100, default=None)
+    description = models.CharField(max_length=100, default=None)
+    prop1 = models.CharField(max_length=100, default=None)
+
+    class Meta:
+        db_table = "TestRecordType"
diff --git a/example/simple_test/templates/testrt/create.html b/example/simple_test/templates/testrt/create.html
new file mode 100644
index 0000000..256405a
--- /dev/null
+++ b/example/simple_test/templates/testrt/create.html
@@ -0,0 +1,4 @@
+<form method="post">{% csrf_token %}
+    {{ form.as_p }}
+    <input type="submit" value="Save">
+</form>
diff --git a/example/simple_test/templates/testrt/detail.html b/example/simple_test/templates/testrt/detail.html
new file mode 100644
index 0000000..6feb3da
--- /dev/null
+++ b/example/simple_test/templates/testrt/detail.html
@@ -0,0 +1,7 @@
+<h1>TestRecordType</h1>
+<dl>
+  <dt>id</dt><dd>{{ testrt.id }}</dd>
+  <dt>name</dt><dd>{{ testrt.name}}</dd>
+  <dt>description</dt><dd>{{ testrt.description }}</dd>
+  <dt>prop1</dt><dd>{{ testrt.prop1 }}</dd>
+</dl>
diff --git a/example/simple_test/tests.py b/example/simple_test/tests.py
new file mode 100644
index 0000000..7ce503c
--- /dev/null
+++ b/example/simple_test/tests.py
@@ -0,0 +1,3 @@
+from django.test import TestCase
+
+# Create your tests here.
diff --git a/example/simple_test/urls.py b/example/simple_test/urls.py
new file mode 100644
index 0000000..d925a43
--- /dev/null
+++ b/example/simple_test/urls.py
@@ -0,0 +1,7 @@
+from django.urls import path
+from .views import ViewTestRT, CreateTestRT
+
+urlpatterns = [
+    path("<int:pk>", ViewTestRT.as_view(), name="detail"),
+    path("create", CreateTestRT.as_view(), name="create"),
+]
diff --git a/example/simple_test/views.py b/example/simple_test/views.py
new file mode 100644
index 0000000..64bca1d
--- /dev/null
+++ b/example/simple_test/views.py
@@ -0,0 +1,14 @@
+from django.views.generic import DetailView
+from django.views.generic.edit import CreateView
+
+from .models import TestRecordType
+
+class ViewTestRT(DetailView):
+    model = TestRecordType
+    template_name = 'testrt/detail.html'
+    context_object_name = "testrt"
+
+class CreateTestRT(CreateView):
+    model = TestRecordType
+    template_name = 'testrt/create.html'
+    fields = ["name", "description", "prop1"]
diff --git a/setup.py b/setup.py
index 8ac0cbd..ada86ff 100644
--- a/setup.py
+++ b/setup.py
@@ -81,9 +81,9 @@ def find_version(*file_paths):
 
 
 install_requires = [
-    'sqlparse==0.2.4',
+    'sqlparse>=0.2.4',
     'caosdb>=0.4.0',
-    'django>=2.1,<=3.0.5',
+    'django>=2.1',
 ]
 
 if sys.version_info.major == 3 and sys.version_info.minor < 7:
diff --git a/tests/djongo_tests/test_project/djongo-test b/tests/djongo_tests/test_project/djongo-test
deleted file mode 100644
index f8130afd9ed4b72044218c38a3b4775ef8e38c7d..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 188416
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
L5Eu=C;T-}18<|;w

diff --git a/tests/djongo_tests/test_project/manage.py b/tests/djongo_tests/test_project/manage.py
index 2f01bb3..66550c0 100644
--- a/tests/djongo_tests/test_project/manage.py
+++ b/tests/djongo_tests/test_project/manage.py
@@ -5,7 +5,7 @@ import sys
 
 if __name__ == "__main__":
 
-    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "test_project.settings.settings_loaded")
+    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "test_project.settings")
     try:
         from django.core.management import execute_from_command_line
     except ImportError:
diff --git a/tests/djongo_tests/test_project/simple/__init__.py b/tests/djongo_tests/test_project/simple/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/djongo_tests/test_project/simple/apps.py b/tests/djongo_tests/test_project/simple/apps.py
new file mode 100644
index 0000000..d392200
--- /dev/null
+++ b/tests/djongo_tests/test_project/simple/apps.py
@@ -0,0 +1,5 @@
+from django.apps import AppConfig
+
+
+class XtestAppConfig(AppConfig):
+    name = 'xtest_app'
diff --git a/tests/djongo_tests/test_project/simple/models/basic.py b/tests/djongo_tests/test_project/simple/models/basic.py
new file mode 100644
index 0000000..fe8538e
--- /dev/null
+++ b/tests/djongo_tests/test_project/simple/models/basic.py
@@ -0,0 +1,8 @@
+from djaosdb import models
+
+
+class TestRecordType(models.Model):
+    _id = models.ObjectIdField()
+    name = models.TextField()
+    description = models.TextField()
+    testProperty1 = models.TextField()
diff --git a/tests/djongo_tests/test_project/test_project/settings/settings_loaded.py b/tests/djongo_tests/test_project/test_project/settings.py
similarity index 65%
rename from tests/djongo_tests/test_project/test_project/settings/settings_loaded.py
rename to tests/djongo_tests/test_project/test_project/settings.py
index 8a89f09..05c2e3d 100644
--- a/tests/djongo_tests/test_project/test_project/settings/settings_loaded.py
+++ b/tests/djongo_tests/test_project/test_project/settings.py
@@ -15,26 +15,49 @@ import os
 # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
 
-
 # Quick-start development settings - unsuitable for production
 # See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/
 
-# SECURITY WARNING: keep the secret key used in production secret!
-SECRET_KEY = '5s(0&1x3(963q!xdyt1=$^(5om4(_=_39ys6=bnp7n-h8%7z+('
-
 # SECURITY WARNING: don't run with debug turned on in production!
 DEBUG = True
 
+LOGGING = {
+    'version': 1,
+    'disable_existing_loggers': False,
+    'handlers': {
+        'console': {
+            'class': 'logging.StreamHandler',
+            'formatter': "verbose",
+        },
+    },
+    'formatters': {
+        'verbose': {
+            'format': '[{levelname}]({module}) {message}',
+            'style': '{',
+        },
+    },
+    'root': {
+        'handlers': ['console'],
+        'level': 'INFO',
+    },
+    'loggers': {
+        'django': {
+            'handlers': ['console'],
+            'level': os.getenv('DJANGO_LOG_LEVEL', 'INFO'),
+            'propagate': False,
+        },
+    },
+}
+
 ALLOWED_HOSTS = ['localhost', '127.0.0.1']
 
 DATABASES = {
     'default': {
         'ENGINE': 'djaosdb',
-        'NAME': 'djaosdb-test',
         'CLIENT': {
             'host': 'localhost',
             'port': 10443,
-            'authSource': 'admin',
+#            'authSource': 'admin',
         },
         'ENFORCE_SCHEMA': True
     },
@@ -42,25 +65,25 @@ DATABASES = {
 # Application definition
 
 INSTALLED_APPS = [
-    'xtest_app.apps.XtestAppConfig',
-    'djaosdb.dynamic_formsets.apps.DynamicFormsetsConfig',
-    'django.contrib.admin',
-    'django.contrib.auth',
-    'django.contrib.contenttypes',
-    'django.contrib.sessions',
-    'django.contrib.messages',
+    'simple.apps',
+#    'djaosdb.dynamic_formsets.apps.DynamicFormsetsConfig',
+#    'django.contrib.admin',
+#    'django.contrib.auth',
+#    'django.contrib.contenttypes',
+#    'django.contrib.sessions',
+#    'django.contrib.messages',
     'django.contrib.staticfiles',
 ]
 
 
 MIDDLEWARE = [
-    'django.middleware.security.SecurityMiddleware',
-    'django.contrib.sessions.middleware.SessionMiddleware',
-    'django.middleware.common.CommonMiddleware',
-    'django.middleware.csrf.CsrfViewMiddleware',
-    'django.contrib.auth.middleware.AuthenticationMiddleware',
-    'django.contrib.messages.middleware.MessageMiddleware',
-    'django.middleware.clickjacking.XFrameOptionsMiddleware',
+#    'django.middleware.security.SecurityMiddleware',
+#    'django.contrib.sessions.middleware.SessionMiddleware',
+#    'django.middleware.common.CommonMiddleware',
+#    'django.middleware.csrf.CsrfViewMiddleware',
+#    'django.contrib.auth.middleware.AuthenticationMiddleware',
+#    'django.contrib.messages.middleware.MessageMiddleware',
+#    'django.middleware.clickjacking.XFrameOptionsMiddleware',
 ]
 
 ROOT_URLCONF = 'test_project.urls.urls_loaded'
diff --git a/tests/djongo_tests/test_project/test_project/settings/settings_lite.py b/tests/djongo_tests/test_project/test_project/settings/settings_lite.py
deleted file mode 100644
index e020677..0000000
--- a/tests/djongo_tests/test_project/test_project/settings/settings_lite.py
+++ /dev/null
@@ -1,130 +0,0 @@
-"""
-Django settings for main_test_app project.
-
-Generated by 'django-admin startproject' using Django 1.11.2.
-
-For more information on this file, see
-https://docs.djangoproject.com/en/1.11/topics/settings/
-
-For the full list of settings and their values, see
-https://docs.djangoproject.com/en/1.11/ref/settings/
-"""
-
-import os, sys
-# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
-BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
-
-
-# Quick-start development settings - unsuitable for production
-# See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/
-
-# SECURITY WARNING: keep the secret key used in production secret!
-SECRET_KEY = '5s(0&1x3(963q!xdyt1=$^(5om4(_=_39ys6=bnp7n-h8%7z+('
-
-# SECURITY WARNING: don't run with debug turned on in production!
-DEBUG = True
-
-ALLOWED_HOSTS = ['localhost','127.0.0.1']
-
-DATABASES = {
-    'default': {
-        'ENGINE': 'djaosdb',
-        'NAME': 'djaosdb-test',
-        'ENFORCE_SCHEMA': False,
-        'LOGGING': {
-            'version': 1,
-            'loggers': {
-                'djaosdb': {
-                    'level': 'DEBUG',
-                    'propagate': False,
-                    'handlers': ['console']
-                }
-            },
-            'handlers': {
-                'console': {
-                    'class': 'logging.StreamHandler',
-                    'level': 'DEBUG',
-                    'stream': sys.stdout
-                }
-            }
-        }
-    },
-}
-# Application definition
-
-INSTALLED_APPS = [
-    'xtest_app.apps.XtestAppConfig',
-]
-
-
-MIDDLEWARE = [
-    # 'django.middleware.security.SecurityMiddleware',
-    # 'django.contrib.sessions.middleware.SessionMiddleware',
-    # 'django.middleware.common.CommonMiddleware',
-    # 'django.middleware.csrf.CsrfViewMiddleware',
-    # 'django.contrib.auth.middleware.AuthenticationMiddleware',
-    # 'django.contrib.messages.middleware.MessageMiddleware',
-    # 'django.middleware.clickjacking.XFrameOptionsMiddleware',
-]
-
-ROOT_URLCONF = 'test_project.urls.urls_lite'
-
-TEMPLATES = [
-    {
-        'BACKEND': 'django.template.backends.django.DjangoTemplates',
-        'DIRS': [],
-        'APP_DIRS': True,
-        'OPTIONS': {
-            'context_processors': [
-                'django.template.context_processors.debug',
-                'django.template.context_processors.request',
-                'django.contrib.auth.context_processors.auth',
-                'django.contrib.messages.context_processors.messages',
-            ],
-        },
-    },
-]
-
-WSGI_APPLICATION = 'test_project.wsgi.application'
-
-
-
-# Password validation
-# https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators
-
-AUTH_PASSWORD_VALIDATORS = [
-    {
-        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
-    },
-    {
-        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
-    },
-    {
-        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
-    },
-    {
-        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
-    },
-]
-
-
-# Internationalization
-# https://docs.djangoproject.com/en/1.11/topics/i18n/
-
-LANGUAGE_CODE = 'en-us'
-
-TIME_ZONE = 'UTC'
-
-USE_I18N = True
-
-USE_L10N = True
-
-USE_TZ = True
-
-
-# Static files (CSS, JavaScript, Images)
-# https://docs.djangoproject.com/en/1.11/howto/static-files/
-
-STATIC_URL = '/static/'
-
-STATIC_ROOT = os.path.join(BASE_DIR, 'static')
\ No newline at end of file
diff --git a/tests/djongo_tests/test_project/test_project/settings/settings_loaded_formsets.py b/tests/djongo_tests/test_project/test_project/settings/settings_loaded_formsets.py
deleted file mode 100644
index 702ca94..0000000
--- a/tests/djongo_tests/test_project/test_project/settings/settings_loaded_formsets.py
+++ /dev/null
@@ -1,125 +0,0 @@
-"""
-Django settings for main_test_app project.
-
-Generated by 'django-admin startproject' using Django 1.11.2.
-
-For more information on this file, see
-https://docs.djangoproject.com/en/1.11/topics/settings/
-
-For the full list of settings and their values, see
-https://docs.djangoproject.com/en/1.11/ref/settings/
-"""
-
-import os
-
-# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
-BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
-
-
-# Quick-start development settings - unsuitable for production
-# See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/
-
-# SECURITY WARNING: keep the secret key used in production secret!
-SECRET_KEY = '5s(0&1x3(963q!xdyt1=$^(5om4(_=_39ys6=bnp7n-h8%7z+('
-
-# SECURITY WARNING: don't run with debug turned on in production!
-DEBUG = True
-
-ALLOWED_HOSTS = ['localhost','127.0.0.1']
-
-DATABASES = {
-    'default': {
-        'ENGINE': 'djaosdb',
-        'NAME': 'djaosdb-test',
-        # 'USER': 'user',
-        # 'PASSWORD': 'passpass',
-        # 'AUTH_SOURCE': 'djaosdb-test',
-        'ENFORCE_SCHEMA': True
-
-    },
-}
-# Application definition
-
-INSTALLED_APPS = [
-    'xtest_app.apps.XtestAppConfig',
-    'djaosdb.dynamic_formsets.apps.DynamicFormsetsConfig',
-    'django.contrib.admin',
-    'django.contrib.auth',
-    'django.contrib.contenttypes',
-    'django.contrib.sessions',
-    'django.contrib.messages',
-    'django.contrib.staticfiles',
-]
-
-
-MIDDLEWARE = [
-    'django.middleware.security.SecurityMiddleware',
-    'django.contrib.sessions.middleware.SessionMiddleware',
-    'django.middleware.common.CommonMiddleware',
-    'django.middleware.csrf.CsrfViewMiddleware',
-    'django.contrib.auth.middleware.AuthenticationMiddleware',
-    'django.contrib.messages.middleware.MessageMiddleware',
-    'django.middleware.clickjacking.XFrameOptionsMiddleware',
-]
-
-ROOT_URLCONF = 'test_project.urls.urls_loaded'
-
-TEMPLATES = [
-    {
-        'BACKEND': 'django.template.backends.django.DjangoTemplates',
-        'DIRS': [],
-        'APP_DIRS': True,
-        'OPTIONS': {
-            'context_processors': [
-                'django.template.context_processors.debug',
-                'django.template.context_processors.request',
-                'django.contrib.auth.context_processors.auth',
-                'django.contrib.messages.context_processors.messages',
-            ],
-        },
-    },
-]
-
-WSGI_APPLICATION = 'test_project.wsgi.application'
-
-
-
-# Password validation
-# https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators
-
-AUTH_PASSWORD_VALIDATORS = [
-    {
-        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
-    },
-    {
-        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
-    },
-    {
-        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
-    },
-    {
-        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
-    },
-]
-
-
-# Internationalization
-# https://docs.djangoproject.com/en/1.11/topics/i18n/
-
-LANGUAGE_CODE = 'en-us'
-
-TIME_ZONE = 'UTC'
-
-USE_I18N = True
-
-USE_L10N = True
-
-USE_TZ = True
-
-
-# Static files (CSS, JavaScript, Images)
-# https://docs.djangoproject.com/en/1.11/howto/static-files/
-
-STATIC_URL = '/static/'
-
-STATIC_ROOT = os.path.join(BASE_DIR, 'static')
\ No newline at end of file
diff --git a/tests/djongo_tests/test_project/test_project/settings/settings_precheckin.py b/tests/djongo_tests/test_project/test_project/settings/settings_precheckin.py
deleted file mode 100644
index c777dd0..0000000
--- a/tests/djongo_tests/test_project/test_project/settings/settings_precheckin.py
+++ /dev/null
@@ -1,121 +0,0 @@
-"""
-Django settings for main_test_app project.
-
-Generated by 'django-admin startproject' using Django 1.11.2.
-
-For more information on this file, see
-https://docs.djangoproject.com/en/1.11/topics/settings/
-
-For the full list of settings and their values, see
-https://docs.djangoproject.com/en/1.11/ref/settings/
-"""
-
-import os
-
-# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
-BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
-
-
-# Quick-start development settings - unsuitable for production
-# See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/
-
-# SECURITY WARNING: keep the secret key used in production secret!
-SECRET_KEY = '5s(0&1x3(963q!xdyt1=$^(5om4(_=_39ys6=bnp7n-h8%7z+('
-
-# SECURITY WARNING: don't run with debug turned on in production!
-DEBUG = True
-
-ALLOWED_HOSTS = ['localhost','127.0.0.1']
-
-DATABASES = {
-    'default': {
-        'ENGINE': 'djaosdb',
-        'NAME': 'djaosdb-test',
-        'ENFORCE_SCHEMA': False
-
-    },
-}
-# Application definition
-
-INSTALLED_APPS = [
-    'xtest_app.apps.XtestAppConfig',
-    'django.contrib.admin',
-    'django.contrib.auth',
-    'django.contrib.contenttypes',
-    'django.contrib.sessions',
-    'django.contrib.messages',
-    'django.contrib.staticfiles',
-]
-
-
-MIDDLEWARE = [
-    'django.middleware.security.SecurityMiddleware',
-    'django.contrib.sessions.middleware.SessionMiddleware',
-    'django.middleware.common.CommonMiddleware',
-    'django.middleware.csrf.CsrfViewMiddleware',
-    'django.contrib.auth.middleware.AuthenticationMiddleware',
-    'django.contrib.messages.middleware.MessageMiddleware',
-    'django.middleware.clickjacking.XFrameOptionsMiddleware',
-]
-
-ROOT_URLCONF = 'test_project.urls.urls_lite'
-
-TEMPLATES = [
-    {
-        'BACKEND': 'django.template.backends.django.DjangoTemplates',
-        'DIRS': [],
-        'APP_DIRS': True,
-        'OPTIONS': {
-            'context_processors': [
-                'django.template.context_processors.debug',
-                'django.template.context_processors.request',
-                'django.contrib.auth.context_processors.auth',
-                'django.contrib.messages.context_processors.messages',
-            ],
-        },
-    },
-]
-
-WSGI_APPLICATION = 'test_project.wsgi.application'
-
-
-
-# Password validation
-# https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators
-
-AUTH_PASSWORD_VALIDATORS = [
-    {
-        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
-    },
-    {
-        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
-    },
-    {
-        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
-    },
-    {
-        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
-    },
-]
-
-
-# Internationalization
-# https://docs.djangoproject.com/en/1.11/topics/i18n/
-
-LANGUAGE_CODE = 'en-us'
-
-TIME_ZONE = 'UTC'
-
-USE_I18N = True
-
-USE_L10N = True
-
-USE_TZ = True
-
-
-# Static files (CSS, JavaScript, Images)
-# https://docs.djangoproject.com/en/1.11/howto/static-files/
-
-STATIC_URL = '/static/'
-
-STATIC_ROOT = os.path.join(BASE_DIR, 'static')
\ No newline at end of file
diff --git a/tests/djongo_tests/test_project/test_project/urls/urls_loaded.py b/tests/djongo_tests/test_project/test_project/urls/urls_loaded.py
index 3c436e8..3713b70 100644
--- a/tests/djongo_tests/test_project/test_project/urls/urls_loaded.py
+++ b/tests/djongo_tests/test_project/test_project/urls/urls_loaded.py
@@ -14,8 +14,8 @@ Including another URLconf
     2. Add a URL to urlpatterns:  url(r'^blog/', include('blog.urls'))
 """
 from django.conf.urls import url
-from django.contrib import admin
+#from django.contrib import admin
 
 urlpatterns = [
-     url(r'^admin/', admin.site.urls),
+#     url(r'^admin/', admin.site.urls),
 ]
diff --git a/tests/djongo_tests/test_project/xtest_app/admin.py b/tests/djongo_tests/test_project/xtest_app/admin.py
index c2282ae..200dd0f 100644
--- a/tests/djongo_tests/test_project/xtest_app/admin.py
+++ b/tests/djongo_tests/test_project/xtest_app/admin.py
@@ -1,15 +1,15 @@
-from django.contrib import admin
+#from django.contrib import admin
 
-from xtest_app.models.admin_tests import ArrayFieldEntry as ArrayEntry
-from xtest_app.models.basic_field import BasicRelatedEntry, BasicAuthor, BasicBlog, EmbeddedFieldEntry as EmbeddedEntry
+#from xtest_app.models.admin_tests import ArrayFieldEntry as ArrayEntry
+#from xtest_app.models.basic_field import BasicRelatedEntry, BasicAuthor, BasicBlog, EmbeddedFieldEntry as EmbeddedEntry
 
 # from xtest_app.models.reference_field import ReferenceEntry, ReferenceAuthor
 
-admin.site.register(BasicAuthor)
-admin.site.register(BasicBlog)
-admin.site.register(ArrayEntry)
+#admin.site.register(BasicAuthor)
+#admin.site.register(BasicBlog)
+#admin.site.register(ArrayEntry)
 
-admin.site.register(BasicRelatedEntry)
+#admin.site.register(BasicRelatedEntry)
 # admin.site.register(EmbeddedEntry)
 # admin.site.register(EmbeddedDateEntry)
 # admin.site.register(ReferenceEntry)
-- 
GitLab