[TASK] Cleanup, begin implementing a mapping wizard for citavi persons.
This commit is contained in:
parent
b0a04b951e
commit
9b06e3aac6
|
@ -8,7 +8,8 @@ admin.autodiscover()
|
|||
from frontend.views import login_wrap, logout_wrap
|
||||
from frontend.views import IndexView, ProjectView, ProjectUpdateView, ProjectPersonView, ProjectMapPersonView
|
||||
|
||||
urlpatterns = patterns('',
|
||||
urlpatterns = patterns(
|
||||
'',
|
||||
url(r'^$', IndexView.as_view(), name='frontend-index'),
|
||||
url(r'^project/$', ProjectView.as_view(), name='frontend-projects'),
|
||||
url(r'^project/(?P<project_id>\d+)/update$', ProjectUpdateView.as_view(), name='frontend-project-update'),
|
||||
|
|
|
@ -61,9 +61,10 @@ class PersonMapForm(forms.Form):
|
|||
self.helper.layout = Layout(
|
||||
'action',
|
||||
'global_identity',
|
||||
Submit('continue', 'Continue', css_class='btn-default'),
|
||||
Submit('skip', 'Skip', css_class='btn-default'),
|
||||
Submit('save-continue', 'Save and continue', css_class='btn-default'),
|
||||
)
|
||||
|
||||
action = forms.ChoiceField(choices=[('new', 'Create new global Identity'), ('existing', 'Map to existing identity')], widget=forms.RadioSelect())
|
||||
global_identity = forms.ModelChoiceField(queryset=PersonGlobalIdentity.objects.all())
|
||||
action = forms.ChoiceField(choices=[('new', 'Create new global Identity'), ('existing', 'Map to existing identity')], initial='new', widget=forms.RadioSelect())
|
||||
global_identity = forms.ModelChoiceField(queryset=PersonGlobalIdentity.objects.all(), required=False)
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ from django.db import models
|
|||
|
||||
|
||||
class Project(models.Model):
|
||||
""" Model representing a citavi project. """
|
||||
name = models.CharField(max_length=255)
|
||||
description = models.TextField()
|
||||
associated_filename = models.CharField(max_length=255, blank=True, null=True)
|
||||
|
@ -18,6 +19,7 @@ class Project(models.Model):
|
|||
|
||||
|
||||
class PersonGlobalIdentity(models.Model):
|
||||
""" Model representing a global person identity in django. Can be used to link any foreign identity to it. """
|
||||
type = models.CharField(max_length=255)
|
||||
# TODO: Extend this for further stuff - maybe vivo external url or something?
|
||||
|
||||
|
@ -27,6 +29,7 @@ class PersonGlobalIdentity(models.Model):
|
|||
|
||||
|
||||
class CitaviProjectIdentity(models.Model):
|
||||
""" Model representing an identity from a citavi project. """
|
||||
global_identity = models.ForeignKey(PersonGlobalIdentity, blank=True, null=True)
|
||||
project = models.ForeignKey(Project, blank=False, null=False)
|
||||
citavi_uuid = models.CharField(max_length=255, blank=False, null=False)
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
<li><a href="{% url 'frontend-projects' %}">Back to projects</a></li>
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
<h3>Project</h3>
|
||||
<p><strong>Name:</strong> {{project.name}}</h3>
|
||||
<p><strong>Description:</strong> {{project.description}}</h3>
|
||||
<p><strong>Current uploaded database filename:</strong> {{project.associated_filename}}</p>
|
||||
|
@ -15,7 +16,13 @@
|
|||
<p>{% crispy form %}</p>
|
||||
-->
|
||||
|
||||
<h3>List of unmapped citavi persons in project:</h3>
|
||||
<h3>Stats</h3>
|
||||
<p>
|
||||
<strong>Mapped:</strong> {{mapped_persons|length}}<br>
|
||||
<strong>Unmapped:</strong> {{unmapped_persons|length}}<br>
|
||||
</p>
|
||||
|
||||
<h3>List of unmapped citavi persons in project</h3>
|
||||
{% if not unmapped_persons %}
|
||||
<p><strong>No unmapped persons in this project. Congratulations!</strong></p>
|
||||
{% else %}
|
||||
|
@ -55,39 +62,25 @@
|
|||
</table>
|
||||
{% endif %}
|
||||
<hr>
|
||||
<h3>List of mapped citavi persons in project:</h3>
|
||||
<h3>List of mapped citavi persons in project</h3>
|
||||
{% if not mapped_persons %}
|
||||
<p><strong>No mapped persons in this project. Work harder!</strong></p>
|
||||
{% else %}
|
||||
<table class="table table-hover table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Prefix</th>
|
||||
<th>Title</th>
|
||||
<th>First Name</th>
|
||||
<th>Middle Name</th>
|
||||
<th>Last Name</th>
|
||||
<th>Suffix</th>
|
||||
<th>Sex</th>
|
||||
<th>Abv.</th>
|
||||
<th>Citavi_UUID</th>
|
||||
<th>Features</th>
|
||||
<th>Features</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for person in mapped_persons.items %}
|
||||
{% for person_id, person in mapped_persons.items %}
|
||||
<tr>
|
||||
<td>{{person.ID}}</td>
|
||||
<td>{{person.Prefix}}</td>
|
||||
<td>{{person.Title}}</td>
|
||||
<td>{{person.FirstName}}</td>
|
||||
<td>{{person.MiddleName}}</td>
|
||||
<td>{{person.LastName}}</td>
|
||||
<td>{{person.Suffix}}</td>
|
||||
<td>{{person.Sex}}</td>
|
||||
<td>{{person.Abbreviation}}</td>
|
||||
<td>{{person.citavi_uuid}}</td>
|
||||
<td>{{person.global_identity}}</td>
|
||||
<td>
|
||||
<a href="{% url 'frontend-project-map-person' project.id person.ID %}" title="Enter mapping wizard starting here.">Map</a>
|
||||
<a href="#TODO" title="Enter mapping wizard starting here.">Delete Mapping</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
<td>{{project.associated_filename}}</td>
|
||||
<td>
|
||||
<a href="{% url 'frontend-project-update' project.id %}">Update project</a>
|
||||
<a href="{% url 'frontend-project-map-person' project.id %}">Persons</a>
|
||||
<a href="{% url 'frontend-project-view-person' project.id %}">Persons</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
|
|
@ -21,6 +21,7 @@ FRONTEND_PAGE_NAME = 'Citavi Mapper'
|
|||
|
||||
# Login wrapper functions
|
||||
def login_wrap(*args, **kwargs):
|
||||
""" Wrapper function for login page. """
|
||||
kwargs['extra_context'] = {
|
||||
'page': {
|
||||
'name': FRONTEND_PAGE_NAME,
|
||||
|
@ -30,6 +31,7 @@ def login_wrap(*args, **kwargs):
|
|||
return login(*args, **kwargs)
|
||||
|
||||
def logout_wrap(*args, **kwargs):
|
||||
""" Wrapper function for logout page. """
|
||||
kwargs['extra_context'] = {
|
||||
'page': {
|
||||
'name': FRONTEND_PAGE_NAME,
|
||||
|
@ -41,6 +43,7 @@ def logout_wrap(*args, **kwargs):
|
|||
|
||||
# My base classes for views
|
||||
class MyViewMixin(object):
|
||||
""" Basic view mixin to add global variables to all templates. """
|
||||
template_name = 'base.html'
|
||||
page_name = FRONTEND_PAGE_NAME
|
||||
page_title = 'BASE'
|
||||
|
@ -70,6 +73,7 @@ class MyUpdateView(MyViewMixin, UpdateView):
|
|||
|
||||
# Mixin to protect pages
|
||||
class LoggedInMixin(object):
|
||||
""" Mixin to force a valid login for protected pages. """
|
||||
@method_decorator(login_required)
|
||||
def dispatch(self, *args, **kwargs):
|
||||
return super(LoggedInMixin, self).dispatch(*args, **kwargs)
|
||||
|
@ -94,6 +98,7 @@ class IndexView(ProtectedTemplateView):
|
|||
template_name = 'index.html'
|
||||
page_title = 'Index'
|
||||
|
||||
|
||||
class ProjectView(ProtectedFormView):
|
||||
template_name = 'projects.html'
|
||||
page_title = 'Projects'
|
||||
|
@ -108,6 +113,7 @@ class ProjectView(ProtectedFormView):
|
|||
form.save()
|
||||
return super(ProjectView, self).form_valid(form)
|
||||
|
||||
|
||||
class ProjectUpdateView(ProtectedFormView, SingleObjectMixin):
|
||||
template_name = 'project/update.html'
|
||||
page_title = 'Update project'
|
||||
|
@ -172,7 +178,7 @@ class ProjectUpdateView(ProtectedFormView, SingleObjectMixin):
|
|||
|
||||
class ProjectPersonView(ProtectedFormView, SingleObjectMixin):
|
||||
template_name = 'project/view-person.html'
|
||||
page_title = 'Person View'
|
||||
page_title = 'Person List View'
|
||||
form_class = FileUploadForm
|
||||
|
||||
success_url = '/projects/'
|
||||
|
@ -183,6 +189,7 @@ class ProjectPersonView(ProtectedFormView, SingleObjectMixin):
|
|||
from service import Mapper
|
||||
pm = Mapper.PersonMapper()
|
||||
kwargs[u'unmapped_persons'] = pm.get_unmapped_identities(project)
|
||||
kwargs[u'mapped_persons'] = pm.get_mapped_identities(project)
|
||||
return super(ProjectPersonView, self).get_context_data(**kwargs)
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
|
@ -204,7 +211,7 @@ class ProjectMapPersonView(ProtectedFormView, SingleObjectMixin):
|
|||
page_title = 'Person Mapping'
|
||||
form_class = PersonMapForm
|
||||
|
||||
success_url = '/projects/'
|
||||
success_url = '/project'
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
project = self.object
|
||||
|
@ -223,9 +230,21 @@ class ProjectMapPersonView(ProtectedFormView, SingleObjectMixin):
|
|||
def post(self, request, *args, **kwargs):
|
||||
self.project_id = kwargs[u'project_id']
|
||||
self.person_uuid = kwargs[u'person_uuid']
|
||||
self.object = Project.objects.get(pk=self.project_id)
|
||||
# self.success_url = self.success_url + self.project_id + '/update'
|
||||
return super(ProjectMapPersonView, self).post(request, *args, **kwargs)
|
||||
|
||||
def form_valid(self, form, *args, **kwargs):
|
||||
from service import Mapper
|
||||
pm = Mapper.PersonMapper()
|
||||
person = pm.get_person_by_uuid(self.object, self.person_uuid)
|
||||
|
||||
print str(form.cleaned_data)
|
||||
# TODO: do mapping according to parameters, override success_url to point to next person!
|
||||
if form.cleaned_data['action'] == 'new':
|
||||
pm.create_new_identity(self.object, person)
|
||||
elif form.cleaned_data['action'] == 'skip':
|
||||
pass
|
||||
|
||||
return super(ProjectMapPersonView, self).form_valid(form)
|
||||
|
||||
|
|
|
@ -105,71 +105,11 @@ class ProjectManager():
|
|||
self._projects[project_id].open()
|
||||
|
||||
def get_person_by_uuid(self, project_id, uuid):
|
||||
""" Returns the person matching the given uuid. """
|
||||
self._add_project(project_id)
|
||||
return self._projects[project_id].get_person_by_uuid(uuid)
|
||||
|
||||
def get_persons_from_project(self, project_id):
|
||||
""" Returns all person from a projects. """
|
||||
self._add_project(project_id)
|
||||
return self._projects[project_id].get_persons()
|
||||
|
||||
"""
|
||||
def import_sqlite(project_id, sqlite_file):
|
||||
print "This is import_sqlite speaking!"
|
||||
print project_id
|
||||
print sqlite_file
|
||||
print "Importing data..."
|
||||
|
||||
# Initialize sqlite part
|
||||
sqlite_engine = create_engine('sqlite+pysqlite:///project_import_9.ctt4', echo=True)
|
||||
sqlite_session = Session(sqlite_engine)
|
||||
sqlite_meta = MetaData(bind=sqlite_engine)
|
||||
sqlite_meta.reflect()
|
||||
|
||||
# Initialize postresql part
|
||||
psql_engine = create_engine("postgresql://citavi_mapper:foobar2000@localhost:5432/citavi_mapper")
|
||||
psql_session = Session(psql_engine)
|
||||
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
|
||||
for table in sqlite_meta.sorted_tables:
|
||||
table_name = str(table)
|
||||
columns = table.columns.items()
|
||||
print "class " + table_name + "(Base):"
|
||||
print " __tablename__ = '" + table_name + "'"
|
||||
print
|
||||
for column_tuple in columns:
|
||||
column_name = column_tuple[0]
|
||||
actual_sqlalchemy_column = column_tuple[1]
|
||||
column_type = str(vars(actual_sqlalchemy_column)['type'])
|
||||
column_type = str(vars(actual_sqlalchemy_column)['type'])
|
||||
#print table_name + "." + column_name + ': ' + column_type
|
||||
print " " + column_name + " = Column(" + column_type + ")"
|
||||
print
|
||||
print
|
||||
|
||||
# Shove it up into postgresql's ... you know.
|
||||
psql_meta.create_all(psql_engine)
|
||||
|
||||
#sqlite_meta.reflect()
|
||||
|
||||
#meta.tables['Reference']
|
||||
#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()
|
||||
for column_tuple in columns:
|
||||
column_name = column_tuple[0]
|
||||
actual_sqlalchemy_column = column_tuple[1]
|
||||
column_type = str(vars(actual_sqlalchemy_column)['type'])
|
||||
print table_name + "." + column_name + ': ' + column_type
|
||||
print
|
||||
print
|
||||
"""
|
||||
|
|
|
@ -4,8 +4,9 @@ from frontend.models import PersonGlobalIdentity, CitaviProjectIdentity
|
|||
|
||||
|
||||
class PersonIdentityManager():
|
||||
|
||||
""" Class wrapping the django model layer to manage identities. """
|
||||
def create_identity(self, project, uuid):
|
||||
""" Creates a new identity and connects it to the given citavi project uuid. """
|
||||
pgi = PersonGlobalIdentity(type='citavi')
|
||||
pgi.save()
|
||||
cpi = CitaviProjectIdentity(global_identity=pgi, project=project, citavi_uuid=uuid, preferred=True)
|
||||
|
@ -13,12 +14,15 @@ class PersonIdentityManager():
|
|||
return cpi
|
||||
|
||||
def add_identity_to_global_identity(self, global_identity, project, uuid, preferred):
|
||||
""" Maps given citavi project identity to existing global identity. """
|
||||
cpi = CitaviProjectIdentity(global_identity=global_identity, project=project, citavi_uuid=uuid, preferred=True)
|
||||
cpi.save()
|
||||
return cpi
|
||||
|
||||
def get_global_identities(self):
|
||||
""" Returns all global identities. """
|
||||
return PersonGlobalIdentity.objects.all()
|
||||
|
||||
def get_mapped_identities_for_project(self, project_instance):
|
||||
""" Returns all existing (mapped) identies for a given project. """
|
||||
return CitaviProjectIdentity.objects.filter(project=project_instance).all()
|
||||
|
|
|
@ -3,53 +3,46 @@
|
|||
from Citavi import ProjectManager
|
||||
from Django import PersonIdentityManager
|
||||
|
||||
|
||||
class PersonMapper():
|
||||
|
||||
def __init__(self):
|
||||
""" Initializes ProjectManager and PersonIdentityManager. """
|
||||
self._citavi_project_manager = ProjectManager()
|
||||
self._person_identity_manager = PersonIdentityManager()
|
||||
|
||||
def __del__(self):
|
||||
""" Destroys ProjectManager and PersonIdentityManager. """
|
||||
del self._citavi_project_manager
|
||||
del self._person_identity_manager
|
||||
|
||||
def get_unmapped_identities(self, project):
|
||||
""" Returns a uuid->person dict for all unmapped persons within a project. """
|
||||
citavi_persons = self._citavi_project_manager.get_persons_from_project(project.id)
|
||||
mapped_persons = self._person_identity_manager.get_mapped_identities_for_project(project)
|
||||
|
||||
print "Len citavi persons: " + str(len(citavi_persons))
|
||||
print "Len mapped persons: " + str(len(mapped_persons))
|
||||
|
||||
# Prepare citavi_persons into a uuid->person dict, then eliminate mapped ones. This is ugly and a little slow.
|
||||
citavi_uuid_dict = {}
|
||||
for person in citavi_persons:
|
||||
citavi_uuid_dict[person.ID] = person
|
||||
|
||||
if len(mapped_persons) == 0:
|
||||
return citavi_uuid_dict
|
||||
|
||||
print len(citavi_uuid_dict)
|
||||
|
||||
for person in mapped_persons:
|
||||
if person.citavi_uuid in citavi_uuid_dict:
|
||||
# print "Match for: " + str(person.id) + " - uuid: " + str(person.citavi_uuid)
|
||||
del citavi_uuid_dict[person.citavi_uuid]
|
||||
|
||||
print len(citavi_uuid_dict)
|
||||
|
||||
return citavi_uuid_dict
|
||||
|
||||
def get_mapped_identities(self, project):
|
||||
""" Returns a uuid->person dict for all mapped persons within a project. """
|
||||
mapped_persons = self._person_identity_manager.get_mapped_identities_for_project(project)
|
||||
mapped_uuid_dict = {}
|
||||
for person in mapped_persons:
|
||||
mapped_uuid_dict[person.citavi_uuid] = person
|
||||
return mapped_uuid_dict
|
||||
|
||||
def create_new_identity(self, project, person):
|
||||
self._person_identity_manager.create_identity(project, person.ID)
|
||||
""" Creates a new identity for a given person. """
|
||||
return self._person_identity_manager.create_identity(project, person.ID)
|
||||
|
||||
def get_person_by_uuid(self, project, uuid): #
|
||||
def get_person_by_uuid(self, project, uuid):
|
||||
""" Returns a person from a citavi project by uuid. """
|
||||
return self._citavi_project_manager.get_person_by_uuid(project.id, uuid)
|
||||
|
||||
def test():
|
||||
from frontend.models import Project
|
||||
project = Project.objects.get(id=1)
|
||||
p = PersonMapper()
|
||||
unmapped = p.get_unmapped_identities(project)
|
||||
print unmapped
|
||||
for person in unmapped:
|
||||
p.create_new_identity(project, person)
|
||||
|
|
Loading…
Reference in New Issue