This commit is contained in:
2021-01-15 15:42:30 +00:00
parent b0df14e7ae
commit f6b9e2f741
43 changed files with 793 additions and 628 deletions

View File

@@ -2,4 +2,4 @@ from django.apps import AppConfig
class AuthenticationsConfig(AppConfig):
name = 'authentications'
name = "authentications"

View File

@@ -11,25 +11,25 @@ def authentication(username, password):
return None
# username format
new_username = 'uid={username},ou=user,dc=fet,dc=htu,dc=tuwien,dc=ac,dc=at'
new_username = "uid={username},ou=user,dc=fet,dc=htu,dc=tuwien,dc=ac,dc=at"
userdn = new_username.format(username=username)
server_uri = 'ldap://gagarin.fet.htu.tuwien.ac.at'
server_uri = "ldap://gagarin.fet.htu.tuwien.ac.at"
server = ldap3.Server(server_uri, port=389, use_ssl=True)
has_user = False
try:
conn = ldap3.Connection(server, user=userdn, password=password, auto_bind=True)
conn.search('dc=fet,dc=htu,dc=tuwien,dc=ac,dc=at', '(objectclass=person)')
conn.search("dc=fet,dc=htu,dc=tuwien,dc=ac,dc=at", "(objectclass=person)")
for user in sorted(conn.entries):
if ("DN: uid=" + str(username.lower())) in str(user):
has_user = True
except LDAPBindError as e:
logger.info('Username does not exist. Error: {}'.format(e))
logger.info("Username does not exist. Error: {}".format(e))
username = None
except Exception as e:
logger.info('Connection to server lost. Error: {}'.format(e))
logger.info("Connection to server lost. Error: {}".format(e))
username = None
if not has_user:

View File

@@ -4,7 +4,7 @@ from django.shortcuts import redirect
def unauthenticated_user(view_func):
def wrapper_func(request, *args, **kwargs):
if request.user.is_authenticated:
return redirect('home')
return redirect("home")
else:
return view_func(request, *args, **kwargs)
@@ -16,7 +16,7 @@ def authenticated_user(view_func):
if request.user.is_authenticated:
return view_func(request, *args, **kwargs)
else:
return redirect('login')
return redirect("login")
return wrapper_func

View File

@@ -3,4 +3,4 @@ from django import forms
class LoginForm(forms.Form):
username = forms.CharField()
password = forms.CharField(label='Passwort', widget=forms.PasswordInput())
password = forms.CharField(label="Passwort", widget=forms.PasswordInput())

View File

@@ -3,6 +3,6 @@ from . import views
urlpatterns = [
path('login/', views.loginPage, name="login"),
path('logout/', views.logoutUser, name="logout"),
path("login/", views.loginPage, name="login"),
path("logout/", views.logoutUser, name="logout"),
]

View File

@@ -12,9 +12,9 @@ from .forms import LoginForm
@unauthenticated_user
def loginPage(request):
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
if request.method == "POST":
username = request.POST.get("username")
password = request.POST.get("password")
auth_user = authentication(username, password)
@@ -27,25 +27,25 @@ def loginPage(request):
login(request, user)
try:
return redirect(request.GET.get('next'))
return redirect(request.GET.get("next"))
except:
return redirect('home')
return redirect("home")
else:
messages.info(request, 'username or password is incorrect')
messages.info(request, "username or password is incorrect")
form = LoginForm()
context = {
"form": form,
}
return render(request, 'authentications/login.html', context)
return render(request, "authentications/login.html", context)
@authenticated_user
def logoutUser(request):
logout(request)
response = redirect('home')
response = redirect("home")
response = del_ep_cookie(request, response)
return response

View File

@@ -8,7 +8,7 @@ class JobPostingAdmin(admin.ModelAdmin):
form = JobPostingForm
model = JobPosting
list_display = ['companyName', 'jobName', 'salary', 'publishDate']
list_display = ["companyName", "jobName", "salary", "publishDate"]
admin.site.register(JobPosting, JobPostingAdmin)

View File

@@ -2,4 +2,4 @@ from django.apps import AppConfig
class BlackboardConfig(AppConfig):
name = 'blackboard'
name = "blackboard"

View File

@@ -7,19 +7,17 @@ from .models import JobPosting
class JobPostingForm(forms.ModelForm):
class Meta:
model = JobPosting
fields = ['companyName', 'jobName', 'salary', 'pdfLocation', 'publishDate']
fields = ["companyName", "jobName", "salary", "pdfLocation", "publishDate"]
labels = {
'companyName': _("Firmenname"),
'jobName': _("Berufsbezeichnung"),
'salary': _("Gehalt"),
'pdfLocation': _("Stellenausschreibung"),
'publishDate': _("Veröffentlichung"),
"companyName": _("Firmenname"),
"jobName": _("Berufsbezeichnung"),
"salary": _("Gehalt"),
"pdfLocation": _("Stellenausschreibung"),
"publishDate": _("Veröffentlichung"),
}
help_texts = {
'pdfLocation': _(
"Verwendbare Formate: PDF"
),
'salary': _("in Euro angeben"),
"pdfLocation": _("Verwendbare Formate: PDF"),
"salary": _("in Euro angeben"),
}

View File

@@ -11,16 +11,23 @@ from os.path import splitext, basename
import ghostscript
import logging
logger = logging.getLogger('blackboard')
logger = logging.getLogger("blackboard")
class JobPosting(models.Model):
companyName = models.CharField(verbose_name="Firmenname", max_length=128)
jobName = models.CharField(verbose_name="Berufsbezeichnung", max_length=128)
salary = models.PositiveSmallIntegerField(verbose_name="Gehalt", )
pdfLocation = models.FileField(verbose_name="Stellenausschreibung", upload_to='uploads/blackboard/pdf/')
salary = models.PositiveSmallIntegerField(
verbose_name="Gehalt",
)
pdfLocation = models.FileField(
verbose_name="Stellenausschreibung", upload_to="uploads/blackboard/pdf/"
)
pdf_thumb_location = models.CharField(max_length=128)
publishDate = models.DateField(verbose_name="Veröffentlichung", default=timezone.now)
publishDate = models.DateField(
verbose_name="Veröffentlichung", default=timezone.now
)
# Managers
all_jobPosting = models.Manager()
@@ -40,7 +47,7 @@ class JobPosting(models.Model):
"-dDEVICEWIDTHPOINTS=600",
"-dDEVICEHEIGHTPOINTS=800",
"-sOutputFile=" + jpeg_output_path,
pdf_input_path
pdf_input_path,
]
encoding = locale.getpreferredencoding()
@@ -54,14 +61,18 @@ class JobPosting(models.Model):
if not os.path.exists(settings.MEDIA_ROOT + "uploads/blackboard/thumb/"):
os.makedirs(settings.MEDIA_ROOT + "uploads/blackboard/thumb/")
pdf_thumb_location_full = settings.MEDIA_ROOT \
+ "uploads/blackboard/thumb/" \
+ splitext(basename(self.pdfLocation.name))[0] \
pdf_thumb_location_full = (
settings.MEDIA_ROOT
+ "uploads/blackboard/thumb/"
+ splitext(basename(self.pdfLocation.name))[0]
+ ".jpg"
)
self.pdf_thumb_location = "/files/uploads/blackboard/thumb/" \
+ splitext(basename(self.pdfLocation.name))[0] \
self.pdf_thumb_location = (
"/files/uploads/blackboard/thumb/"
+ splitext(basename(self.pdfLocation.name))[0]
+ ".jpg"
)
self.pdf2jpeg(self.pdfLocation.path, pdf_thumb_location_full)
logger.info("SavenThumbAs: " + self.pdf_thumb_location)
@@ -70,7 +81,7 @@ class JobPosting(models.Model):
def clean(self):
count = 0
for i in self.pdfLocation.name:
if i == '.':
if i == ".":
count = count + 1
if count > 1: # if more than one dot in filename
raise ValidationError(_('Keine Dateien mit >1 Punkten im Namen erlaubt.'))
raise ValidationError(_("Keine Dateien mit >1 Punkten im Namen erlaubt."))

View File

@@ -4,5 +4,5 @@ from . import views
urlpatterns = [
path('', views.index, name='blackboard'),
path("", views.index, name="blackboard"),
]

View File

@@ -10,8 +10,8 @@ from posts.models import Post
def index(request):
job_postings_cutoff = timezone.now().date() - timedelta(30) # 30days from now
job_postings = JobPosting.all_jobPosting.filter(publishDate__gt=job_postings_cutoff)
bb_info = Post.objects.filter(slug='blackboard').first()
bb_empty = Post.objects.filter(slug='blackboard-empty').first()
bb_info = Post.objects.filter(slug="blackboard").first()
bb_empty = Post.objects.filter(slug="blackboard-empty").first()
context = {
"job_postings": job_postings,
@@ -19,4 +19,4 @@ def index(request):
"bb_empty": bb_empty,
}
return render(request, 'blackboard/index.html', context)
return render(request, "blackboard/index.html", context)

View File

