diff --git a/district/migrations/0043_alter_districtarticletag_tag_and_more.py b/district/migrations/0043_alter_districtarticletag_tag_and_more.py
new file mode 100644
index 0000000000000000000000000000000000000000..261e36a3e08607454e3df8331e097249769a42cc
--- /dev/null
+++ b/district/migrations/0043_alter_districtarticletag_tag_and_more.py
@@ -0,0 +1,33 @@
+# Generated by Django 4.0.3 on 2022-03-11 22:09
+
+import django.db.models.deletion
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ("taggit", "0004_alter_taggeditem_content_type_alter_taggeditem_tag"),
+        ("district", "0042_auto_20220309_1319"),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name="districtarticletag",
+            name="tag",
+            field=models.ForeignKey(
+                on_delete=django.db.models.deletion.CASCADE,
+                related_name="%(app_label)s_%(class)s_items",
+                to="taggit.tag",
+            ),
+        ),
+        migrations.AlterField(
+            model_name="districtpersontag",
+            name="tag",
+            field=models.ForeignKey(
+                on_delete=django.db.models.deletion.CASCADE,
+                related_name="%(app_label)s_%(class)s_items",
+                to="taggit.tag",
+            ),
+        ),
+    ]
diff --git a/elections2021/migrations/0050_alter_elections2021articletag_tag.py b/elections2021/migrations/0050_alter_elections2021articletag_tag.py
new file mode 100644
index 0000000000000000000000000000000000000000..c1a94522209d820cef331d6ed62b49138c652ba1
--- /dev/null
+++ b/elections2021/migrations/0050_alter_elections2021articletag_tag.py
@@ -0,0 +1,24 @@
+# Generated by Django 4.0.3 on 2022-03-11 22:09
+
+import django.db.models.deletion
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ("taggit", "0004_alter_taggeditem_content_type_alter_taggeditem_tag"),
+        ("elections2021", "0049_auto_20210930_2104"),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name="elections2021articletag",
+            name="tag",
+            field=models.ForeignKey(
+                on_delete=django.db.models.deletion.CASCADE,
+                related_name="%(app_label)s_%(class)s_items",
+                to="taggit.tag",
+            ),
+        ),
+    ]
diff --git a/majak/urls.py b/majak/urls.py
index 1dbbebe03a1396b71c1f1748269f9429bbb11ff2..66a1e21220f566a619b456f8f470992c47762c85 100644
--- a/majak/urls.py
+++ b/majak/urls.py
@@ -1,7 +1,7 @@
 import captcha.urls
 from django.conf import settings
-from django.conf.urls import include, url
 from django.contrib import admin
+from django.urls import include, path
 from pirates.urls import urlpatterns as pirates_urlpatterns
 from wagtail.admin import urls as wagtailadmin_urls
 from wagtail.core import urls as wagtail_urls
