conference-website/conference_main/util.py

136 lines
4.4 KiB
Python

from typing import Optional
import hashlib
import io
from django import urls
from django.conf import settings
from django.contrib.admin.models import CHANGE, LogEntry
from django.contrib.sites.shortcuts import get_current_site
from django.urls import reverse
from django.utils.encoding import force_bytes
from urllib.parse import urlencode as urllib_urlencode
from urllib.parse import urljoin
import django.conf
import django.db.models
import django.utils.text
import yarl
def login_url_with_redirect(redirect_url: str) -> str:
"""
Construct a login URL which will redirect the user to the given URL after logging in.
:param redirect_url: The URL to redirect the user to after a successful login.
:return: The constructed login URL.
"""
return str(yarl.URL(urls.reverse('oauth:login')).with_query({'next': redirect_url}))
def compact_timesince(timesince):
"""Make timesince filter super compact."""
# Replace long words with letters. (2 days, 3 hours -> 2 d, 3 h)
timesince = (
timesince.replace('minutes', 'm')
.replace('minute', 'm')
.replace('hour', 'h')
.replace('hours', 'h')
)
timesince = timesince.replace('days', 'd').replace('day', 'd').replace('month', 'mon')
timesince = timesince.replace('months', 'mon').replace('weeks', 'w').replace('week', 'w')
# Remove space between digit and unit. (2 d, 3h -> 2d, 3h)
timesince = timesince.replace('\xa0', '')
# Take only the first, usually interesting part. (2d, 3h -> 2d)
timesince = timesince.split(',', 1)[0]
return timesince
def attach_log_entry(
instance: django.db.models.Model,
message: str,
action_flag: int = CHANGE,
user_id: Optional[int] = None,
) -> None:
"""Attach a log entry to this model, for in the admin 'history' page.
:param instance:
:param message:
:param action_flag: Either ADDITION, CHANGE, or DELETION, defaults to CHANGE.
:param user_id: Optionally, the user who performs the logged action.
Can be None when the action is performed by the system.
"""
from django.contrib.admin.models import LogEntry
from django.contrib.contenttypes.models import ContentType
if user_id is None:
user_id = django.conf.settings.SYSTEM_USER_ID
LogEntry.objects.log_action(
user_id=user_id,
content_type_id=ContentType.objects.get_for_model(type(instance)).pk,
object_id=instance.pk,
object_repr=str(instance),
action_flag=action_flag,
change_message=message,
)
def entries_for(instance: django.db.models.Model) -> 'django.db.models.QuerySet[LogEntry]':
"""Build a query for all log entries attached to an instance."""
from django.contrib.admin.models import LogEntry
from django.contrib.contenttypes.models import ContentType
return LogEntry.objects.filter(
content_type_id=ContentType.objects.get_for_model(type(instance)).pk, object_id=instance.pk
)
def get_sha256(file_obj):
"""Calculate a sha256 hash for `file_obj`.
`file_obj` must either be be an open file descriptor, in which case the
caller needs to take care of closing it properly, or a django File-like
object with a chunks() method to iterate over its contents.
"""
hash_ = hashlib.sha256()
if hasattr(file_obj, 'chunks') and callable(file_obj.chunks):
iterator = file_obj.chunks()
else:
iterator = iter(lambda: file_obj.read(io.DEFAULT_BUFFER_SIZE), b'')
for chunk in iterator:
hash_.update(chunk)
# This file might be read again by validation or other utilities
file_obj.seek(0)
return hash_.hexdigest()
def urlencode(items):
"""A Unicode-safe URLencoder."""
try:
return urllib_urlencode(items)
except UnicodeEncodeError:
return urllib_urlencode([(k, force_bytes(v)) for k, v in items])
def absolutify(url: str, request=None) -> str:
"""Return an absolute URL."""
if url and url.startswith(('http://', 'https://')):
return url
proto = 'http' if settings.DEBUG else 'https'
domain = get_current_site(request).domain
return urljoin(f'{proto}://{domain}', url)
def absolute_url(
view_name: str, args: Optional[tuple] = None, kwargs: Optional[dict] = None
) -> str:
"""Same as django.urls.reverse() but returned as an absolute URL."""
relative_url = reverse(view_name, args=args, kwargs=kwargs)
return absolutify(relative_url)