Package: django-dataporten
Django-dataporten is a simple Django app which fetches data from dataporten and
attaches it to your Django user objects. It implements the dataporten groups
API, allowing you to easily access group memberships through a pythonic API, without
worrying about parsing raw JSON content.SetupAdd “dataporten” to yourINSTALLED_APPSsetting like thisINSTALLED_APPS=[...'dataporten',...]Runpython manage.py migrateto create the dataporten proxy models.3. In yoursettings.pyfile, add the variableDATAPORTEN_TOKEN_FUNCTION,
which should be a dotted path to the function that will retrieve user tokens.
Dataporten uses this “importable string” in order to retrieve the OAuth2
authentication token for a given user. For instance,DATAPORTEN_TOKEN_FUNCTION='myapp.oauth.allauth_token'The function should accept aUserand return astr, if the
token exists, elseNone.
Here is a python3.6/3.7 example that will work if you usedjango-allauth:defallauth_token(user:User)->Optional[str]:try:returnSocialToken.objects.get(account__user=user,account__provider='dataporten',).tokenexceptSocialToken.DoesNotExist:returnNone4. Add the dataporten middleware. This middleware adds adataportenattribute torequest.userfor users with an associated
dataporten token. Take care to place it afterdjango.contrib.auth.middleware.AuthenticationMiddleware.MIDDLEWARE=(...'django.contrib.auth.middleware.AuthenticationMiddleware',...'dataporten.middleware.DataportenGroupsMiddleware',...)5. Optionally, enable caching for API queries. Take care to create the directory
set inDATAPORTEN_CACHE_PATHbefore starting the Django server.# Cache requests to the dataporten APIDATAPORTEN_CACHE_REQUESTS=True# Where to save the sqlite3 cache backendDATAPORTEN_CACHE_PATH='tmp/'UsageTheDataportenGroupsMiddlewareadds an instance ofDataportenGroupsManagerassigned torequest.user.dataportenfor
every valid dataporten user making a request. This object contains attributes
for accessing different types of group memberships, such as courses, organization
units, study programmes, main profiles, generic groups, andallgroups.GroupsAllgroups are accessible throughrequest.user.dataporten.groups.
This is a dictionary keyed by group ids, withGroupobjects as values.
Let’s use the Applied Physics and Mathematics master degree at NTNU as an example
for common attributes available for all group typesuid='fc:fs:fs:prg:ntnu.no:MTFYMA'group=request.user.dataporten.groups[uid]assertgroup.uid==uidassertgroup.name=='Fysikk og matematikk - masterstudium (5-\u00e5rig)'assertgroup.url=='http://www.ntnu.no/studier/mtfyma'assertgroup.group_type=='fc:fs:prg'Membership objectsAll groups have an associatedMembershipobject which can be used for
further querying of membership properties for that particular group.
The original membership JSON can be accessed from theMembership.jsonattribute:group=request.user.dataporten.groups[uid]membership=group.membershipprint(membership.json)>>>{>>>'title':['fast ansatt'],>>>'affiliation':['employee','member','affiliate','student'],>>>'primaryAffiliation':'employee',>>>'basic':'admin',>>>'displayName':'Ansatt',>>>}Some additional, common properties are available:# Membership objects are "truthy" if they are considered activeassertmembership# Not all group memberships have a set end timeassertisinstance(membership.end_time,[datetime.datetime,None])# The displayName value is used as the membership string representationassertstr(membership)=='Ansatt'# Primary affiliation to the groupassertmembership.primary_affiliation=='employee'# And all affiliations to the groupassertmembership.affiliations==['employee','member','affiliate','student',]Group membership checksYou can also check if a user is anactivemember of a specific dataporten group
by providing the groupidto theDataportenGroupsManager.is_member_ofmethod. This is offered as a more ergonomic alternative tobool(request.user.dataporten.groups[uid].membership). For instance,assertrequest.user.dataporten.is_member_of(uid='fc:org:ntnu.no:unit:167500',active=True,)Ifactiveis set toFalse, the method only checks if the user
has been a member of the group at any time, not necessarily if the user is
anactivemember.Semester objectsMembership objects also have an associatedSemesterobject which
can be used to determine the year and season of the membership.fromdataporten.parsersimportSemestersemester=request.user.groups[uid].membership.semesterassertsemester.year==2019assertsemester.seasonin(Semester.SPRING,Semester.AUTUMN)TheSemesterclass also implements__sub__, which
returns “semester delta” between two semesters. For instance,
the spring semester of 2019 minus the autumn semester of 2017 would
return3.CoursesCourse enrollment can be queryed from theCourseManagerobject, attributed torequest.user.dataporten.course.You can check if a user has an affiliation to a course, only given
its course code, and not its dataporten ID,# Already finished the courseassert'TMA4150'inrequest.user.dataporten.courses.finished# Currently enrolled in the courseassert'TMA4150'inrequest.user.dataporten.courses.active# Eitherassert'TMA4150'inrequest.user.dataporten.courses.allMoreThere is still lots of more undocumented (but well tested!) attributes ofDataportenGroupsManager. Take a look atdataporten/parsers.py.
Each parser has a class variableNAME, and they are attached to
the user asrequest.user.dataporten.NAME.If you have a specific usecase, please open a GitHub issue, and I will
document and/or implement it for you.Run testsexportDJANGO_SETTINGS_MODULE=dataporten.settingspytest