diff --git a/frontend/views.py b/frontend/views.py index 64e3a59..abac806 100644 --- a/frontend/views.py +++ b/frontend/views.py @@ -125,20 +125,37 @@ class UpdateProjectView(ProtectedFormView, SingleObjectMixin): self.success_url = self.success_url + self.project_id + '/update' return super(UpdateProjectView, self).post(request, *args, **kwargs) - """ This form_valid handles the file uploads and triggers a citavi schema import and things. """ def form_valid(self, form, *args, **kwargs): + """ This form_valid handles the file upload. """ original_file = form.files[u'file'] original_filename = str(original_file) - relative_path = default_storage.save('tmp/project_' + self.project_id + '.ctt4', ContentFile(original_file.read())) - path = os.path.join(settings.MEDIA_ROOT, relative_path) - #TODO: Actually validate that we get an SQLite3 file! + """ Put file into temporary folder for analysis """ + relative_path = default_storage.save('tmp/project_' + str(self.project_id) + '.ctt4', ContentFile(original_file.read())) + temp_sqlite = os.path.join(settings.MEDIA_ROOT, relative_path) - # Store this in the project model - project = Project.objects.get(id=self.project_id) - project.associated_filename = original_filename - project.save() + """ Test if SQLite is a valid citavi project. """ + from service import Citavi + citavi_project = Citavi.CitaviProject(temp_sqlite) + citavi_project_valid = citavi_project.is_valid() + """ Free temporary ressources. """ + del citavi_project + default_storage.delete(temp_sqlite) + if citavi_project_valid == False: + """ TODO: Put up an error message or something. """ + pass + else: + """ Actually store file in citavi folder """ + relative_path = default_storage.save('citavi/project_' + str(self.project_id) + '.ctt4', ContentFile(original_file.read())) + sqlite_path = os.path.join(settings.MEDIA_ROOT, relative_path) + + """ Store new original filename in Project """ + project = Project.objects.get(id=self.project_id) + project.associated_filename = original_filename + project.save() + + """ Refresh identities from citavi project. """ + # TODO return super(UpdateProjectView, self).form_valid(form) - - \ No newline at end of file + diff --git a/service/sqlitehelper.py b/service/Citavi.py similarity index 51% rename from service/sqlitehelper.py rename to service/Citavi.py index ad7481a..747b420 100644 --- a/service/sqlitehelper.py +++ b/service/Citavi.py @@ -1,19 +1,87 @@ # -*- coding: utf-8 -*- +from sqlalchemy import create_engine, MetaData +from sqlalchemy.ext.automap import automap_base +from sqlalchemy.orm import Session +class CitaviProject(): + """ A helper class representing a Citavi project. """ + def __init__(self, sqlite_file): + """ Constructor to get absolute path to sqlite. """ + self.sqlite_file = sqlite_file + self._is_open = False + self._is_error = False + self._sa = {} # Object namespace for sqlalchemy related objects + + def __del__(self): + """ Destructor to close the citavi file. """ + self.close() + + def is_valid(self): + """ This method returns False in case the given sqlite file is not a valid Citavi project. """ + self.open() + return self._is_open and not self._is_error + + def get_persons(self): + try: + PersonClass = self._sa_sqlite_autobase.classes.Person + except: + return False + + def open(self): + """ Public method to open a citavi project file. """ + if not self._is_open: + self._open() + + def close(self): + """ Public method to close a citavi project file. """ + if self._is_open: + self._close() + + def _open(self): + """ Internal method to open a citavi project file. """ + try: + self._sa_sqlite_engine = create_engine('sqlite+pysqlite:///' + self.sqlite_file) + self._sa_sqlite_session = Session(self._sa_sqlite_engine) + self._sa_sqlite_meta = MetaData(bind=self._sa_sqlite_engine) + self._sa_sqlite_meta.reflect() + self._sa_sqlite_autobase = automap_base() + self._sa_sqlite_autobase.prepare(self._sa_sqlite_engine, reflect=True) + self._is_open = True + except: + self._is_error = True + self._is_open = False + + def _close(self): + """ Internal method to actually close a citavi project file. """ + try: + del self._sa.sqlite_engine + del self._sa.sqlite_session + del self._sa.sqlite_meta + del self._sa.sqlite_autobase + del self._sa.sqlite_engine + self._is_open = False + except: + self._is_error = True + self._is_open = True + + + + pass + + + + + +""" def import_sqlite(project_id, sqlite_file): print "This is import_sqlite speaking!" print project_id print sqlite_file print "Importing data..." - - from sqlalchemy import * - from sqlalchemy.schema import CreateSchema - from sqlalchemy.ext.automap import automap_base - from sqlalchemy.orm import Session - + # Initialize sqlite part sqlite_engine = create_engine('sqlite+pysqlite:///project_import_9.ctt4', echo=True) sqlite_session = Session(sqlite_engine) @@ -26,11 +94,9 @@ def import_sqlite(project_id, sqlite_file): psql_engine.execute(CreateSchema('alchemytest')) # TODO: Catch Exception/Warning/Whatever here psql_meta = MetaData(bind=psql_engine, schema='alchemytest') - """ # Reflect the origin - maybe psql_meta.reflect() is enough? sqlite_autobase = automap_base() sqlite_autobase.prepare(sqlite_engine, reflect=True) - """ # This small snippet prints python class code for sqlalchemy reflected classes @@ -59,7 +125,6 @@ def import_sqlite(project_id, sqlite_file): #meta.tables['ReferenceAuthor'].select().execute().fetchall() # Now we need to "convert" unsupported types :-/ - """ for table in meta.sorted_tables: table_name = str(table) columns = table.columns.items() @@ -70,10 +135,4 @@ def import_sqlite(project_id, sqlite_file): print table_name + "." + column_name + ': ' + column_type print print - """ - - """ TODO: since DATETIME (sqlite3) does not map onto TIMESTAMP / DATE (postgresql), some mapping/migrating is required! """ - - - - pass \ No newline at end of file +""" \ No newline at end of file