@@ -13,16 +13,16 @@ from search import views as search_views
 handler404 = "shared.views.page_not_found"
 
 urlpatterns = [
-    url(r"^django-admin/", admin.site.urls),
-    url(r"^admin/", include(wagtailadmin_urls)),
-    url(r"^documents/", include(wagtaildocs_urls)),
-    url(r"^search/$", search_views.search, name="search"),
-    url(
-        r"^export/elections2021/banner-orders.csv$",
+    path("django-admin/", admin.site.urls),
+    path("admin/", include(wagtailadmin_urls)),
+    path("documents/", include(wagtaildocs_urls)),
+    path("search/", search_views.search, name="search"),
+    path(
+        "export/elections2021/banner-orders.csv",
         elections2021_views.banner_orders_csv,
         name="elections2021_banner_orders_csv",
     ),
-    url(r"^captcha/", include(captcha.urls)),
+    path("captcha/", include(captcha.urls)),
 ] + pirates_urlpatterns
 
 
@@ -38,7 +38,7 @@ urlpatterns = urlpatterns + [
     # For anything not caught by a more specific rule above, hand over to
     # Wagtail's page serving mechanism. This should be the last pattern in
     # the list:
-    url(r"", include(wagtail_urls)),
+    path("", include(wagtail_urls)),
     # Alternatively, if you want Wagtail pages to be served from a subpath
     # of your site, rather than the site root:
     #    url(r"^pages/", include(wagtail_urls)),
diff --git a/region/migrations/0018_alter_regionarticletag_tag_alter_regionpersontag_tag.py b/region/migrations/0018_alter_regionarticletag_tag_alter_regionpersontag_tag.py
new file mode 100644
index 0000000000000000000000000000000000000000..b6bdbae6664487ca7c40b0b5558b031626acfcfe
--- /dev/null
+++ b/region/migrations/0018_alter_regionarticletag_tag_alter_regionpersontag_tag.py
@@ -0,0 +1,33 @@
+# Generated by Django 4.0.3 on 2022-03-11 22:09
+
+import django.db.models.deletion
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ("taggit", "0004_alter_taggeditem_content_type_alter_taggeditem_tag"),
+        ("region", "0017_auto_20220309_1357"),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name="regionarticletag",
+            name="tag",
+            field=models.ForeignKey(
+                on_delete=django.db.models.deletion.CASCADE,
+                related_name="%(app_label)s_%(class)s_items",
+                to="taggit.tag",
+            ),
+        ),
+        migrations.AlterField(
+            model_name="regionpersontag",
+            name="tag",
+            field=models.ForeignKey(
+                on_delete=django.db.models.deletion.CASCADE,
+                related_name="%(app_label)s_%(class)s_items",
+                to="taggit.tag",
+            ),
+        ),
+    ]
diff --git a/requirements/base.in b/requirements/base.in
index 93d9dceef9832a61683d9116e03db4478a7e7f8d..32bf181d3c77086cf40ff6869ebae9ffe241914c 100644
--- a/requirements/base.in
+++ b/requirements/base.in
@@ -7,7 +7,7 @@ django-settings-export
 django-widget-tweaks
 django-simple-captcha
 psycopg2-binary
-pirates<=0.6
+pirates<=0.7
 whitenoise
 opencv-python
 requests
diff --git a/requirements/base.txt b/requirements/base.txt
index 5c4806c8e18ac22cfc7e2cf9e6930238252bb880..cdbdc7732b26cd344d396397f0bb88454d107176 100644
--- a/requirements/base.txt
+++ b/requirements/base.txt
@@ -1,5 +1,5 @@
 #
-# This file is autogenerated by pip-compile with python 3.9
+# This file is autogenerated by pip-compile with python 3.10
 # To update, run:
 #
 #    pip-compile base.in
@@ -22,8 +22,6 @@ beautifulsoup4==4.9.3
     # via
     #   -r base.in
     #   wagtail
-black==21.12b0
-    # via ipython
 bleach==4.1.0
     # via -r base.in
 brotli==1.0.9
@@ -36,22 +34,20 @@ cffi==1.15.0
     # via
     #   cryptography
     #   weasyprint
-charset-normalizer==2.0.10
+charset-normalizer==2.0.12
     # via requests
-click==8.0.3
-    # via black
 cryptography==36.0.1
     # via
     #   josepy
     #   mozilla-django-oidc
     #   pyopenssl
-cssselect2==0.4.1
+cssselect2==0.5.0
     # via weasyprint
 decorator==5.1.1
     # via ipython
 deprecated==1.2.13
     # via redis
-django==3.2.11
+django==4.0.3
     # via
     #   django-extensions
     #   django-filter
@@ -70,7 +66,7 @@ django-extensions==3.1.5
     # via -r base.in
 django-filter==21.1
     # via wagtail
-django-modelcluster==5.2
+django-modelcluster==5.3
     # via wagtail
 django-ranged-response==0.2.0
     # via django-simple-captcha
@@ -78,9 +74,9 @@ django-redis==5.2.0
     # via -r base.in
 django-settings-export==1.2.1
     # via -r base.in
-django-simple-captcha==0.5.14
+django-simple-captcha==0.5.17
     # via -r base.in
-django-taggit==1.5.1
+django-taggit==2.1.0
     # via wagtail
 django-treebeard==4.5.1
     # via wagtail
@@ -92,9 +88,9 @@ draftjs-exporter==2.1.7
     # via wagtail
 et-xmlfile==1.1.0
     # via openpyxl
-executing==0.8.2
+executing==0.8.3
     # via stack-data