@@ -6,6 +6,7 @@ import urllib.parse
from etherpad_lite import EtherpadLiteClient, EtherpadException
import logging
logger = logging.getLogger(__name__)
SERVER_URL = settings.ETHERPAD_CLIENT["exturl"]
@@ -20,9 +21,11 @@ def get_ep_client():
apikey = f.read()
apikey = apikey.rstrip()
epc = EtherpadLiteClient(
base_params={'apikey': apikey, },
base_params={
"apikey": apikey,
},
base_url=urllib.parse.urljoin(settings.ETHERPAD_CLIENT["url"], "api"),
api_version='1.2.14',
api_version="1.2.14",
)
group = epc.createGroupIfNotExistsFor(groupMapper="fet")
except Exception as e:
@@ -62,7 +65,9 @@ def createPadifNotExists(padID):
# Pad doesn't exist
if not __checkPadExists(padID=padID):
try:
epc.createGroupPad(groupID=group["groupID"], padName=padID, text="helloworld")
epc.createGroupPad(
groupID=group["groupID"], padName=padID, text="helloworld"
)
except EtherpadException as e:
logger.info("Can't create Pad '{}'. EtherpadException: {}".format(padID, e))
return None
@@ -81,7 +86,9 @@ def getPadHTML(padID):
try:
text = epc.getHTML(padID=group["groupID"] + "$" + padID)["html"]
except EtherpadException as e:
logger.info("Can't get HTML from padID '{}'. EtherpadException: {}".format(padID, e))
logger.info(
"Can't get HTML from padID '{}'. EtherpadException: {}".format(padID, e)
)
return None
except Exception as e:
raise e
@@ -107,4 +114,6 @@ def get_pad_link(padID):
if not epc or not group:
return "#"
return urllib.parse.urljoin(settings.ETHERPAD_CLIENT["exturl"], 'p/' + group["groupID"] + '$' + str(padID))
return urllib.parse.urljoin(
settings.ETHERPAD_CLIENT["exturl"], "p/" + group["groupID"] + "$" + str(padID)
)

View File

@@ -1,6 +1,7 @@
from django.apps import AppConfig
# from django.contrib.admin.apps import AdminConfig
class DocumentsConfig(AppConfig):
name = 'documents'
name = "documents"

View File

@@ -11,22 +11,21 @@ def __get_ep_sessionid(request):
return None, None
author = epc.createAuthorIfNotExistsFor(
name=str(request.user),
authorMapper=str(request.user)
)['authorID']
name=str(request.user), authorMapper=str(request.user)
)["authorID"]
expires = datetime.utcnow() + timedelta(hours=3)
try:
result = epc.createSession(
groupID=str(group['groupID']),
groupID=str(group["groupID"]),
authorID=str(author),
validUntil=str(int(expires.timestamp()))
validUntil=str(int(expires.timestamp())),
)
except Exception as e:
raise e
return None, None
return result['sessionID'], expires
return result["sessionID"], expires
def add_ep_cookie(request, response):
@@ -34,32 +33,19 @@ def add_ep_cookie(request, response):
if ep_sessid:
response.set_cookie(
"sessionID",
ep_sessid,
expires=expires,
domain=".2020.fet.at",
path="/"
)
response.set_cookie(
"sessionID",
ep_sessid,
expires=expires,
path="/etherpad"
"sessionID", ep_sessid, expires=expires, domain=".2020.fet.at", path="/"
)
response.set_cookie("sessionID", ep_sessid, expires=expires, path="/etherpad")
return response
def del_ep_cookie(request, response):
if 'sessionID' in request.COOKIES:
ep_sessionID = request.COOKIES['sessionID']
if "sessionID" in request.COOKIES:
ep_sessionID = request.COOKIES["sessionID"]
epc, group = get_ep_client()
epc.deleteSession(sessionID=ep_sessionID)
response.delete_cookie(
"sessionID",
domain=".2020.fet.at",
path="/"
)
response.delete_cookie("sessionID", domain=".2020.fet.at", path="/")
return response

View File

@@ -2,6 +2,6 @@ import os
from django.core.asgi import get_asgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'fet2020.settings')
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "fet2020.settings")
application = get_asgi_application()

View File

