django-dataporten 0.4.0

Creator: danarutscher

Last updated:

Add to Cart

Description:

djangodataporten 0.4.0

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.

Setup

Add “dataporten” to your INSTALLED_APPS setting like this

INSTALLED_APPS = [
...
'dataporten',
...
]

Run python manage.py migrate to create the dataporten proxy models.

3. In your settings.py file, add the variable DATAPORTEN_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 a User and return a str, if the
token exists, else None.
Here is a python3.6/3.7 example that will work if you use django-allauth:
def allauth_token(user: User) -> Optional[str]:
try:
return SocialToken.objects.get(
account__user=user,
account__provider='dataporten',
).token
except SocialToken.DoesNotExist:
return None
4. Add the dataporten middleware. This middleware adds a dataporten
attribute to request.user for users with an associated
dataporten token. Take care to place it after
django.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 in DATAPORTEN_CACHE_PATH before starting the Django server.
# Cache requests to the dataporten API
DATAPORTEN_CACHE_REQUESTS = True

# Where to save the sqlite3 cache backend
DATAPORTEN_CACHE_PATH = 'tmp/'


Usage
The DataportenGroupsMiddleware adds an instance of
DataportenGroupsManager assigned to request.user.dataporten for
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, and all groups.

Groups
All groups are accessible through request.user.dataporten.groups.
This is a dictionary keyed by group ids, with Group objects as values.
Let’s use the Applied Physics and Mathematics master degree at NTNU as an example
for common attributes available for all group types
uid = 'fc:fs:fs:prg:ntnu.no:MTFYMA'
group = request.user.dataporten.groups[uid]
assert group.uid == uid
assert group.name == 'Fysikk og matematikk - masterstudium (5-\u00e5rig)'
assert group.url == 'http://www.ntnu.no/studier/mtfyma'
assert group.group_type == 'fc:fs:prg'


Membership objects
All groups have an associated Membership object which can be used for
further querying of membership properties for that particular group.
The original membership JSON can be accessed from the Membership.json
attribute:
group = request.user.dataporten.groups[uid]
membership = group.membership

print(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 active
assert membership

# Not all group memberships have a set end time
assert isinstance(membership.end_time, [datetime.datetime, None])

# The displayName value is used as the membership string representation
assert str(membership) == 'Ansatt'

# Primary affiliation to the group
assert membership.primary_affiliation == 'employee'

# And all affiliations to the group
assert membership.affiliations == [
'employee',
'member',
'affiliate',
'student',
]

Group membership checks
You can also check if a user is an active member of a specific dataporten group
by providing the group id to the DataportenGroupsManager.is_member_of
method. This is offered as a more ergonomic alternative to
bool(request.user.dataporten.groups[uid].membership). For instance,
assert request.user.dataporten.is_member_of(
uid='fc:org:ntnu.no:unit:167500',
active=True,
)
If active is set to False, the method only checks if the user
has been a member of the group at any time, not necessarily if the user is
an active member.



Semester objects
Membership objects also have an associated Semester object which
can be used to determine the year and season of the membership.
from dataporten.parsers import Semester

semester = request.user.groups[uid].membership.semester
assert semester.year == 2019
assert semester.season in (Semester.SPRING, Semester.AUTUMN)
The Semester class also implements __sub__, which
returns “semester delta” between two semesters. For instance,
the spring semester of 2019 minus the autumn semester of 2017 would
return 3.


Courses
Course enrollment can be queryed from the CourseManager object, attributed to
request.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 course
assert 'TMA4150' in request.user.dataporten.courses.finished

# Currently enrolled in the course
assert 'TMA4150' in request.user.dataporten.courses.active

# Either
assert 'TMA4150' in request.user.dataporten.courses.all


More
There is still lots of more undocumented (but well tested!) attributes of
DataportenGroupsManager. Take a look at dataporten/parsers.py.
Each parser has a class variable NAME, and they are attached to
the user as request.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 tests
export DJANGO_SETTINGS_MODULE=dataporten.settings
pytest

License

For personal and professional use. You cannot resell or redistribute these repositories in their original state.

Customer Reviews

There are no reviews.