-fonttools[woff]==4.29.0
+fonttools[woff]==4.30.0
     # via weasyprint
 html5lib==1.1
     # via
@@ -104,13 +100,11 @@ ics==0.7
     # via -r base.in
 idna==3.3
     # via requests
-importlib-metadata==4.10.1
-    # via markdown
-ipython==8.0.1
+ipython==8.1.1
     # via -r base.in
 jedi==0.18.1
     # via ipython
-josepy==1.12.0
+josepy==1.13.0
     # via mozilla-django-oidc
 l18n==2021.3
     # via wagtail
@@ -118,13 +112,11 @@ markdown==3.3.6
     # via -r base.in
 matplotlib-inline==0.1.3
     # via ipython
-mozilla-django-oidc==1.2.4
+mozilla-django-oidc==2.0.0
     # via pirates
-mypy-extensions==0.4.3
-    # via black
-numpy==1.22.1
+numpy==1.22.3
     # via opencv-python
-opencv-python==4.5.5.62
+opencv-python==4.5.5.64
     # via -r base.in
 openpyxl==3.0.9
     # via tablib
@@ -134,22 +126,18 @@ packaging==21.3
     #   redis
 parso==0.8.3
     # via jedi
-pathspec==0.9.0
-    # via black
 pexpect==4.8.0
     # via ipython
 pickleshare==0.7.5
     # via ipython
-pillow==9.0.0
+pillow==9.0.1
     # via
     #   django-simple-captcha
     #   wagtail
     #   weasyprint
-pirates==0.5.0
+pirates==0.6.0
     # via -r base.in
-platformdirs==2.4.1
-    # via black
-prompt-toolkit==3.0.24
+prompt-toolkit==3.0.28
     # via ipython
 psycopg2-binary==2.9.3
     # via -r base.in
@@ -163,7 +151,7 @@ pydyf==0.1.2
     # via weasyprint
 pygments==2.11.2
     # via ipython
-pyopenssl==21.0.0
+pyopenssl==22.0.0
     # via josepy
 pyparsing==3.0.7
     # via packaging
@@ -177,41 +165,37 @@ python-dateutil==2.8.2
     #   ics
 pytz==2021.3
     # via
-    #   django
     #   django-modelcluster
     #   djangorestframework
     #   l18n
 pyyaml==6.0
     # via -r base.in
-redis==4.1.1
+redis==4.1.4
     # via django-redis
 requests==2.27.1
     # via
     #   -r base.in
     #   mozilla-django-oidc
     #   wagtail
-sentry-sdk==1.5.4
+sentry-sdk==1.5.7
     # via -r base.in
 six==1.16.0
     # via
     #   asttokens
     #   bleach
-    #   django-simple-captcha
     #   html5lib
     #   ics
     #   l18n
-    #   mozilla-django-oidc
-    #   pyopenssl
     #   python-dateutil
 soupsieve==2.3.1
     # via beautifulsoup4
 sqlparse==0.4.2
     # via django
-stack-data==0.1.4
+stack-data==0.2.0
     # via ipython
-tablib[xls,xlsx]==3.1.0
+tablib[xls,xlsx]==3.2.0
     # via wagtail
-tatsu==5.6.1
+tatsu==5.7.3
     # via ics
 telepath==0.2
     # via wagtail
@@ -219,27 +203,23 @@ tinycss2==1.1.1
     # via
     #   cssselect2
     #   weasyprint
-tomli==1.2.3
-    # via black
 traitlets==5.1.1
     # via
     #   ipython
     #   matplotlib-inline
-typing-extensions==4.0.1
-    # via black
 urllib3==1.26.8
     # via
     #   requests
     #   sentry-sdk
-wagtail==2.15.3
+wagtail==2.16.1
     # via
     #   -r base.in
     #   wagtail-metadata
-wagtail-metadata==3.4.1
+wagtail-metadata==3.5.0
     # via -r base.in
 wcwidth==0.2.5
     # via prompt-toolkit
-weasyprint==54.0
+weasyprint==54.2
     # via -r base.in
 webencodings==0.5.1
     # via
@@ -247,21 +227,19 @@ webencodings==0.5.1
     #   cssselect2
     #   html5lib
     #   tinycss2
