Simplified student import process
This commit is contained in:
parent
7d45cd0047
commit
03f45f0785
5 changed files with 89 additions and 8 deletions
|
|
@ -110,6 +110,22 @@ INSTALLED_APPS = (
|
|||
'stages',
|
||||
)
|
||||
|
||||
FILE_UPLOAD_HANDLERS = ["django.core.files.uploadhandler.TemporaryFileUploadHandler"]
|
||||
|
||||
ALLOWED_HOSTS = ['localhost', 'stages.pierre-coullery.ch']
|
||||
|
||||
# Mapping between column names of a tabular file and Student field names
|
||||
STUDENT_IMPORT_MAPPING = {
|
||||
'Num élève': 'ext_id',
|
||||
'Nom élève': 'last_name',
|
||||
'Prénom élève': 'first_name',
|
||||
'Rue élève': 'street',
|
||||
'Localité élève': 'city', # pcode is separated from city in prepare_import
|
||||
'Tél. élève': 'tel',
|
||||
'Natel élève': 'mobile',
|
||||
'Email élève': 'email',
|
||||
'Date nais. élève': 'birth_date',
|
||||
'Classe': 'klass',
|
||||
}
|
||||
|
||||
from .local_settings import *
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ urlpatterns = [
|
|||
url(r'^$', RedirectView.as_view(url='/admin/', permanent=True), name='home'),
|
||||
|
||||
url(r'^admin/', include(admin.site.urls)),
|
||||
url(r'^data-import/', include('tabimport.urls')),
|
||||
url(r'^data-import/', views.StudentImportView.as_view(), name='tabimport'),
|
||||
|
||||
url(r'^attribution/$', views.AttributionView.as_view(), name='attribution'),
|
||||
url(r'^stages/export/(?P<scope>all)?/?$', views.stages_export, name='stages_export'),
|
||||
|
|
|
|||
|
|
@ -1,8 +1,29 @@
|
|||
from django import forms
|
||||
from django.conf import settings
|
||||
|
||||
from tabimport import FileFactory, UnsupportedFileFormat
|
||||
|
||||
from .models import Section, Period
|
||||
|
||||
|
||||
class StudentImportForm(forms.Form):
|
||||
upload = forms.FileField(label="Fichier des étudiants")
|
||||
|
||||
def clean_upload(self):
|
||||
f = self.cleaned_data['upload']
|
||||
try:
|
||||
imp_file = FileFactory(f)
|
||||
except UnsupportedFileFormat as e:
|
||||
raise forms.ValidationError("Erreur: %s" % e)
|
||||
# Check needed headers are present
|
||||
headers = imp_file.get_headers()
|
||||
missing = set(settings.STUDENT_IMPORT_MAPPING.keys()) - set(headers)
|
||||
if missing:
|
||||
raise forms.ValidationError("Erreur: il manque les colonnes %s" % (
|
||||
", ".join(missing)))
|
||||
return f
|
||||
|
||||
|
||||
class PeriodForm(forms.Form):
|
||||
section = forms.ModelChoiceField(queryset=Section.objects.all())
|
||||
period = forms.ModelChoiceField(queryset=None)
|
||||
|
|
|
|||
|
|
@ -2,12 +2,18 @@ import json
|
|||
from collections import OrderedDict
|
||||
from datetime import date, datetime, timedelta
|
||||
|
||||
from django.db.models import Count
|
||||
from django.http import HttpResponse, HttpResponseNotAllowed
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.views.generic import DetailView, TemplateView, ListView
|
||||
from tabimport import FileFactory
|
||||
|
||||
from .forms import PeriodForm
|
||||
from django.conf import settings
|
||||
from django.contrib import messages
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.db.models import Count
|
||||
from django.http import HttpResponse, HttpResponseNotAllowed, HttpResponseRedirect
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.utils.translation import ugettext as _
|
||||
from django.views.generic import DetailView, FormView, TemplateView, ListView
|
||||
|
||||
from .forms import PeriodForm, StudentImportForm
|
||||
from .models import (Section, Student, Corporation, CorpContact, Period,
|
||||
Training, Referent, Availability)
|
||||
|
||||
|
|
@ -197,7 +203,7 @@ def new_training(request):
|
|||
avail.save()
|
||||
except Exception as exc:
|
||||
return HttpResponse(str(exc))
|
||||
return HttpResponse('OK')
|
||||
return HttpResponse(b'OK')
|
||||
|
||||
def del_training(request):
|
||||
""" Delete training and return the referent id """
|
||||
|
|
@ -209,6 +215,44 @@ def del_training(request):
|
|||
return HttpResponse(json.dumps({'ref_id': ref_id}), content_type="application/json")
|
||||
|
||||
|
||||
class StudentImportView(FormView):
|
||||
template_name = 'student_import.html'
|
||||
form_class = StudentImportForm
|
||||
|
||||
def form_valid(self, form):
|
||||
try:
|
||||
imp_file = FileFactory(form.cleaned_data['upload'])
|
||||
created, modified = self.import_data(imp_file)
|
||||
except Exception as e:
|
||||
if settings.DEBUG:
|
||||
raise
|
||||
messages.error(self.request, _("The import failed. Error message: %s") % e)
|
||||
else:
|
||||
messages.info(self.request, _("Created objects: %(cr)d, modified objects: %(mod)d") % {
|
||||
'cr': created, 'mod': modified})
|
||||
return HttpResponseRedirect(reverse('admin:index'))
|
||||
|
||||
def import_data(self, up_file):
|
||||
""" Import Student data from uploaded file. """
|
||||
mapping = settings.STUDENT_IMPORT_MAPPING
|
||||
rev_mapping = {v: k for k, v in mapping.items()}
|
||||
obj_created = obj_modified = 0
|
||||
for line in up_file:
|
||||
defaults = dict((val, line[key]) for key, val in mapping.items() if val != 'ext_id')
|
||||
defaults = Student.prepare_import(defaults)
|
||||
obj, created = Student.objects.get_or_create(
|
||||
ext_id=line[rev_mapping['ext_id']], defaults=defaults)
|
||||
if not created:
|
||||
for key, val in defaults.items():
|
||||
setattr(obj, key, val)
|
||||
obj.save()
|
||||
obj_modified += 1
|
||||
else:
|
||||
obj_created += 1
|
||||
#FIXME: implement arch_staled
|
||||
return obj_created, obj_modified
|
||||
|
||||
|
||||
EXPORT_FIELDS = [
|
||||
('Prénom', 'student__first_name'), ('Nom', 'student__last_name'),
|
||||
('ID externe', 'student__ext_id'),
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@
|
|||
<div class="module" id="custom-actions-module">
|
||||
<h2>Importation/exportation</h2>
|
||||
<ul>
|
||||
<li><a href="{% url 'tabimport' %}">Importer des données</a></li>
|
||||
<li><a href="{% url 'tabimport' %}">Importer un fichier d'étudiants</a></li>
|
||||
<li><a href="{% url 'stages_export' %}">Exporter les données de stages</a> (récentes)</li>
|
||||
<li><a href="{% url 'stages_export' 'all' %}">Exporter les données de stages</a> (toutes)</li>
|
||||
</ul>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue