diff --git a/district/forms.py b/district/forms.py
index 03efb555b07efea5d2457a5fae28debca7d33a94..48600686a04f6efbc03dbd7de3cbe1dbe5c416c4 100644
--- a/district/forms.py
+++ b/district/forms.py
@@ -1,52 +1,16 @@
+from shared.forms import JekyllImportForm as SharedJekyllImportForm
+import os
 from django import forms
-from django.utils.safestring import mark_safe
-from wagtail.admin.forms import WagtailAdminPageForm
-from wagtail.models.collections import Collection
+from .tasks import import_jekyll_articles
 
-from shared.jekyll_import import JekyllArticleImporter
 
-
-class JekyllImportForm(WagtailAdminPageForm):
-    do_import = forms.BooleanField(
-        initial=False, required=False, label="Provést import z Jekyllu"
-    )
-    collection = forms.ModelChoiceField(
-        queryset=Collection.objects.all(), required=False, label="Kolekce obrázků"
-    )
-    dry_run = forms.BooleanField(
-        initial=True,
-        required=False,
-        label="Jenom na zkoušku",
-        help_text="Žádné články se neuloží, vypíše případné problémy či "
-        "již existující články - 'ostrému' importu existující "
-        "články nevadí, přeskočí je",
-    )
+class JekyllImportForm(SharedJekyllImportForm):
     use_git = forms.BooleanField(
         initial=False,
         required=False,
         label="Použít Git",
         help_text="Umožňuje jednodušší zpracování, ale vyžaduje nainstalovaný Git.",
     )
-    jekyll_repo_url = forms.URLField(
-        max_length=512,
-        required=False,
-        help_text=mark_safe(
-            "V GitHubu tlačítko Code -> a odkaz z <strong>Download zip</strong>, "
-            "např. <em>https://github.com/pirati-web/cb.pirati.cz/archive/refs/heads/gh-pages.zip</em>. "
-            "Pokud máte nainstalovaný Git, zvolte <strong>Použít Git</strong> a vložte jednoduše "
-            "URL repozitáře, např. <em>https://github.com/pirati-web/cb.pirati.cz</em>."
-        ),
-    )
-    readonly_log = forms.CharField(
-        disabled=True,
-        label="Log z posledního importu",
-        required=False,
-        widget=forms.Textarea,
-    )
-
-    def __init__(self, *args, **kwargs):
-        super().__init__(*args, **kwargs)
-        self.fields["readonly_log"].initial = self.instance.last_import_log
 
     def clean(self):
         cleaned_data = super().clean()
@@ -54,16 +18,6 @@ class JekyllImportForm(WagtailAdminPageForm):
         if not cleaned_data.get("do_import"):
             return cleaned_data
 
-        if cleaned_data.get("do_import") and not self.instance.id:
-            self.add_error(
-                "do_import", "Import proveďte prosím až po vytvoření stránky"
-            )
-
-        if not cleaned_data.get("collection"):
-            self.add_error("collection", "Pro import je toto pole povinné")
-        if not cleaned_data.get("jekyll_repo_url"):
-            self.add_error("jekyll_repo_url", "Pro import je toto pole povinné")
-
         if cleaned_data.get("use_git"):
             if cleaned_data.get("jekyll_repo_url", "").endswith(".zip"):
                 self.add_error(
@@ -81,19 +35,17 @@ class JekyllImportForm(WagtailAdminPageForm):
         return cleaned_data
 
     def handle_import(self):
-        from .models import DistrictArticlePage
+        lock_file_name = f"/tmp/.{self.instance.id}.import-lock"
 
-        JekyllArticleImporter(
-            article_parent_page=self.instance,
+        if os.path.isfile(lock_file_name):
+            return
+
+        open(lock_file_name, "w").close()
+
+        import_jekyll_articles.delay(
+            article_parent_page_id=self.instance.id,
             collection_id=self.cleaned_data["collection"].id,
             url=self.cleaned_data["jekyll_repo_url"],
             dry_run=self.cleaned_data["dry_run"],
-            use_git=self.cleaned_data["use_git"],
-            page_model=DistrictArticlePage,
-        ).perform_import()
-
-    def save(self, commit=True):
-        if self.cleaned_data.get("do_import"):
-            self.handle_import()
-
-        return super().save(commit=commit)
+            use_git=True,
+        )
diff --git a/district/tasks.py b/district/tasks.py
new file mode 100644
index 0000000000000000000000000000000000000000..8162ecb06496e59c2bef2bd445984ff4fb7363d9
--- /dev/null
+++ b/district/tasks.py
@@ -0,0 +1,27 @@
+import logging
+
+from celery import shared_task
+from shared.jekyll_import import JekyllArticleImporter
+
+logger = logging.getLogger(__name__)
+
+
+@shared_task()
+def import_jekyll_articles(
+    article_parent_page_id,
+    collection_id,
+    url,
+    dry_run,
+    use_git,
+):
+    from .models import DistrictArticlePage, DistrictArticlesPage
+
+    return JekyllArticleImporter(
+        article_parent_page_id=article_parent_page_id,
+        article_parent_page_model=DistrictArticlesPage,
+        collection_id=collection_id,
+        url=url,
+        dry_run=dry_run,
+        use_git=use_git,
+        page_model=DistrictArticlePage,
+    ).perform_import()
diff --git a/elections/forms.py b/elections/forms.py
new file mode 100644
index 0000000000000000000000000000000000000000..b252a89ac370c1ae3dd2b4dba6d51bb91d689604
--- /dev/null
+++ b/elections/forms.py
@@ -0,0 +1,21 @@
+from shared.forms import JekyllImportForm as SharedJekyllImportForm
+import os
+from .tasks import import_jekyll_articles
+
+
+class JekyllImportForm(SharedJekyllImportForm):
+    def handle_import(self):
+        lock_file_name = f"/tmp/.{self.instance.id}.import-lock"
+
+        if os.path.isfile(lock_file_name):
+            return
+
+        open(lock_file_name, "w").close()
+
+        import_jekyll_articles.delay(
+            article_parent_page_id=self.instance.id,
+            collection_id=self.cleaned_data["collection"].id,
+            url=self.cleaned_data["jekyll_repo_url"],
+            dry_run=self.cleaned_data["dry_run"],
+            use_git=True,
+        )
diff --git a/elections/models.py b/elections/models.py
index 9f7f1bf88f3e740ab91c9953aef686262610fcc5..7222292745c5a7315b349973434bea4ef403d867 100644
--- a/elections/models.py
+++ b/elections/models.py
@@ -46,6 +46,7 @@ from shared.models import (  # MenuMixin,
 )
 from shared.utils import make_promote_panels, subscribe_to_newsletter
 from tuning import admin_help
+from .forms import JekyllImportForm
 
 from . import blocks
 
@@ -118,6 +119,8 @@ class ElectionsHomePage(MainHomePageMixin):
 
 
 class ElectionsArticlesPage(MainArticlesPageMixin):
+    base_form_class = JekyllImportForm
+
     parent_page_types = ["elections.ElectionsHomePage"]
     subpage_types = ["elections.ElectionsArticlePage"]
 
diff --git a/elections/tasks.py b/elections/tasks.py
new file mode 100644
index 0000000000000000000000000000000000000000..f3cce43e0f8491caa438ea473f1e9b69fb041c74
--- /dev/null
+++ b/elections/tasks.py
@@ -0,0 +1,27 @@
+import logging
+
+from celery import shared_task
+from shared.jekyll_import import JekyllArticleImporter
+
+logger = logging.getLogger(__name__)
+
+
+@shared_task()
+def import_jekyll_articles(
+    article_parent_page_id,
+    collection_id,
+    url,
+    dry_run,
+    use_git,
+):
+    from .models import ElectionsArticlePage, ElectionsArticlesPage
+
+    return JekyllArticleImporter(
+        article_parent_page_id=article_parent_page_id,
+        article_parent_page_model=ElectionsArticlesPage,
+        collection_id=collection_id,
+        url=url,
+        dry_run=dry_run,
+        use_git=use_git,
+        page_model=ElectionsArticlePage,
+    ).perform_import()
diff --git a/main/forms.py b/main/forms.py
new file mode 100644
index 0000000000000000000000000000000000000000..b252a89ac370c1ae3dd2b4dba6d51bb91d689604
--- /dev/null
+++ b/main/forms.py
@@ -0,0 +1,21 @@
+from shared.forms import JekyllImportForm as SharedJekyllImportForm
+import os
+from .tasks import import_jekyll_articles
+
+
+class JekyllImportForm(SharedJekyllImportForm):
+    def handle_import(self):
+        lock_file_name = f"/tmp/.{self.instance.id}.import-lock"
+
+        if os.path.isfile(lock_file_name):
+            return
+
+        open(lock_file_name, "w").close()
+
+        import_jekyll_articles.delay(
+            article_parent_page_id=self.instance.id,
+            collection_id=self.cleaned_data["collection"].id,
+            url=self.cleaned_data["jekyll_repo_url"],
+            dry_run=self.cleaned_data["dry_run"],
+            use_git=True,
+        )
diff --git a/main/models.py b/main/models.py
index c120f0404b5e83901ee04bc0002af366b2987715..9f4cc1678e85385e86a0999268714c91875b9dbe 100644
--- a/main/models.py
+++ b/main/models.py
@@ -46,6 +46,7 @@ from shared.models import (  # MenuMixin,
 )
 from shared.utils import make_promote_panels, subscribe_to_newsletter
 from tuning import admin_help
+from .forms import JekyllImportForm
 
 from . import blocks
 
@@ -132,6 +133,8 @@ class MainHomePage(MainHomePageMixin):
 
 
 class MainArticlesPage(MainArticlesPageMixin):
+    base_form_class = JekyllImportForm
+
     parent_page_types = ["main.MainHomePage"]
     subpage_types = ["main.MainArticlePage"]
 
diff --git a/shared/tasks.py b/main/tasks.py
similarity index 100%
rename from shared/tasks.py
rename to main/tasks.py
diff --git a/shared/forms.py b/shared/forms.py
index 934dd0bf2da12a0adbec5ae823eaeb832c1a6580..909728431a623b39325640543a4a6ee1f8aaf03c 100644
--- a/shared/forms.py
+++ b/shared/forms.py
@@ -1,8 +1,7 @@
 from django import forms
 from wagtail.admin.forms import WagtailAdminPageForm
 from wagtail.models.collections import Collection
-
-from .tasks import import_jekyll_articles
+import os
 
 
 class SubscribeForm(forms.Form):
@@ -65,21 +64,6 @@ class JekyllImportForm(WagtailAdminPageForm):
 
         return cleaned_data
 
-    def handle_import(self):
-        # TODO: Portable function
-
-        print("handling import")
-
-        print(
-            import_jekyll_articles.delay(
-                article_parent_page_id=self.instance.id,
-                collection_id=self.cleaned_data["collection"].id,
-                url=self.cleaned_data["jekyll_repo_url"],
-                dry_run=self.cleaned_data["dry_run"],
-                use_git=True,
-            )
-        )
-
     def save(self, commit=True):
         if self.cleaned_data.get("do_import"):
             self.handle_import()
diff --git a/shared/jekyll_import.py b/shared/jekyll_import.py
index a58508c33cbe6b5a590c2a3071b1d01dc44f11cc..1d5baffa94a1348153750bcddb43f4a20ba3c1be 100644
--- a/shared/jekyll_import.py
+++ b/shared/jekyll_import.py
@@ -13,6 +13,7 @@ from io import StringIO
 from typing import List
 from urllib.error import HTTPError
 from uuid import uuid4
+import os
 
 import bleach
 import markdown.serializers
@@ -665,30 +666,33 @@ class JekyllArticleImporter:
         Začne vyčištěním logu.
         """
 
-        self.article_parent_page.last_import_log = ""
-        self.article_parent_page.save()
-
-        msg = "{} Import započat".format(datetime.now())
-        logger.info(msg)
-        self.page_log += "{}\n\n".format(msg)
-
-        for file_name in os.listdir(os.path.join(self.path, POSTS_DIR)):
-            # Případ podsložek (typicky po jednotlivých letech)
-            if os.path.isdir(os.path.join(self.path, POSTS_DIR, file_name)):
-                posts_sub_folder = os.path.join(self.path, POSTS_DIR, file_name)
-                for sub_file_name in os.listdir(posts_sub_folder):
-                    file_path = os.path.join(posts_sub_folder, sub_file_name)
-                    self.process_article(sub_file_name, file_path)
-            # Případ všech článků v jedné složce
-            else:
-                file_path = os.path.join(POSTS_DIR, file_name)
-                self.process_article(file_name, file_path)
-
-        msg = "{} Import ukončen".format(datetime.now())
-        logger.info(msg)
-        self.page_log += "{}\n\n".format(msg)
-
-        self.create_summary_log()
+        try:
+            self.article_parent_page.last_import_log = ""
+            self.article_parent_page.save()
+
+            msg = "{} Import započat".format(datetime.now())
+            logger.info(msg)
+            self.page_log += "{}\n\n".format(msg)
+
+            for file_name in os.listdir(os.path.join(self.path, POSTS_DIR)):
+                # Případ podsložek (typicky po jednotlivých letech)
+                if os.path.isdir(os.path.join(self.path, POSTS_DIR, file_name)):
+                    posts_sub_folder = os.path.join(self.path, POSTS_DIR, file_name)
+                    for sub_file_name in os.listdir(posts_sub_folder):
+                        file_path = os.path.join(posts_sub_folder, sub_file_name)
+                        self.process_article(sub_file_name, file_path)
+                # Případ všech článků v jedné složce
+                else:
+                    file_path = os.path.join(POSTS_DIR, file_name)
+                    self.process_article(file_name, file_path)
+
+            msg = "{} Import ukončen".format(datetime.now())
+            logger.info(msg)
+            self.page_log += "{}\n\n".format(msg)
+
+            self.create_summary_log()
+        finally:
+            os.remove(f"/tmp/.{self.article_parent_page_id}.import-lock")
 
     def process_article(self, file_name: str, file_path: str):
         match = re.match(r"(\d*)-(\d*)-(\d*)-(.*)\.(.*)", file_name)
diff --git a/shared/models/main.py b/shared/models/main.py
index c9871aec2d8b5522b366a40b8b341e2cd71aa00f..7f4848c62dcc0df32291d05f88e751bbb3551783 100644
--- a/shared/models/main.py
+++ b/shared/models/main.py
@@ -41,7 +41,7 @@ from shared.blocks import (
     TwoTextColumnBlock,
 )
 from shared.const import MONTH_NAMES
-from shared.forms import JekyllImportForm, SubscribeForm
+from shared.forms import SubscribeForm
 from shared.utils import make_promote_panels, subscribe_to_newsletter
 from tuning import admin_help
 
@@ -438,8 +438,6 @@ class MainArticlesPageMixin(
 
     ### OTHERS
 
-    base_form_class = JekyllImportForm
-
     class Meta:
         verbose_name = "Rozcestník článků"
         abstract = True