diff --git a/AKPlan/apps.py b/AKPlan/apps.py
index f18da123bf48684c2fda835ceb479dadd24bf758..bf67895b111a417a6d3894c859bf406c82ded869 100644
--- a/AKPlan/apps.py
+++ b/AKPlan/apps.py
@@ -2,4 +2,7 @@ from django.apps import AppConfig
 
 
 class AkplanConfig(AppConfig):
+    """
+    App configuration (default, only specifies name of the app)
+    """
     name = 'AKPlan'
diff --git a/AKPlan/templatetags/color_gradients.py b/AKPlan/templatetags/color_gradients.py
index 1a9f96fd87eda8e405894eef648e048d81e87d32..2574efbcb425752fb35d6159ac3bb59a7df9f132 100644
--- a/AKPlan/templatetags/color_gradients.py
+++ b/AKPlan/templatetags/color_gradients.py
@@ -1,7 +1,7 @@
 # gradients based on http://bsou.io/posts/color-gradients-with-python
 
 
-def hex_to_rgb(hex):
+def hex_to_rgb(hex): #pylint: disable=redefined-builtin
     """
     Convert hex color to RGB color code
     :param hex: hex encoded color
@@ -23,8 +23,7 @@ def rgb_to_hex(rgb):
     """
     # Components need to be integers for hex to make sense
     rgb = [int(x) for x in rgb]
-    return "#"+"".join(["0{0:x}".format(v) if v < 16 else
-                        "{0:x}".format(v) for v in rgb])
+    return "#"+"".join([f"0{v:x}" if v < 16 else f"{v:x}" for v in rgb])
 
 
 def linear_blend(start_hex, end_hex, position):
diff --git a/AKPlan/templatetags/tags_AKPlan.py b/AKPlan/templatetags/tags_AKPlan.py
index 8b30bfabd34b501a858351d6b1e384b4fe39e5bb..ae259be4cc042ede588f4b12867dfabfc37b15bf 100644
--- a/AKPlan/templatetags/tags_AKPlan.py
+++ b/AKPlan/templatetags/tags_AKPlan.py
@@ -11,6 +11,14 @@ register = template.Library()
 
 @register.filter
 def highlight_change_colors(akslot):
+    """
+    Adjust color to highlight recent changes if needed
+
+    :param akslot: akslot to determine color for
+    :type akslot: AKSlot
+    :return: color that should be used (either default color of the category or some kind of red)
+    :rtype: str
+    """
     # Do not highlight in preview mode or when changes occurred before the plan was published
     if akslot.event.plan_hidden or (akslot.event.plan_published_at is not None
                                     and akslot.event.plan_published_at > akslot.updated):
@@ -25,9 +33,14 @@ def highlight_change_colors(akslot):
     # Recent change? Calculate gradient blend between red and
     recentness = seconds_since_update / settings.PLAN_MAX_HIGHLIGHT_UPDATE_SECONDS
     return darken("#b71540", recentness)
-    # return linear_blend("#b71540", "#000000", recentness)
 
 
 @register.simple_tag
 def timestamp_now(tz):
+    """
+    Get the current timestamp for the given timezone
+
+    :param tz: timezone to be used for the timestamp
+    :return: current timestamp in given timezone
+    """
     return date_format(datetime.now().astimezone(tz), "c")
diff --git a/AKPlan/views.py b/AKPlan/views.py
index 513bca31838a5f33da37b3127a579cdc2a7c500a..87c513a646dba58661a1a64c50d10121c148ba3b 100644
--- a/AKPlan/views.py
+++ b/AKPlan/views.py
@@ -1,5 +1,3 @@
-from datetime import timedelta
-
 from django.conf import settings
 from django.shortcuts import redirect
 from django.urls import reverse_lazy
@@ -11,6 +9,11 @@ from AKModel.metaviews.admin import FilterByEventSlugMixin
 
 
 class PlanIndexView(FilterByEventSlugMixin, ListView):
+    """
+    Default plan view
+
+    Shows two lists of current and upcoming AKs and a graphical full plan below
+    """
     model = AKSlot
     template_name = "AKPlan/plan_index.html"
     context_object_name = "akslots"
@@ -60,6 +63,15 @@ class PlanIndexView(FilterByEventSlugMixin, ListView):
 
 
 class PlanScreenView(PlanIndexView):
+    """
+    Plan view optimized for screens and projectors
+
+    This again shows current and upcoming AKs as well as a graphical plan,
+    but no navigation elements and trys to use the available space as best as possible
+    such that no scrolling is needed.
+
+    The view contains a frontend functionality for auto-reload.
+    """
     template_name = "AKPlan/plan_wall.html"
 
     def get(self, request, *args, **kwargs):
@@ -92,22 +104,34 @@ class PlanScreenView(PlanIndexView):
 
 
 class PlanRoomView(FilterByEventSlugMixin, DetailView):
+    """
+    Plan view for a single room
+    """
     template_name = "AKPlan/plan_room.html"
     model = Room
     context_object_name = "room"
 
     def get_context_data(self, *, object_list=None, **kwargs):
         context = super().get_context_data(object_list=object_list, **kwargs)
+        # Restrict AKSlot list to the given room
+        # while joining AK, room and category information to reduce the amount of necessary SQL queries
         context["slots"] = AKSlot.objects.filter(room=context['room']).select_related('ak', 'ak__category', 'ak__track')
         return context
 
 
 class PlanTrackView(FilterByEventSlugMixin, DetailView):
+    """
+    Plan view for a single track
+    """
     template_name = "AKPlan/plan_track.html"
     model = AKTrack
     context_object_name = "track"
 
     def get_context_data(self, *, object_list=None, **kwargs):
         context = super().get_context_data(object_list=object_list, **kwargs)
-        context["slots"] = AKSlot.objects.filter(event=self.event, ak__track=context['track']).select_related('ak', 'room', 'ak__category')
+        # Restrict AKSlot list to given track
+        # while joining AK, room and category information to reduce the amount of necessary SQL queries
+        context["slots"] = AKSlot.objects.\
+            filter(event=self.event, ak__track=context['track']).\
+            select_related('ak', 'room', 'ak__category')
         return context
diff --git a/pylintrc b/pylintrc
index e604e04a521231c8dd83cc433abcc99cb28cd2be..3c0776b4c0acd810ad191cb03ef9dbe87a60e804 100644
--- a/pylintrc
+++ b/pylintrc
@@ -1,4 +1,5 @@
 [MAIN]
+
 ignore=tests.py, urls.py, migrations
 
 load-plugins=
@@ -41,7 +42,7 @@ ignore-signatures=yes
 [BASIC]
 
 # Regular expression matching correct module names
-module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+)|(AK[A-Z][a-z0-9_]+))$
+module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+)|((tags_)*AK[A-Z][a-z0-9_]+))$
 
 # Good variable names which should always be accepted, separated by a comma
 good-names=i,j,k,a,e,ak,tz,_
@@ -66,3 +67,8 @@ generated-members=objects,DoesNotExist,id,pk,_meta,base_fields,context
 
 # List of method names used to declare (i.e. assign) instance attributes
 defining-attr-methods=__init__,__new__,setUp
+
+
+[DESIGN]
+
+max-parents=15