# -*- coding: utf-8 -*-
###########################################################################
# Copyright (c), The AiiDA team. All rights reserved. #
# This file is part of the AiiDA code. #
# #
# The code is hosted on GitHub at https://github.com/aiidateam/aiida-core #
# For further information on the license, see the LICENSE.txt file #
# For further information please visit http://www.aiida.net #
###########################################################################
"""Django implementation of `aiida.orm.implementation.backends.Backend`."""
from contextlib import contextmanager
# pylint: disable=import-error,no-name-in-module
from django.db import models, transaction
from aiida.backends.djsite.queries import DjangoQueryManager
from aiida.backends.djsite.manager import DjangoBackendManager
from ..sql import SqlBackend
from . import authinfos
from . import comments
from . import computers
from . import convert
from . import groups
from . import logs
from . import nodes
from . import querybuilder
from . import users
__all__ = ('DjangoBackend',)
[docs]class DjangoBackend(SqlBackend[models.Model]):
"""Django implementation of `aiida.orm.implementation.backends.Backend`."""
[docs] def __init__(self):
"""Construct the backend instance by initializing all the collections."""
self._authinfos = authinfos.DjangoAuthInfoCollection(self)
self._comments = comments.DjangoCommentCollection(self)
self._computers = computers.DjangoComputerCollection(self)
self._groups = groups.DjangoGroupCollection(self)
self._logs = logs.DjangoLogCollection(self)
self._nodes = nodes.DjangoNodeCollection(self)
self._query_manager = DjangoQueryManager(self)
self._backend_manager = DjangoBackendManager()
self._users = users.DjangoUserCollection(self)
[docs] def migrate(self):
self._backend_manager.migrate()
@property
def authinfos(self):
return self._authinfos
@property
def comments(self):
return self._comments
@property
def computers(self):
return self._computers
@property
def groups(self):
return self._groups
@property
def logs(self):
return self._logs
@property
def nodes(self):
return self._nodes
@property
def query_manager(self):
return self._query_manager
[docs] def query(self):
return querybuilder.DjangoQueryBuilder(self)
@property
def users(self):
return self._users
[docs] @staticmethod
def transaction():
"""Open a transaction to be used as a context manager."""
return transaction.atomic()
[docs] @staticmethod
def get_session():
"""Return a database session that can be used by the `QueryBuilder` to perform its query.
If there is an exception within the context then the changes will be rolled back and the state will
be as before entering. Transactions can be nested.
:return: an instance of :class:`sqlalchemy.orm.session.Session`
"""
from aiida.backends.djsite import get_scoped_session
return get_scoped_session()
# Below are abstract methods inherited from `aiida.orm.implementation.sql.backends.SqlBackend`
[docs] def get_backend_entity(self, model):
"""Return a `BackendEntity` instance from a `DbModel` instance."""
return convert.get_backend_entity(model, self)
[docs] @contextmanager
def cursor(self):
"""Return a psycopg cursor to be used in a context manager.
:return: a psycopg cursor
:rtype: :class:`psycopg2.extensions.cursor`
"""
try:
yield self.get_connection().cursor()
finally:
pass
[docs] def execute_raw(self, query):
"""Execute a raw SQL statement and return the result.
:param query: a string containing a raw SQL statement
:return: the result of the query
"""
with self.cursor() as cursor:
cursor.execute(query)
results = cursor.fetchall()
return results
[docs] @staticmethod
def get_connection():
"""
Get the Django connection
:return: the django connection
"""
# pylint: disable=import-error,no-name-in-module
from django.db import connection
# For now we just return the global but if we ever support multiple Django backends
# being loaded this should be specific to this backend
return connection