-whitenoise==5.3.0
+whitenoise==6.0.0
     # via -r base.in
-willow==1.4
+willow==1.4.1
     # via wagtail
-wrapt==1.13.3
+wrapt==1.14.0
     # via deprecated
 xlrd==2.0.1
     # via tablib
-xlsxwriter==3.0.2
+xlsxwriter==3.0.3
     # via wagtail
 xlwt==1.3.0
     # via tablib
-zipp==3.7.0
-    # via importlib-metadata
-zopfli==0.1.9
+zopfli==0.2.1
     # via fonttools
 
 # The following packages are considered to be unsafe in a requirements file:
diff --git a/requirements/dev.txt b/requirements/dev.txt
index a3d71077b0444e45aaa96572f7b05abfe889f2e9..0a306787ddf237cdc7a2d40e5db3ba524c0183b5 100644
--- a/requirements/dev.txt
+++ b/requirements/dev.txt
@@ -1,20 +1,20 @@
 #
-# This file is autogenerated by pip-compile with python 3.9
+# This file is autogenerated by pip-compile with python 3.10
 # To update, run:
 #
 #    pip-compile dev.in
 #
 attrs==21.4.0
     # via pytest
-coverage[toml]==6.3
+coverage[toml]==6.3.2
     # via pytest-cov
 factory-boy==3.2.1
     # via pytest-factoryboy
-faker==11.3.0
+faker==13.3.1
     # via factory-boy
 fastdiff==0.3.0
     # via snapshottest
-freezegun==1.1.0
+freezegun==1.2.0
     # via pytest-freezegun
 inflection==0.5.1
     # via pytest-factoryboy
@@ -30,7 +30,7 @@ py==1.11.0
     # via pytest
 pyparsing==3.0.7
     # via packaging
-pytest==6.2.5
+pytest==7.0.1
     # via
     #   -r dev.in
     #   pytest-cov
@@ -47,7 +47,7 @@ pytest-factoryboy==2.1.0
     # via -r dev.in
 pytest-freezegun==0.4.2
     # via -r dev.in
-pytest-mock==3.6.1
+pytest-mock==3.7.0
     # via -r dev.in
 pytest-sugar==0.9.4
     # via -r dev.in
@@ -65,12 +65,10 @@ termcolor==1.1.0
     # via
     #   pytest-sugar
     #   snapshottest
-text-unidecode==1.3
-    # via faker
-toml==0.10.2
-    # via pytest
-tomli==1.2.3
-    # via coverage
+tomli==2.0.1
+    # via
+    #   coverage
+    #   pytest
 wasmer==1.1.0
     # via fastdiff
 wasmer-compiler-cranelift==1.1.0
diff --git a/requirements/production.txt b/requirements/production.txt
index da9eb845cab39ba36c8de3e185318e4f7271fd3f..3333386f4e89a4345670321d51b646a4098aa598 100644
--- a/requirements/production.txt
+++ b/requirements/production.txt
@@ -1,5 +1,5 @@
 #
-# This file is autogenerated by pip-compile with python 3.9
+# This file is autogenerated by pip-compile with python 3.10
 # To update, run:
 #
 #    pip-compile production.in
diff --git a/uniweb/migrations/0021_alter_uniwebarticletag_tag.py b/uniweb/migrations/0021_alter_uniwebarticletag_tag.py
new file mode 100644
index 0000000000000000000000000000000000000000..6a2ff8f380bda82deb877e14b2cc0faf92b1fe22
--- /dev/null
+++ b/uniweb/migrations/0021_alter_uniwebarticletag_tag.py
@@ -0,0 +1,24 @@
+# Generated by Django 4.0.3 on 2022-03-11 22:09
+
+import django.db.models.deletion
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ("taggit", "0004_alter_taggeditem_content_type_alter_taggeditem_tag"),
+        ("uniweb", "0020_auto_20220213_1210"),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name="uniwebarticletag",
+            name="tag",
+            field=models.ForeignKey(
+                on_delete=django.db.models.deletion.CASCADE,
+                related_name="%(app_label)s_%(class)s_items",
+                to="taggit.tag",
+            ),
+        ),
+    ]