@@ -11,23 +11,23 @@ env = environ.Env(
MYSQL_USER=(str),
MYSQL_PASSWORD=(str),
HOST_NAME=(str, "localhost"),
ETHERPAD_PORT=(str,"9001"),
ETHERPAD_HOST=(str,"etherpad2.2020.fet.at")
ETHERPAD_PORT=(str, "9001"),
ETHERPAD_HOST=(str, "etherpad2.2020.fet.at"),
)
# Prints and logs are written to console
# TODO: Change before release
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
'console': {
'class': 'logging.StreamHandler',
"version": 1,
"disable_existing_loggers": False,
"handlers": {
"console": {
"class": "logging.StreamHandler",
},
},
'root': {
'handlers': ['console'],
'level': 'DEBUG',
"root": {
"handlers": ["console"],
"level": "DEBUG",
},
}
@@ -41,106 +41,106 @@ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# See https://docs.djangoproject.com/en/3.0/howto/deployment/checklist/
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = env('DEBUG')
DEBUG = env("DEBUG")
if DEBUG:
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'r37-i7l)vrduzz2-gira+z#u!p!di9#f+%s*5-bb($hg)55@ns'
SECRET_KEY = "r37-i7l)vrduzz2-gira+z#u!p!di9#f+%s*5-bb($hg)55@ns"
else:
SECRET_KEY = env('SECRET_KEY')
SECRET_KEY = env("SECRET_KEY")
ALLOWED_HOSTS = ["127.0.0.1", env('HOST_NAME')]
ALLOWED_HOSTS = ["127.0.0.1", env("HOST_NAME")]
HOST_NAME = env('HOST_NAME')
HOST_NAME = env("HOST_NAME")
DATA_UPLOAD_MAX_MEMORY_SIZE = 1024 * 1024 * 1024
# Application definition
CKEDITOR_UPLOAD_PATH = 'upload'
CKEDITOR_UPLOAD_PATH = "upload"
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.admindocs',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'taggit',
'ckeditor',
'ckeditor_uploader',
'easy_thumbnails',
'rest_framework',
'softhyphen',
'django_crontab',
'django_filters',
'django_static_jquery_ui',
'posts.apps.PostsConfig',
'members.apps.MembersConfig',
'documents.apps.DocumentsConfig',
'blackboard.apps.BlackboardConfig',
'tasks.apps.TasksConfig',
"django.contrib.admin",
"django.contrib.admindocs",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
"taggit",
"ckeditor",
"ckeditor_uploader",
"easy_thumbnails",
"rest_framework",
"softhyphen",
"django_crontab",
"django_filters",
"django_static_jquery_ui",
"posts.apps.PostsConfig",
"members.apps.MembersConfig",
"documents.apps.DocumentsConfig",
"blackboard.apps.BlackboardConfig",
"tasks.apps.TasksConfig",
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
"django.middleware.security.SecurityMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.locale.LocaleMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
]
ROOT_URLCONF = 'fet2020.urls'
ROOT_URLCONF = "fet2020.urls"
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [
os.path.join(BASE_DIR, 'templates'),
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [
os.path.join(BASE_DIR, "templates"),
],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
'django.template.context_processors.i18n',
"APP_DIRS": True,
"OPTIONS": {
"context_processors": [
"django.template.context_processors.debug",
"django.template.context_processors.request",
"django.contrib.auth.context_processors.auth",
"django.contrib.messages.context_processors.messages",
"django.template.context_processors.i18n",
],
},
},
]
WSGI_APPLICATION = 'fet2020.wsgi.application'
WSGI_APPLICATION = "fet2020.wsgi.application"
# Database
# https://docs.djangoproject.com/en/3.0/ref/settings/#databases
if DEBUG:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
"default": {
"ENGINE": "django.db.backends.sqlite3",
"NAME": os.path.join(BASE_DIR, "db.sqlite3"),
}
}
else:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': env('MYSQL_DATABASE'),
'USER': env('MYSQL_USER'),
'PASSWORD': env('MYSQL_PASSWORD'),
'HOST': env('MYSQL_HOST'),
'PORT': env('MYSQL_PORT')
"default": {
"ENGINE": "django.db.backends.mysql",
"NAME": env("MYSQL_DATABASE"),
"USER": env("MYSQL_USER"),
"PASSWORD": env("MYSQL_PASSWORD"),
"HOST": env("MYSQL_HOST"),
"PORT": env("MYSQL_PORT"),
}
}
AUTHENTICATION_BACKENDS = [
'django.contrib.auth.backends.ModelBackend',
"django.contrib.auth.backends.ModelBackend",
]
# Password validation
@@ -148,16 +148,16 @@ AUTHENTICATION_BACKENDS = [
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",
},
]
@@ -165,9 +165,9 @@ AUTH_PASSWORD_VALIDATORS = [
# Internationalization
# https://docs.djangoproject.com/en/3.0/topics/i18n/
LANGUAGE_CODE = 'de-at'
LANGUAGE_CODE = "de-at"
TIME_ZONE = 'CET'
TIME_ZONE = "CET"
USE_I18N = True
@@ -179,28 +179,26 @@ USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.0/howto/static-files/
STATIC_URL = '/assets/'
STATIC_URL = "/assets/"
STATICFILES_DIRS = [
os.path.join(BASE_DIR, "static")
]
STATIC_ROOT = 'assets/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'files/')
MEDIA_URL = '/files/'
STATICFILES_DIRS = [os.path.join(BASE_DIR, "static")]
STATIC_ROOT = "assets/"
MEDIA_ROOT = os.path.join(BASE_DIR, "files/")
MEDIA_URL = "/files/"
TAGGIT_FORCE_LOWERCASE = True
CKEDITOR_CONFIGS = {
'default': {
'stylesSet': [
"default": {
"stylesSet": [
{
"name": 'Überschrift 2',
"element": 'h2',
"name": "Überschrift 2",
"element": "h2",
"attributes": {},
},
{
"name": 'Code',
"element": 'code',
"name": "Code",
"element": "code",
"attributes": {"class": "code-block"},
},
],
@@ -209,41 +207,41 @@ CKEDITOR_CONFIGS = {
# THUMBNAIL
THUMBNAIL_ALIASES = {
'': {
'avatar': {'size': (50, 50), 'crop': True},
'thumb': {'size': (150, 150), 'crop': True},
"": {
"avatar": {"size": (50, 50), "crop": True},
"thumb": {"size": (150, 150), "crop": True},
},
}
# ETHERPAD CLIENT
if DEBUG:
ETHERPAD_CLIENT = {
'url': "http://etherpad:"+env('ETHERPAD_PORT'),
'exturl': env('ETHERPAD_HOST'),
'apikey': "/srv/etherpad/APIKEY.txt"
"url": "http://etherpad:" + env("ETHERPAD_PORT"),
"exturl": env("ETHERPAD_HOST"),
"apikey": "/srv/etherpad/APIKEY.txt",
}
else:
ETHERPAD_CLIENT = {
'url': "http://etherpad:"+env('ETHERPAD_PORT'),
'exturl': urljoin('https://' + env('HOST_NAME'),"etherpad/"),
'apikey': "/app/etherpad/APIKEY.txt"
"url": "http://etherpad:" + env("ETHERPAD_PORT"),
"exturl": urljoin("https://" + env("HOST_NAME"), "etherpad/"),
"apikey": "/app/etherpad/APIKEY.txt",
}
# REST FRAMEWORK
REST_FRAMEWORK={
'DEFAULT_PERMISSION_CLASSES_CLASSES':[
'rest_framework.permissions.AllowAny',
REST_FRAMEWORK = {
"DEFAULT_PERMISSION_CLASSES_CLASSES": [
"rest_framework.permissions.AllowAny",
],
'DEFAULT_AUTHENTICATION_CLASSES':()
"DEFAULT_AUTHENTICATION_CLASSES": (),
}
# DJANGO MAIL
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'buran.htu.tuwien.ac.at'
EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend"
EMAIL_HOST = "buran.htu.tuwien.ac.at"
EMAIL_PORT = 587
EMAIL_USE_TLS = True
# CRON JOBS
CRONJOBS = [
('0 16 * * *', 'posts.cronjobs.check_to_send_agenda_mail'),
("0 16 * * *", "posts.cronjobs.check_to_send_agenda_mail"),
]

View File

@@ -6,29 +6,34 @@ from django.views.generic import RedirectView
from . import views
from posts.viewsets import PostViewSet
from members.urls import member_urlpatterns, jobs_urlpatterns
from members.viewsets import MemberViewSet, JobViewSet, JobGroupViewSet, JobMemberViewSet
from members.viewsets import (
MemberViewSet,
JobViewSet,
JobGroupViewSet,
JobMemberViewSet,
)
from rest_framework import routers
router = routers.DefaultRouter()
router.register(r'posts', PostViewSet)
router.register(r'members', MemberViewSet)
router.register(r'jobgroups', JobGroupViewSet)
router.register(r'jobs', JobViewSet)
router.register(r'jobmembers', JobMemberViewSet)
router.register(r"posts", PostViewSet)
router.register(r"members", MemberViewSet)
router.register(r"jobgroups", JobGroupViewSet)
router.register(r"jobs", JobViewSet)
router.register(r"jobmembers", JobMemberViewSet)
urlpatterns = [
path('posts/', include('posts.urls')),
path('admin/doc/', include('django.contrib.admindocs.urls')),
path('admin/login/', RedirectView.as_view(pattern_name='login')),
path('admin/', admin.site.urls),
path('auth/', include('authentications.urls')),
path('', views.index, name='home'),
path('index.html', views.index, name='home'),
path('ckeditor/', include('ckeditor_uploader.urls')),
path('api/', include(router.urls)),
path('members/', include('members.urls'), name='members'),
path('jobs/', include(jobs_urlpatterns), name='jobs'),
path('member/', include(member_urlpatterns), name='member'),
path('blackboard/', include('blackboard.urls'), name='blackboard'),
path('tasks/', include('tasks.urls'), name='tasks'),
path("posts/", include("posts.urls")),
path("admin/doc/", include("django.contrib.admindocs.urls")),
path("admin/login/", RedirectView.as_view(pattern_name="login")),
path("admin/", admin.site.urls),
path("auth/", include("authentications.urls")),
path("", views.index, name="home"),
path("index.html", views.index, name="home"),
path("ckeditor/", include("ckeditor_uploader.urls")),
path("api/", include(router.urls)),
path("members/", include("members.urls"), name="members"),
path("jobs/", include(jobs_urlpatterns), name="jobs"),
path("member/", include(member_urlpatterns), name="member"),
path("blackboard/", include("blackboard.urls"), name="blackboard"),
path("tasks/", include("tasks.urls"), name="tasks"),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

View File

@@ -1,4 +1,5 @@
from django.shortcuts import render
# from django.http import HttpResponse
from collections import deque
from posts.models import Post, FetMeeting, Event
@@ -34,12 +35,12 @@ def index(request):
featured_meeting = FetMeeting.objects.get_meetings()
context = {
'posts': deque(list(posts)[:5]),
'events': Event.all_events.get_five_events(),
'featured_post': featured_post,
'featured_event': featured_event,
'featured_meeting': featured_meeting,
'tags_list': " ".join(t)
"posts": deque(list(posts)[:5]),
"events": Event.all_events.get_five_events(),
"featured_post": featured_post,
"featured_event": featured_event,
"featured_meeting": featured_meeting,
"tags_list": " ".join(t),
}
return render(request, 'home.html', context)
return render(request, "home.html", context)

View File

@@ -2,6 +2,6 @@ import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'fet2020.settings')
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "fet2020.settings")
application = get_wsgi_application()

View File

@@ -6,13 +6,13 @@ from .forms import MemberForm, JobForm, JobGroupForm
class MemberRoleFilter(admin.SimpleListFilter):
title = _('Rolle')
parameter_name = 'role'
title = _("Rolle")
parameter_name = "role"
def lookups(self, request, model_admin):
return (
('A', _('Aktiv')),
('P', _('Pension')),
("A", _("Aktiv")),
("P", _("Pension")),
)
def queryset(self, request, queryset):
@@ -55,40 +55,53 @@ class MemberAdmin(admin.ModelAdmin):
form = MemberForm
model = Member
fieldsets = (
(None, {
'fields': (
('firstname', 'surname',),
'nickname',
'username',
'mailaccount',
'role',
'description',
'image',
'birthday',
'phone',
'address',
)
}),
(
None,
{
"fields": (
(
"firstname",
"surname",
),
"nickname",
"username",
"mailaccount",
"role",
"description",
"image",
"birthday",
"phone",
"address",
)
},
),
)
inlines = (JobOverviewInline,)
list_display = ['nickname', 'firstname', 'surname', 'mailaccount', 'role']
ordering = ['firstname', ]
search_fields = ['firstname', 'surname', 'nickname', 'mailaccount']
list_display = ["nickname", "firstname", "surname", "mailaccount", "role"]
ordering = [
"firstname",
]
search_fields = ["firstname", "surname", "nickname", "mailaccount"]
list_filter = [MemberRoleFilter]
def add_view(self, request, form_url='', extra_context=None):
def add_view(self, request, form_url="", extra_context=None):
extra_context = extra_context or {}
extra_context['help_text'] = "Fette Schriften sind Pflichtfelder."
extra_context["help_text"] = "Fette Schriften sind Pflichtfelder."
return super().add_view(
request, form_url, extra_context=extra_context,
request,
form_url,
extra_context=extra_context,
)
def change_view(self, request, object_id, form_url='', extra_context=None):
def change_view(self, request, object_id, form_url="", extra_context=None):
extra_context = extra_context or {}
extra_context['help_text'] = "Fette Schriften sind Pflichtfelder."
extra_context["help_text"] = "Fette Schriften sind Pflichtfelder."
return super().change_view(
request, object_id, form_url, extra_context=extra_context,
request,
object_id,
form_url,
extra_context=extra_context,
)
def save_model(self, request, obj, form, change):
@@ -101,22 +114,33 @@ class JobAdmin(admin.ModelAdmin):
model = Job
inlines = (ActiveMemberInline, InactiveMemberInline)
list_display = ['name', ]
ordering = ['name', ]
search_fields = ['name', ]
list_display = [
"name",
]
ordering = [
"name",
]
search_fields = [
"name",
]
def add_view(self, request, form_url='', extra_context=None):
def add_view(self, request, form_url="", extra_context=None):
extra_context = extra_context or {}
extra_context['help_text'] = "Fette Schriften sind Pflichtfelder."
extra_context["help_text"] = "Fette Schriften sind Pflichtfelder."
return super().add_view(
request, form_url, extra_context=extra_context,
request,
form_url,
extra_context=extra_context,
)
def change_view(self, request, object_id, form_url='', extra_context=None):
def change_view(self, request, object_id, form_url="", extra_context=None):
extra_context = extra_context or {}
extra_context['help_text'] = "Fette Schriften sind Pflichfelder."
extra_context["help_text"] = "Fette Schriften sind Pflichfelder."
return super().change_view(
request, object_id, form_url, extra_context=extra_context,
request,
object_id,
form_url,
extra_context=extra_context,
)
def save_model(self, request, obj, form, change):
@@ -127,24 +151,36 @@ class JobAdmin(admin.ModelAdmin):
class JobGroupAdmin(admin.ModelAdmin):
form = JobGroupForm
model = JobGroup
inlines = (JobInline, )
inlines = (JobInline,)
list_display = ['name', 'is_pinned', ]
ordering = ['name', ]
search_fields = ['name', ]
list_display = [
"name",
"is_pinned",
]
ordering = [
"name",
]
search_fields = [
"name",
]
def add_view(self, request, form_url='', extra_context=None):
def add_view(self, request, form_url="", extra_context=None):
extra_context = extra_context or {}
extra_context['help_text'] = "Fette Schriften sind Pflichtfelder."
extra_context["help_text"] = "Fette Schriften sind Pflichtfelder."
return super().add_view(
request, form_url, extra_context=extra_context,
request,
form_url,
extra_context=extra_context,
)
def change_view(self, request, object_id, form_url='', extra_context=None):
def change_view(self, request, object_id, form_url="", extra_context=None):
extra_context = extra_context or {}
extra_context['help_text'] = "Fette Schriften sind Pflichfelder."
extra_context["help_text"] = "Fette Schriften sind Pflichfelder."
return super().change_view(
request, object_id, form_url, extra_context=extra_context,
request,
object_id,
form_url,
extra_context=extra_context,
)
def save_model(self, request, obj, form, change):

View File

@@ -2,4 +2,4 @@ from django.apps import AppConfig
class MembersConfig(AppConfig):
name = 'members'
name = "members"

View File

@@ -10,56 +10,68 @@ class MemberForm(forms.ModelForm):
class Meta:
model = Member
fields = [
'firstname', 'surname', 'nickname', 'username', 'mailaccount', 'role', 'description',
'image', 'birthday', 'phone', 'address',
"firstname",
"surname",
"nickname",
"username",
"mailaccount",
"role",
"description",
"image",
"birthday",
"phone",
"address",
]
widgets = {
'description': CKEditorUploadingWidget(config_name='default')
}
widgets = {"description": CKEditorUploadingWidget(config_name="default")}
labels = {
'description': _("Beschreibung zu der Person"),
'image': _("Porträt"),
'birthday': _("Geburtstag"),
'phone': _("Telefonnummer"),
'address': _("Wohnadresse"),
"description": _("Beschreibung zu der Person"),
"image": _("Porträt"),
"birthday": _("Geburtstag"),
"phone": _("Telefonnummer"),
"address": _("Wohnadresse"),
}
help_texts = {
'image': _(
"Mindestgröße: 150*150 px, Verwendbare Formate: ..."
),
'mailaccount': _(
"Die Mailadresse mit '@fet.at' angeben."
),
"image": _("Mindestgröße: 150*150 px, Verwendbare Formate: ..."),
"mailaccount": _("Die Mailadresse mit '@fet.at' angeben."),
}
class JobForm(forms.ModelForm):
class Meta:
model = Job
fields = ['name', 'shortterm', 'slug', 'job_group',]
fields = [
"name",
"shortterm",
"slug",
"job_group",
]
labels = {
'shortterm': _("Kürzel der Tätigkeit"),
'job_group': _("Tätigkeitsbereich"),
"shortterm": _("Kürzel der Tätigkeit"),
"job_group": _("Tätigkeitsbereich"),
}
class JobGroupForm(forms.ModelForm):
class Meta:
model = JobGroup
fields = ['name', 'shortterm', 'slug', 'description', 'is_pinned',]
fields = [
"name",
"shortterm",
"slug",
"description",
"is_pinned",
]
widgets = {
'description': CKEditorUploadingWidget(config_name='default')
}
widgets = {"description": CKEditorUploadingWidget(config_name="default")}
labels = {
'shortterm': _("Kürzel des Tätigkeitsbereichs"),
'description': _("Beschreibung des Tätigkeitsbereichs"),
'is_pinned': _(
"shortterm": _("Kürzel des Tätigkeitsbereichs"),
"description": _("Beschreibung des Tätigkeitsbereichs"),
"is_pinned": _(
"Dieser Tätigkeitsbereich soll im Fachschaftsbereich angeheftet werden, damit es sofort ersichtlich ist."
),
}

View File

@@ -10,15 +10,20 @@ from easy_thumbnails.fields import ThumbnailerImageField
class ActiveJobMemberManager(models.Manager):
'''
"""
return a list of active member, and members who are still working
'''
"""
def get_all_by_slug(self, slug):
return self.get_queryset().filter(job__job_group__slug=slug).order_by('job__slug', 'job_role', 'member__firstname')
return (
self.get_queryset()
.filter(job__job_group__slug=slug)
.order_by("job__slug", "job_role", "member__firstname")
)
def get_queryset(self):
date_today = timezone.now().date()
qs = super().get_queryset().order_by('member__firstname')
qs = super().get_queryset().order_by("member__firstname")
return qs.filter(
Q(member__role=Member.MemberRole.ACTIVE)
@@ -27,15 +32,20 @@ class ActiveJobMemberManager(models.Manager):
class InactiveJobMemberManager(models.Manager):
'''
"""
return a list of inactive member
'''
"""
def get_all_by_slug(self, slug):
return self.get_queryset().filter(job__job_group__slug=slug).order_by('job__slug', 'job_role', 'member__firstname')
return (
self.get_queryset()
.filter(job__job_group__slug=slug)
.order_by("job__slug", "job_role", "member__firstname")
)
def get_queryset(self):
date_today = timezone.now().date()
qs = super().get_queryset().order_by('member__firstname')
qs = super().get_queryset().order_by("member__firstname")
return qs.filter(
Q(member__role=Member.MemberRole.PENSION)
@@ -45,7 +55,7 @@ class InactiveJobMemberManager(models.Manager):
class JobMemberManager(models.Manager):
def get_members(self, role):
qs = self.get_queryset().order_by('member__firstname')
qs = self.get_queryset().order_by("member__firstname")
return qs.filter(Q(member__role=role))
@@ -82,19 +92,19 @@ class JobGroupManager(models.Manager):
class MemberManager(models.Manager):
def get_queryset(self):
return super().get_queryset().order_by('firstname')
return super().get_queryset().order_by("firstname")
class Member(models.Model):
firstname = models.CharField("Vorname", max_length=128)
surname = models.CharField("Nachname", max_length=128)
nickname = models.CharField("Spitzname", max_length=128)
nickname = models.CharField("Spitzname", max_length=128)
username = models.CharField("Benutzername", blank=True, max_length=128)
mailaccount = models.CharField("Mailadresse", unique=True, max_length=128)
class MemberRole(models.TextChoices):
ACTIVE = 'A', _('Active')
PENSION = 'P', _('Pension')
ACTIVE = "A", _("Active")
PENSION = "P", _("Pension")
role = models.CharField(
"Rolle",
@@ -104,14 +114,16 @@ class Member(models.Model):
)
description = models.TextField(null=True, blank=True)
image = ThumbnailerImageField(upload_to='uploads/members/image/')
image = ThumbnailerImageField(upload_to="uploads/members/image/")
birthday = models.DateField(null=True, blank=True)
phone_error_msg = _((
"Phone number must be entered in the format: +999999999'. Up to 15 digits allowed."
))
phone_regex = RegexValidator(regex=r'^\+?1?\d{9,15}$', message=phone_error_msg)
phone_error_msg = _(
(
"Phone number must be entered in the format: +999999999'. Up to 15 digits allowed."
)
)
phone_regex = RegexValidator(regex=r"^\+?1?\d{9,15}$", message=phone_error_msg)
phone = models.CharField(validators=[phone_regex], max_length=17, blank=True)
address = models.TextField(null=True, blank=True)
@@ -134,15 +146,12 @@ class Member(models.Model):
if self.image.height < 150 or self.image.width < 150:
raise ValidationError(
_("Das Bild ist zu klein. (Höhe: {}, Breite: {})").format(
self.image.height,
self.image.width
self.image.height, self.image.width
)
)
if not "@fet.at" in self.mailaccount:
raise ValidationError(
_("In der Mailadresse fehlt die Domäne.")
)
raise ValidationError(_("In der Mailadresse fehlt die Domäne."))
def __str__(self):
return self.firstname + " " + self.surname
@@ -198,7 +207,7 @@ class Job(models.Model):
def save(self, *args, **kwargs):
if not self.slug:
self.slug = slugify(self.shortterm)
#if type(self.job_group) = str:
# if type(self.job_group) = str:
# self.job_group=JobGroup.objects.filter(slug=self.job)
super().save(*args, **kwargs)
@@ -218,18 +227,20 @@ class JobMember(models.Model):
verbose_name="Tätigkeit",
)
job_start = models.DateField('Job Start')
job_end = models.DateField('Job Ende', null=True, blank=True)
job_start = models.DateField("Job Start")
job_end = models.DateField("Job Ende", null=True, blank=True)
class JobRole(models.TextChoices):
PRESIDENT = ('10', _('VorsitzendeR'))
VICE_PRESIDENT = ('20', _('stv VorsitzendeR'))
SECOND_VICE_PRESIDENT = ('30', _('2. stv VorsitzendeR'))
PERSON_RESPONSIBLE = ('40', _('VerantwortlicheR'))
MEMBER = ('50', _('Mitglied'))
SUBSTITUTE_MEMBER = ('60', _('Ersatzmitglied'))
PRESIDENT = ("10", _("VorsitzendeR"))
VICE_PRESIDENT = ("20", _("stv VorsitzendeR"))
SECOND_VICE_PRESIDENT = ("30", _("2. stv VorsitzendeR"))
PERSON_RESPONSIBLE = ("40", _("VerantwortlicheR"))
MEMBER = ("50", _("Mitglied"))
SUBSTITUTE_MEMBER = ("60", _("Ersatzmitglied"))
job_role = models.CharField(max_length=2, choices=JobRole.choices, default=JobRole.MEMBER)
job_role = models.CharField(
max_length=2, choices=JobRole.choices, default=JobRole.MEMBER
)
objects = models.Manager()
members = JobMemberManager()

View File

@@ -4,65 +4,50 @@ from rest_framework import serializers
class MemberSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Member
fields = ['id',
'firstname',
'surname',
'nickname',
'mailaccount',
'role',
'description',
'image',
'birthday',
fields = [
"id",
"firstname",
"surname",
"nickname",
"mailaccount",
"role",
"description",
"image",
"birthday",
]
class JobGroupSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = JobGroup
fields = [
'id',
'name',
'shortterm',
'slug'
]
fields = ["id", "name", "shortterm", "slug"]
class JobSerializer(serializers.HyperlinkedModelSerializer):
#job_group = JobGroupSerializer()
# job_group = JobGroupSerializer()
job_group = serializers.SlugRelatedField(
slug_field='slug',queryset = JobGroup.objects
)
slug_field="slug", queryset=JobGroup.objects
)
class Meta:
model = Job
fields = [
'id',
'name',
'shortterm',
'job_group',
'slug'
]
fields = ["id", "name", "shortterm", "job_group", "slug"]
class JobMemberSerializer(serializers.HyperlinkedModelSerializer):
#member = MemberSerializer()
#job = JobSerializer()
job = serializers.SlugRelatedField(
slug_field='slug',queryset = Job.objects
)
member= serializers.SlugRelatedField(
slug_field='mailaccount',queryset = Member.objects
)
# member = MemberSerializer()
# job = JobSerializer()
job = serializers.SlugRelatedField(slug_field="slug", queryset=Job.objects)
member = serializers.SlugRelatedField(
slug_field="mailaccount", queryset=Member.objects
)
class Meta:
model = JobMember
fields = [
'id',
'job_start',
'job_end',
'member',
'job',
'job_role'
]
fields = ["id", "job_start", "job_end", "member", "job", "job_role"]
# def create(self, validated_data):
# member_data = validated_data.pop('member')

View File

@@ -4,14 +4,14 @@ from . import views
urlpatterns = [
path('', views.index, name='members'),
path('<str:filter>', views.members_view),
path("", views.index, name="members"),
path("<str:filter>", views.members_view),
]
member_urlpatterns = [
path('<str:member_id>', views.profile_view, name='member'),
path("<str:member_id>", views.profile_view, name="member"),
]
jobs_urlpatterns = [
path('<str:slug>', views.jobs_view, name='jobs'),
path("<str:slug>", views.jobs_view, name="jobs"),
]

View File

@@ -7,6 +7,7 @@ from .models import Member, JobMember, JobGroup, Job
from posts.models import Post
import logging
logger = logging.getLogger(__name__)
@@ -41,7 +42,7 @@ def index(request):
pinned_job_groups, unpinned_job_groups = __get_job_groups()
members = deque(Member.all_members.all())
fs_info = Post.objects.filter(slug='fachschaft-info').first()
fs_info = Post.objects.filter(slug="fachschaft-info").first()
context = {
"pinned_job_groups": pinned_job_groups,
@@ -50,14 +51,16 @@ def index(request):
"fs_info": fs_info,
}
return render(request, 'members/index.html', context)
return render(request, "members/index.html", context)
def jobs_view(request, slug=None):
pinned_job_groups, unpinned_job_groups = __get_job_groups()
try:
description = JobGroup.all_jobgroups.filter(slug=slug).values().first()['description']
description = (
JobGroup.all_jobgroups.filter(slug=slug).values().first()["description"]
)
except Exception as e:
logger.info("Wrong job '{}'".format(slug))
raise Http404("wrong job")
@@ -71,7 +74,7 @@ def jobs_view(request, slug=None):
"job_members": job_members,
}
return render(request, 'members/index.html', context)
return render(request, "members/index.html", context)
def members_view(request, filter=None):
@@ -83,7 +86,7 @@ def members_view(request, filter=None):
logger.info("Wrong member role '{}'".format(filter))
raise Http404("no member role")
fs_info = Post.objects.filter(slug='fachschaft-info').first()
fs_info = Post.objects.filter(slug="fachschaft-info").first()
context = {
"pinned_job_groups": pinned_job_groups,
@@ -92,7 +95,7 @@ def members_view(request, filter=None):
"fs_info": fs_info,
}
return render(request, 'members/index.html', context)
return render(request, "members/index.html", context)
def profile_view(request, member_id=None):
@@ -112,4 +115,4 @@ def profile_view(request, member_id=None):
"jobs": jobs,
}
return render(request, 'members/member.html', context)
return render(request, "members/member.html", context)

View File

@@ -2,54 +2,63 @@ from django_filters.rest_framework import DjangoFilterBackend
from rest_framework import viewsets
from .models import Member, JobMember, JobGroup, Job
from .serializers import MemberSerializer, JobSerializer, JobGroupSerializer, JobMemberSerializer
from .serializers import (
MemberSerializer,
JobSerializer,
JobGroupSerializer,
JobMemberSerializer,
)
class MemberViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows users to be viewed or edited.
"""
queryset = Member.all_members.order_by('nickname')
queryset = Member.all_members.order_by("nickname")
serializer_class = MemberSerializer
#permission_classes = [permissions.IsAuthenticated]
# permission_classes = [permissions.IsAuthenticated]
filter_backends = [DjangoFilterBackend]
filterset_fields = ['nickname','mailaccount']
#lookup_field = 'name'
filterset_fields = ["nickname", "mailaccount"]
# lookup_field = 'name'
def pre_save(self, obj):
obj.image = self.request.FILES.get('image')
obj.image = self.request.FILES.get("image")
class JobGroupViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows users to be viewed or edited.
"""
queryset = JobGroup.all_jobgroups.all()
serializer_class = JobGroupSerializer
filter_backends = [DjangoFilterBackend]
filterset_fields = ['name','slug']
#lookup_field = 'name'
filterset_fields = ["name", "slug"]
# lookup_field = 'name'
class JobViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows users to be viewed or edited.
"""
queryset = Job.objects.all()
serializer_class = JobSerializer
filter_backends = [DjangoFilterBackend]
filterset_fields = ['name','slug']
#lookup_field = 'slug'
filterset_fields = ["name", "slug"]
# lookup_field = 'slug'
class JobMemberViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows users to be viewed or edited.
"""
queryset = JobMember.objects.all()
serializer_class = JobMemberSerializer
filter_backends = [DjangoFilterBackend]
filterset_fields = ['member','job','job_role','job_start']
#lookup_field = 'nickname'
filterset_fields = ["member", "job", "job_role", "job_start"]
# lookup_field = 'nickname'

View File

@@ -13,7 +13,7 @@ admin.site.unregister(taggit.models.Tag)
def make_fetmeeting(self, request, queryset):
qs = self.get_queryset(request).filter(id=request.POST['_selected_action']).first()
qs = self.get_queryset(request).filter(id=request.POST["_selected_action"]).first()
failed = False
agenda_key = None
@@ -24,7 +24,7 @@ def make_fetmeeting(self, request, queryset):
except Exception as e:
self.message_user(
request,
_('Das Agenda konnte nicht erstellt werden. Error: %s') % str(e),
_("Das Agenda konnte nicht erstellt werden. Error: %s") % str(e),
messages.ERROR,
)
failed = True
@@ -34,14 +34,14 @@ def make_fetmeeting(self, request, queryset):
except Exception as e:
self.message_user(
request,
_('Das Protokoll konnte nicht erstellt werden. Error: %s') % str(e),
_("Das Protokoll konnte nicht erstellt werden. Error: %s") % str(e),
messages.ERROR,
)
failed = True
if not failed:
queryset.update(
post_type='F',
post_type="F",
has_agenda=True,
has_protocol=True,
agenda_key=agenda_key,
@@ -49,7 +49,8 @@ def make_fetmeeting(self, request, queryset):
)
self.message_user(
request,
_('Das Event %s wurde erfolgreich in eine FET Sitzung konvertiert.') % (qs.title),
_("Das Event %s wurde erfolgreich in eine FET Sitzung konvertiert.")
% (qs.title),
messages.SUCCESS,
)
@@ -60,22 +61,27 @@ make_fetmeeting.short_description = "In eine Fachschaftssitzung konvertieren"
class PostAdmin(admin.ModelAdmin):
form = PostForm
model = Post
list_filter = ['is_pinned', 'is_hidden']
list_display = ['title', 'slug', 'public_date', 'is_pinned', 'is_hidden']
ordering = ['is_hidden', '-public_date']
list_filter = ["is_pinned", "is_hidden"]
list_display = ["title", "slug", "public_date", "is_pinned", "is_hidden"]
ordering = ["is_hidden", "-public_date"]
def add_view(self, request, form_url='', extra_context=None):
def add_view(self, request, form_url="", extra_context=None):
extra_context = extra_context or {}
extra_context['help_text'] = "Fette Schriften sind Pflichtfelder."
extra_context["help_text"] = "Fette Schriften sind Pflichtfelder."
return super().add_view(
request, form_url, extra_context=extra_context,
request,
form_url,
extra_context=extra_context,
)
def change_view(self, request, object_id, form_url='', extra_context=None):
def change_view(self, request, object_id, form_url="", extra_context=None):
extra_context = extra_context or {}
extra_context['help_text'] = "Fette Schriften sind Pflichtfelder."
extra_context["help_text"] = "Fette Schriften sind Pflichtfelder."
return super().change_view(
request, object_id, form_url, extra_context=extra_context,
request,
object_id,
form_url,
extra_context=extra_context,
)
def save_model(self, request, obj, form, change):
@@ -98,9 +104,9 @@ class PostAdmin(admin.ModelAdmin):
class EventAdmin(PostAdmin):
form = EventForm
model = Event
list_filter = ['is_pinned']
list_display = ['title', 'slug', 'event_start', 'public_date', 'is_pinned']
ordering = ['-event_start']
list_filter = ["is_pinned"]
list_display = ["title", "slug", "event_start", "public_date", "is_pinned"]
ordering = ["-event_start"]
actions = [make_fetmeeting]
@@ -113,7 +119,7 @@ class FetMeetingAdmin(EventAdmin):
form = FetMeetingForm
model = FetMeeting
list_filter = []
list_display = ['title', 'slug', 'event_start', 'public_date']
list_display = ["title", "slug", "event_start", "public_date"]
actions = []

View File

@@ -2,4 +2,4 @@ from django.apps import AppConfig
class PostsConfig(AppConfig):
name = 'posts'
name = "posts"

View File

@@ -10,14 +10,23 @@ from .models import Post, Event, News, FetMeeting
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = ['title', 'subtitle', 'tags', 'image', 'body', 'slug', 'author', 'public_date']
fields = [
"title",
"subtitle",
"tags",
"image",
"body",
"slug",
"author",
"public_date",
]
widgets = {'body': CKEditorUploadingWidget(config_name='default')}
widgets = {"body": CKEditorUploadingWidget(config_name="default")}
class Media:
js = (
'js/auto_slug.js', # automatic slag completion via ajax
'js/tag_completion.js', # to get a list for tag autocompletion via ajax
"js/auto_slug.js", # automatic slag completion via ajax
"js/tag_completion.js", # to get a list for tag autocompletion via ajax
)
@@ -25,106 +34,124 @@ class NewsForm(PostForm):
class Meta:
model = News
fields = [
'title', 'subtitle', 'tags', 'image', 'body', 'slug', 'author', 'public_date',
'is_pinned', 'is_hidden',
"title",
"subtitle",
"tags",
"image",
"body",
"slug",
"author",
"public_date",
"is_pinned",
"is_hidden",
]
labels = {
'title': _("Titel"),
'subtitle': _("Untertitel"),
'image': _("Hintergrundbild"),
'body': _("Text"),
'author': _("Autor"),
'public_date': _("Veröffentlichung"),
'is_pinned': _("Post anheften"),
'is_hidden': _("Post verstecken"),
"title": _("Titel"),
"subtitle": _("Untertitel"),
"image": _("Hintergrundbild"),
"body": _("Text"),
"author": _("Autor"),
"public_date": _("Veröffentlichung"),
"is_pinned": _("Post anheften"),
"is_hidden": _("Post verstecken"),
}
help_texts = {
'tags': _(
"tags": _(
"Die Hashtags ohne '#' eintragen, und mit Komma kann man mehrere Tags anfügen."
),
'image': _(
"Verwendbare Formate: ..."
),
'is_pinned': _(
"image": _("Verwendbare Formate: ..."),
"is_pinned": _(
"Dieser Post soll an die Startseite als erster Post angeheftet werden."
),
'is_hidden': _(
"is_hidden": _(
"Dieser Post soll im News Feed nicht auftauchen, z.B. Impressum."
),
}
widgets = {'body': CKEditorUploadingWidget(config_name='default')}
widgets = {"body": CKEditorUploadingWidget(config_name="default")}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) # to get the self.fields set
self.fields['author'].queryset = self.fields['author'].queryset.order_by('username')
self.fields["author"].queryset = self.fields["author"].queryset.order_by(
"username"
)
class EventForm(PostForm):
class Meta:
model = Event
fields = [
'title', 'subtitle', 'tags', 'image', 'body', 'event_start', 'event_end',
'event_place', 'slug', 'author', 'public_date', 'is_pinned',
"title",
"subtitle",
"tags",
"image",
"body",
"event_start",
"event_end",
"event_place",
"slug",
"author",
"public_date",
"is_pinned",
]
labels = {
'title': _("Titel"),
'subtitle': _("Untertitel"),
'image': _("Hintergrundbild"),
'body': _("Text"),
'event_start': _("Start des Events"),
'event_end': _("Ende des Events"),
'event_place': _("Ort des Events"),
'author': _("Autor"),
'public_date': _("Veröffentlichung"),
'is_pinned': _("Event anheften"),
"title": _("Titel"),
"subtitle": _("Untertitel"),
"image": _("Hintergrundbild"),
"body": _("Text"),
"event_start": _("Start des Events"),
"event_end": _("Ende des Events"),
"event_place": _("Ort des Events"),
"author": _("Autor"),
"public_date": _("Veröffentlichung"),
"is_pinned": _("Event anheften"),
}
help_texts = {
'tags': _(
"tags": _(
"Die Hashtags ohne '#' eintragen, und mit Komma kann man mehrere Tags anfügen."
),
'image': _(
"Verwendbare Formate: "
),
'is_pinned': _(
"image": _("Verwendbare Formate: "),
"is_pinned": _(
"Dieses Event soll an die Startseite als erster Post angeheftet werden."
),
}
widgets = {'body': CKEditorUploadingWidget(config_name='default')}
widgets = {"body": CKEditorUploadingWidget(config_name="default")}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) # to get the self.fields set
self.fields['author'].queryset = self.fields['author'].queryset.order_by('username')
self.fields["author"].queryset = self.fields["author"].queryset.order_by(
"username"
)
self.fields['event_start'].required = True
self.fields['event_end'].required = False
self.fields["event_start"].required = True
self.fields["event_end"].required = False
if 'event_place' in self.fields:
self.fields['event_place'].required = True
if "event_place" in self.fields:
self.fields["event_place"].required = True
class FetMeetingForm(PostForm):
# agenda_html = forms.CharField(widget = forms.TextInput())
class Meta:
model = FetMeeting
fields = ['event_start', 'event_end', 'tags']#, 'has_agenda', 'has_protocol']
fields = ["event_start", "event_end", "tags"] # , 'has_agenda', 'has_protocol']
labels = {
'event_start': _("Start der Sitzung"),
'event_end': _("Ende der Sitzung")#,
# 'has_agenda': _("Agenda"),
# 'has_protocol': _("Protokoll"),
"event_start": _("Start der Sitzung"),
"event_end": _("Ende der Sitzung") # ,
# 'has_agenda': _("Agenda"),
# 'has_protocol': _("Protokoll"),
}
help_texts = {
'tags': _(
"tags": _(
"Die Hashtags ohne '#' eintragen, und mit Komma kann man mehrere Tags anfügen."
)#,
) # ,
#'has_agenda': _("Agenda zur Sitzung hinzufügen."),
#'has_protocol': _("Protokoll zur Sitzung hinzufügen."),
}
@@ -132,13 +159,13 @@ class FetMeetingForm(PostForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) # to get the self.fields set
self.fields['event_start'].required = True
self.fields['event_end'].required = False
self.fields["event_start"].required = True
self.fields["event_end"].required = False
#self.fields['has_agenda'].initial = True
#self.fields['has_protocol'].initial = True
# self.fields['has_agenda'].initial = True
# self.fields['has_protocol'].initial = True
tags = []
tags.append(Tag())
tags[0].name = "fachschaft"
self.fields['tags'].initial = tags
self.fields["tags"].initial = tags

View File

@@ -3,15 +3,22 @@ from django.core.mail import send_mail
def send_agenda_mail(date, time, slug):
msg = "Liebe Alle,\n\n" \
"wir haben am " + str(date) + " um " + str(time) + " wieder Sitzung.\n" \
"du hast noch bis morgen Zeit, weitere Themen auf die Agenda zu schreiben: " \
+ settings.HOST_NAME + '/posts/' + str(slug) + ".\n\n" \
msg = (
"Liebe Alle,\n\n"
"wir haben am " + str(date) + " um " + str(time) + " wieder Sitzung.\n"
"du hast noch bis morgen Zeit, weitere Themen auf die Agenda zu schreiben: "
+ settings.HOST_NAME
+ "/posts/"
+ str(slug)
+ ".\n\n"
"LG deine FET"
)
send_mail(
subject = 'Test - Agenda der FET Sitzung von ' + str(date),
message = msg,
from_email = 'patrick@fet.at',
recipient_list = ['all@fet.at', ],
subject="Test - Agenda der FET Sitzung von " + str(date),
message=msg,
from_email="patrick@fet.at",
recipient_list=[
"all@fet.at",
],
)

View File

@@ -5,23 +5,32 @@ from django.utils import timezone
class PostManager(models.Manager):
def get_queryset(self):
return super().get_queryset().order_by('-public_date')
return super().get_queryset().order_by("-public_date")
def get_visible_articles(self):
return self.get_queryset().filter(is_hidden=False)
def all_post_with_date(self):
return self.get_queryset().filter(Q(event_start__isnull=False) & Q(event_end__isnull=False)).order_by('-event_start')
return (
self.get_queryset()
.filter(Q(event_start__isnull=False) & Q(event_end__isnull=False))
.order_by("-event_start")
)
class ArticleManager(models.Manager):
"""
Provide a query set only for "Article"
regular fet meetings should not be contained in the news stream
"""
def get_queryset(self):
return super().get_queryset().filter(
Q(post_type='E')
| Q(post_type='N')
).order_by('-public_date')
return (
super()
.get_queryset()
.filter(Q(post_type="E") | Q(post_type="N"))
.order_by("-public_date")
)
def get_visible_articles(self):
return self.get_queryset().filter(is_hidden=False)
@@ -34,8 +43,9 @@ class NewsManager(models.Manager):
"""
Provide a query set only for "News"
"""
def get_queryset(self):
return super().get_queryset().filter(post_type='N').order_by('-public_date')
return super().get_queryset().filter(post_type="N").order_by("-public_date")
def get_visible_articles(self):
return self.get_queryset().filter(is_hidden=False)
@@ -45,12 +55,17 @@ class AllEventManager(models.Manager):
"""
Provide a query set for all events ("Event" and "Fet Meeting")
"""
def get_queryset(self):
return super().get_queryset().filter(Q(post_type='E') | Q(post_type='F'))
return super().get_queryset().filter(Q(post_type="E") | Q(post_type="F"))
def get_five_events(self):
date_today = timezone.now()
return self.get_queryset().filter(event_start__gt=date_today).order_by('event_start')[:5]
return (
self.get_queryset()
.filter(event_start__gt=date_today)
.order_by("event_start")[:5]
)
class EventManager(models.Manager):
@@ -58,32 +73,50 @@ class EventManager(models.Manager):
Provide a query set only for "Events"
regular fet meetings should not be contained in the news stream
"""
def get_queryset(self):
return super().get_queryset().filter(post_type='E')
return super().get_queryset().filter(post_type="E")
def get_future_events(self):
date_today = timezone.now()
return self.get_queryset().filter(event_start__gt=date_today).order_by('event_start')
return (
self.get_queryset()
.filter(event_start__gt=date_today)
.order_by("event_start")
)
def get_past_events(self):
date_today = timezone.now()
return self.get_queryset().filter(event_start__lt=date_today).order_by('-event_start')
return (
self.get_queryset()
.filter(event_start__lt=date_today)
.order_by("-event_start")
)
class FetMeetingManager(models.Manager):
"""
Provide a query set only for "Fet Meeting"
"""
def get_queryset(self):
return super().get_queryset().filter(post_type='F')
return super().get_queryset().filter(post_type="F")
def _get_future_events(self):
date_today = timezone.now()
return self.get_queryset().filter(event_start__gt=date_today).order_by('event_start')
return (
self.get_queryset()
.filter(event_start__gt=date_today)
.order_by("event_start")
)
def _get_past_events(self):
date_today = timezone.now()
return self.get_queryset().filter(event_start__lt=date_today).order_by('-event_start')
return (
self.get_queryset()
.filter(event_start__lt=date_today)
.order_by("-event_start")
)
def get_meetings(self):
meetings = []

View File

@@ -133,6 +133,7 @@ class Post(models.Model):
)
html = None
return html
@property
def protocol_html(self):
"Protocol HTML from Etherpad Pad"
@@ -196,7 +197,7 @@ class Post(models.Model):
def get_agenda_key(self):
"""Create a Etherpad Id for the Pad associated to this post.
Creates the pad if it doesn't exist"""
Creates the pad if it doesn't exist"""
if not self.slug:
return None
return create_pad_for_post(self.slug, typ="agenda")
@@ -255,9 +256,10 @@ class Post(models.Model):
def clean(self):
if self.event_end and self.event_end < self.event_start:
raise ValidationError(_("Das Ende des Events liegt vor dem Beginn."))
if self.event_start and self.post_type not in ['E','F']:
if self.event_start and self.post_type not in ["E", "F"]:
raise ValidationError("Für diesen Post Typ ist kein Event Start zulässig")
super().clean()
def save(self, *args, **kwargs):
# save the post with some defaults
if not self.public_date:
@@ -307,9 +309,9 @@ class Event(Post):
verbose_name = "Event"
verbose_name_plural = "Events"
def __init__(self,*args,**kwargs):
super().__init__(*args,**kwargs)
self.post_type='E'
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.post_type = "E"
def clean(self):
if not self.event_start:
@@ -334,9 +336,9 @@ class FetMeeting(Event):
verbose_name = "Fet Sitzung"
verbose_name_plural = "Fet Sitzungen"
def __init__(self,*args,**kwargs):
super().__init__(*args,**kwargs)
self.post_type='F'
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.post_type = "F"
def __get_slug(self):
slug = slugify(self.event_start.date()) + "-" + slugify("Fachschaftssitzung")
@@ -349,34 +351,33 @@ class FetMeeting(Event):
return slug
# def __get_agenda_key(self):
# if not self.slug:
# return None##
#
# try:
# agenda_key = createPadifNotExists(self.slug + "-agenda")
# except Exception as error:
# raise ValidationError(
# _("Die Agenda konnte nicht erstellt werden. Error: %(error)s"),
# params={"error": str(error)},
# ) from error
#
# return agenda_key
# def __get_protocol_key(self):
# if not self.slug:
# return None#
#
# try:
# protocol_key = createPadifNotExists(self.slug + "-protocol")
# except URLError as error:
# raise ValidationError(
# _("Das Protokoll konnte nicht erstellt werden. Error: %(error)s"),
# params={"error": str(error)},
# ) from error#
#
# return protocol_key
# def __get_agenda_key(self):
# if not self.slug:
# return None##
#
# try:
# agenda_key = createPadifNotExists(self.slug + "-agenda")
# except Exception as error:
# raise ValidationError(
# _("Die Agenda konnte nicht erstellt werden. Error: %(error)s"),
# params={"error": str(error)},
# ) from error
#
# return agenda_key
# def __get_protocol_key(self):
# if not self.slug:
# return None#
#
# try:
# protocol_key = createPadifNotExists(self.slug + "-protocol")
# except URLError as error:
# raise ValidationError(
# _("Das Protokoll konnte nicht erstellt werden. Error: %(error)s"),
# params={"error": str(error)},
# ) from error#
#
# return protocol_key
def clean(self):
super().clean()

View File

@@ -5,33 +5,34 @@ from rest_framework import serializers
class PostSerializer(serializers.HyperlinkedModelSerializer):
agenda_html = serializers.CharField(required=False)
tag_string = serializers.CharField(required=False,read_only=True)
imageurl = serializers.CharField(required=False,read_only=True)
tag_string = serializers.CharField(required=False, read_only=True)
imageurl = serializers.CharField(required=False, read_only=True)
class Meta:
model = Post
fields = [
'slug',
'title',
'subtitle',
'body',
'url',
'post_type',
'public_date',
'legacy_id',
'image',
'event_start',
'event_end',
'is_hidden',
'agenda_html',
'protocol_html',
'has_agenda',
'has_protocol',
'tag_string',
'imageurl'
"slug",
"title",
"subtitle",
"body",
"url",
"post_type",
"public_date",
"legacy_id",
"image",
"event_start",
"event_end",
"is_hidden",
"agenda_html",
"protocol_html",
"has_agenda",
"has_protocol",
"tag_string",
"imageurl"
# 'author',
]
extra_kwargs={
'agenda_html': {"required": False},
'protocol_html': {"required": False}
extra_kwargs = {
"agenda_html": {"required": False},
"protocol_html": {"required": False},
}

View File

@@ -3,10 +3,10 @@ from . import views
urlpatterns = [
path('func/tag_complete', views.tag_complete),
path('func/slug_calc', views.slug_calc),
path('t/<str:tag>', views.tags, name='posts.tags'),
path('', views.index, name='posts.index'),
path('fet_calendar.ics', views.calendar, name='posts.calendar'),
path('<str:id>', views.show, name='posts.show'),
path("func/tag_complete", views.tag_complete),
path("func/slug_calc", views.slug_calc),
path("t/<str:tag>", views.tags, name="posts.tags"),
path("", views.index, name="posts.index"),
path("fet_calendar.ics", views.calendar, name="posts.calendar"),
path("<str:id>", views.show, name="posts.show"),
]

View File

@@ -27,7 +27,7 @@ def index(request):
"Index von aktuellen Posts"
posts = deque(Post.objects.get_visible_articles().order_by("-public_date"))
taglist = map(lambda post : post.tags, posts)
taglist = map(lambda post: post.tags, posts)
return render(request, "posts/index.html", {"posts": posts, "tags_list": taglist})
@@ -48,7 +48,6 @@ def tags(request, tag=""):
posts = deque(Post.objects.get_visible_articles().filter(tags__name=tag))
featured_post = Post.objects.get_visible_articles().filter(slug=tag).first()
job_members = JobMember.active_member.get_all_by_slug(slug=tag)
author_image = None
@@ -86,25 +85,21 @@ def show(request, id=None):
ep_agenda_link = "#"
ep_protocol_link = "#"
if p.has_agenda:# and p.agenda_key:
if p.has_agenda: # and p.agenda_key:
try:
ep_agenda_link = get_pad_link(p.agenda_key)
except Exception as e:
logger.error(
"Can't get the agenda link from '%s'. Error: %s",
p.agenda_key,
e
"Can't get the agenda link from '%s'. Error: %s", p.agenda_key, e
)
ep_agenda_link = "#"
if p.has_protocol:# and p.protocol_key:
if p.has_protocol: # and p.protocol_key:
try:
ep_protocol_link = get_pad_link(p.protocol_key)
except Exception as e:
logger.error(
"Can't get the protocol link from '%s. Error: %s",
p.protocol_key, e
"Can't get the protocol link from '%s. Error: %s", p.protocol_key, e
)
ep_protocol_link = "#"
@@ -125,8 +120,7 @@ def show(request, id=None):
try:
response = add_ep_cookie(request, response)
except Exception as e:
logger.info(
"Etherpad Server doesn't work. Error: %s", e)
logger.info("Etherpad Server doesn't work. Error: %s", e)
return response

View File

@@ -8,23 +8,33 @@ class TaskAdmin(admin.ModelAdmin):
form = TaskAdminForm
model = Task
fieldsets = (
(None, {
'fields': (
'title',
'task_list',
'assigned_to',
'due_date',
'completed',
'completed_date',
'note',
'priority',
)
}),
(
None,
{
"fields": (
"title",
"task_list",
"assigned_to",
"due_date",
"completed",
"completed_date",
"note",
"priority",
)
},
),
)
list_display = ['title', 'task_list', 'assigned_to', 'due_date', 'completed', 'priority']
list_filter = ('task_list', )
search_fields = ('title', )
list_display = [
"title",
"task_list",
"assigned_to",
"due_date",
"completed",
"priority",
]
list_filter = ("task_list",)
search_fields = ("title",)
def save_model(self, request, obj, form, change):
obj.created_by = request.user

View File

@@ -2,4 +2,4 @@ from django.apps import AppConfig
class TasksConfig(AppConfig):
name = 'tasks'
name = "tasks"

View File

@@ -7,29 +7,31 @@ from .models import Task, TaskList
class DateInput(forms.DateInput):
input_type = 'date'
input_type = "date"
class TaskAdminForm(forms.ModelForm):
class Meta:
model = Task
fields = '__all__'
fields = "__all__"
labels = {
'title': _('Titel'),
'task_list': _('Aufgabenbereich'),
'due_date': _('Fälligkeit'),
'completed': _('Abgeschlossen'),
'completed_date': _('Datum der Fertigstellung'),
'assigned_to': _('Zuweisen an'),
'note': _('Notizen'),
'priority': _('Priorität'),
"title": _("Titel"),
"task_list": _("Aufgabenbereich"),
"due_date": _("Fälligkeit"),
"completed": _("Abgeschlossen"),
"completed_date": _("Datum der Fertigstellung"),
"assigned_to": _("Zuweisen an"),
"note": _("Notizen"),
"priority": _("Priorität"),
}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) # to get the self.fields set
self.fields['assigned_to'].empty_label = "Alle"
self.fields['assigned_to'].queryset = self.fields['assigned_to'].queryset.order_by('username')
self.fields["assigned_to"].empty_label = "Alle"
self.fields["assigned_to"].queryset = self.fields[
"assigned_to"
].queryset.order_by("username")
class TaskForm(forms.ModelForm):
@@ -37,39 +39,41 @@ class TaskForm(forms.ModelForm):
model = Task
fields = [
'title',
'task_list',
'due_date',
'assigned_to',
"title",
"task_list",
"due_date",
"assigned_to",
]
labels = {
'title': _('Titel des Tasks'),
'task_list': _('Task-Gruppe'),
'due_date': _('Fälligkeitsdatum'),
'assigned_to': _('Zuweisen an'),
"title": _("Titel des Tasks"),
"task_list": _("Task-Gruppe"),
"due_date": _("Fälligkeitsdatum"),
"assigned_to": _("Zuweisen an"),
}
widgets = {
'due_date': DateInput(
format=('%d-%m-%Y'),
"due_date": DateInput(
format=("%d-%m-%Y"),
)
}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) # to get the self.fields set
self.fields['assigned_to'].empty_label = "Alle"
self.fields['assigned_to'].queryset = self.fields['assigned_to'].queryset.order_by('username')
self.fields["assigned_to"].empty_label = "Alle"
self.fields["assigned_to"].queryset = self.fields[
"assigned_to"
].queryset.order_by("username")
class TaskListForm(forms.ModelForm):
users = forms.ModelMultipleChoiceField(
label="Benutzer",
help_text="Es können nur die Benutzer ausgewählt werden, die sich auf der Homepage angemeldet haben.",
queryset=User.objects.all().order_by('username'),
widget=FilteredSelectMultiple("User", is_stacked=False)
queryset=User.objects.all().order_by("username"),
widget=FilteredSelectMultiple("User", is_stacked=False),
)
class Meta:
model = TaskList
fields = '__all__'
fields = "__all__"

View File

@@ -7,7 +7,7 @@ from django.utils import timezone
class TaskQuerySet(models.QuerySet):
def get_ordered(self):
return self.order_by('task_list')
return self.order_by("task_list")
class TaskManager(models.Manager):
@@ -16,7 +16,11 @@ class TaskManager(models.Manager):
qs = self.get_queryset().get_ordered().filter(assigned_to__id=user)
if all_tasks:
qs_tmp = self.get_queryset().get_ordered().filter(Q(assigned_to=None) & Q(task_list__users__id__exact=user))
qs_tmp = (
self.get_queryset()
.get_ordered()
.filter(Q(assigned_to=None) & Q(task_list__users__id__exact=user))
)
qs = (qs | qs_tmp).distinct()
if not completed:
@@ -49,7 +53,9 @@ class TaskList(models.Model):
class Task(models.Model):
title = models.CharField(verbose_name="Titel", max_length=140)
task_list = models.ForeignKey(TaskList, verbose_name="Aufgabenbereich", on_delete=models.CASCADE, null=True)
task_list = models.ForeignKey(
TaskList, verbose_name="Aufgabenbereich", on_delete=models.CASCADE, null=True
)
created_date = models.DateTimeField(auto_now_add=True)
due_date = models.DateField(verbose_name="Fälligkeit", blank=True, null=True)
@@ -72,7 +78,9 @@ class Task(models.Model):
)
note = models.TextField(verbose_name="Notizen", blank=True, null=True)
priority = models.PositiveIntegerField(verbose_name="Priorität", blank=True, null=True)
priority = models.PositiveIntegerField(
verbose_name="Priorität", blank=True, null=True
)
objects = models.Manager()
taskmanager = TaskManager()

View File

@@ -4,5 +4,5 @@ from . import views
urlpatterns = [
path('', views.index, name='tasks'),
path("", views.index, name="tasks"),
]

View File

@@ -17,8 +17,8 @@ def index(request):
show_tasklist = None
show_all_tasks = True
if request.method == 'POST':
if 'btn_input' in request.POST:
if request.method == "POST":
if "btn_input" in request.POST:
form = TaskForm(request.POST)
if form.is_valid():
@@ -29,13 +29,18 @@ def index(request):
task.created_by = request.user
task.save()
else:
messages.info(request, "User '{}' ist nicht in der Liste von Task-Gruppe '{}'.".format(task.assigned_to, task.task_list.name))
messages.info(
request,
"User '{}' ist nicht in der Liste von Task-Gruppe '{}'.".format(
task.assigned_to, task.task_list.name
),
)
else:
task.created_by = request.user
task.save()
elif 'btn_checkbox' in request.POST:
for task_id in request.POST.getlist('checkbox'):
elif "btn_checkbox" in request.POST:
for task_id in request.POST.getlist("checkbox"):
task = Task.objects.get(id=task_id)
if not task.completed:
@@ -43,27 +48,31 @@ def index(request):
task.completed_date = timezone.now().date()
task.save()
elif 'btn_user' in request.POST:
if request.POST['action'] == 'show_incompleted':
elif "btn_user" in request.POST:
if request.POST["action"] == "show_incompleted":
current_action = False
else:
current_action = True
if request.POST['tasklist'] != 'all':
show_tasklist = TaskList.objects.filter(id=request.POST['tasklist']).first()
if request.POST["tasklist"] != "all":
show_tasklist = TaskList.objects.filter(
id=request.POST["tasklist"]
).first()
if request.POST['tasks'] == 'all':
if request.POST["tasks"] == "all":
show_all_tasks = True
else:
show_all_tasks = False
form = TaskForm()
tasks = deque(Task.taskmanager.get_tasks(
user=current_user,
completed=current_action,
task_list=show_tasklist,
all_tasks=show_all_tasks
))
tasks = deque(
Task.taskmanager.get_tasks(
user=current_user,
completed=current_action,
task_list=show_tasklist,
all_tasks=show_all_tasks,
)
)
tasklists = deque(TaskList.objects.all())
context = {
@@ -74,4 +83,4 @@ def index(request):
"current_action": current_action,
}
return render(request, 'tasks/index.html', context)
return render(request, "tasks/index.html", context)