diff --git a/district/models.py b/district/models.py
index dc83652697d775237d2c811cc9fd63c2e29b841c..584c00bd6ad7ff2efa11ede7617a581659111be8 100644
--- a/district/models.py
+++ b/district/models.py
@@ -53,7 +53,6 @@ from shared.models import (
     ExtendedMetadataPageMixin,
     FooterMixin,
     MenuMixin,
-    SharedArticleTypes,
     SharedTaggedDistrictArticle,
     SubpageMixin,
 )
@@ -538,9 +537,7 @@ class DistrictArticlesPage(
     def get_context(self, request):
         context = super().get_context(request)
         context["articles"] = Paginator(
-            self.append_all_shared_articles(
-                SharedArticleTypes.DISTRICT, DistrictArticlePage.objects.child_of(self)
-            ),
+            self.append_all_shared_articles(DistrictArticlePage.objects.child_of(self)),
             self.max_items,
         ).get_page(request.GET.get("page"))
         return context
@@ -564,7 +561,7 @@ class DistrictArticlesPage(
         context = super().get_context(request)
 
         site_article_ids = self.append_all_shared_articles(
-            SharedArticleTypes.DISTRICT, DistrictArticlePage.objects.child_of(self)
+            DistrictArticlePage.objects.child_of(self)
         ).values_list("id", flat=True)
 
         # Naplním "tag" a "article_page_list" parametry
@@ -582,7 +579,7 @@ class DistrictArticlesPage(
         separátně, ale pak by se musel rozpadnout ten try/except na více bloků.
         """
         article_page_qs = self.append_all_shared_articles(
-            SharedArticleTypes.DISTRICT, DistrictArticlePage.objects
+            DistrictArticlePage.objects
         ).filter(id__in=site_article_ids)
 
         try:
diff --git a/main/models.py b/main/models.py
index 6d4d882bd32353d3e5206563aef65f86ae90215b..5d6f9e8b7fd4f6b18451b49d15cbd2b9c5cf4b09 100644
--- a/main/models.py
+++ b/main/models.py
@@ -35,7 +35,6 @@ from shared.models import (  # MenuMixin,
     ArticlesMixin,
     ExtendedMetadataHomePageMixin,
     ExtendedMetadataPageMixin,
-    SharedArticleTypes,
     SharedTaggedMainArticle,
     SubpageMixin,
 )
@@ -513,9 +512,9 @@ class MainArticlesPage(
 
     def get_all_articles_search_response(self, request):
         article_paginator = Paginator(
-            self.append_all_shared_articles(
-                SharedArticleTypes.MAIN, MainArticlePage.objects
-            ).search(request.GET["q"]),
+            self.append_all_shared_articles(MainArticlePage.objects).search(
+                request.GET["q"]
+            ),
             10,
         )
         article_page = article_paginator.get_page(request.GET.get("page", 1))
@@ -543,7 +542,6 @@ class MainArticlesPage(
             query = request.GET["q"]
 
             article_results = self.append_all_shared_articles(
-                SharedArticleTypes.MAIN,
                 MainArticlePage.objects,
             ).search(query)[:11]
 
diff --git a/shared/models.py b/shared/models.py
index 187a4be4c0e86467d530540e84807039a38a5272..d1e12c9c934263541b3b5d9b1c6ac4400faf8415 100644
--- a/shared/models.py
+++ b/shared/models.py
@@ -1,5 +1,5 @@
 import logging
-from enum import Enum
+from functools import reduce
 
 from django.apps import apps
 from django.db import models
@@ -63,6 +63,9 @@ class ArticleMixin(models.Model):
         null=True,
         verbose_name="obrázek",
     )
+    shared = models.BooleanField(
+        default=False
+    )  # hidden field to indicate the article is from another page
 
     ### PANELS
 
@@ -258,12 +261,6 @@ class SharedTaggedMainArticle(ItemBase):
     )
 
 
-class SharedArticleTypes(Enum):
-    DISTRICT = "district"
-    UNIWEB = "uniweb"
-    MAIN = "main"
-
-
 class ArticlesMixin(models.Model):
     shared_tags = ParentalManyToManyField(
         "shared.SharedTag",
@@ -274,12 +271,16 @@ class ArticlesMixin(models.Model):
 
     content_panels = Page.content_panels + [FieldPanel("shared_tags")]
 
-    def append_all_shared_articles(
-        self, source: SharedArticleTypes | None, previous_query: models.QuerySet | None
-    ):
+    def append_all_shared_articles(self, previous_query: models.QuerySet | None):
         """
         To prevent circular deps, we get class models during runtime
         """
+        DistrictArticlesPage = apps.get_model(app_label="district.DistrictArticlesPage")
+        UniwebArticlesIndexPage = apps.get_model(
+            app_label="uniweb.UniwebArticlesIndexPage"
+        )
+        MainArticlesPage = apps.get_model(app_label="main.MainArticlesPage")
+
         DistrictArticlePage = apps.get_model(app_label="district.DistrictArticlePage")
         UniwebArticlePage = apps.get_model(app_label="uniweb.UniwebArticlePage")
         MainArticlePage = apps.get_model(app_label="main.MainArticlePage")
@@ -289,58 +290,50 @@ class ArticlesMixin(models.Model):
             These values must be in correct order
         """
 
-        main_fields = {
-            "union_id": F("id"),
-            "union_page_ptr_id": F("page_ptr_id"),
-            "union_perex": F("perex"),
-            "union_date": F("date"),
-            "union_author": F("author"),
-            "union_image_id": F("image_id"),
-            "union_search_image_id": F("search_image_id"),
-            "union_content": F("content"),
-            "union_author_page_id": F("author_page_id"),
-            "union_region": F("region"),
-            "union_article_type": F("article_type"),
-            "union_is_black": F("is_black"),
-            "union_thumb_image_id": F("search_image_id"),
-        }
+        main_meta_fields = MainArticlePage._meta.fields
+        district_meta_fields = DistrictArticlePage._meta.fields
+        uniweb_meta_fields = UniwebArticlePage._meta.fields
+
+        fields_reducer = (
+            lambda assigned, field: assigned
+            if field.name is "shared"
+            else assigned | {f"union_{field.name}": F(field.name)}
+        )
+        setup_fields_order = lambda orderBy, orderFrom: reduce(
+            lambda orderTo, field: orderTo | {f"{field}": orderFrom[field]},
+            orderBy.keys(),
+            {},
+        )
 
-        district_fields = {
-            "union_id": F("id"),
-            "union_page_ptr_id": F("page_ptr_id"),
-            "union_perex": F("perex"),
-            "union_date": F("date"),
-            "union_author": F("author"),
-            "union_image_id": F("image_id"),
-            "union_search_image_id": F("search_image_id"),
-            "union_content": F("content"),
-            "union_author_page_id": F("author_page_id"),
-            "union_region": Value("", models.CharField()),
-            "union_article_type": Value(0, models.PositiveSmallIntegerField()),
-            "union_is_black": F("is_black"),
-            "union_thumb_image_id": F("thumb_image_id"),
+        main_fields = reduce(fields_reducer, main_meta_fields, {}) | {
+            "union_thumb_image": F("search_image"),
         }
 
-        uniweb_fields = {
-            "union_id": F("id"),
-            "union_page_ptr_id": F("page_ptr_id"),
-            "union_perex": F("perex"),
-            "union_date": F("date"),
-            "union_author": F("author"),
-            "union_image_id": F("image_id"),
-            "union_search_image_id": F("search_image_id"),
-            "union_content": F("content"),
-            "union_author_page_id": Value(
-                None,
-                output_field=models.ForeignKey(
-                    DistrictArticlePage, blank=True, on_delete=models.SET_NULL
+        district_fields = setup_fields_order(
+            main_fields,
+            reduce(fields_reducer, district_meta_fields, {})
+            | {
+                "union_region": Value("", models.CharField()),
+                "union_article_type": Value(0, models.PositiveSmallIntegerField()),
+            },
+        )
+
+        uniweb_fields = setup_fields_order(
+            main_fields,
+            reduce(fields_reducer, uniweb_meta_fields, {})
+            | {
+                "union_author_page": Value(
+                    None,
+                    output_field=models.ForeignKey(
+                        DistrictArticlePage, blank=True, on_delete=models.SET_NULL
+                    ),
                 ),
-            ),
-            "union_region": Value("", models.CharField()),
-            "union_article_type": Value(0, models.PositiveSmallIntegerField()),
-            "union_is_black": Value(False, models.BooleanField()),
-            "union_thumb_image_id": F("search_image_id"),
-        }
+                "union_region": Value("", models.CharField()),
+                "union_article_type": Value(0, models.PositiveSmallIntegerField()),
+                "union_is_black": Value(False, models.BooleanField()),
+                "union_thumb_image": F("search_image"),
+            },
+        )
 
         districtArticleQuery: models.QuerySet = DistrictArticlePage.objects
         uniwebArticlePageQuery: models.QuerySet = UniwebArticlePage.objects
@@ -382,18 +375,19 @@ class ArticlesMixin(models.Model):
 
         results = (
             main_by_slug.values(
-                **main_fields, shared=Value(True, output_field=models.BooleanField())
+                **main_fields,
+                union_shared=Value(True, output_field=models.BooleanField()),
             )
             .union(
                 uniweb_by_slug.values(
                     **uniweb_fields,
-                    shared=Value(True, output_field=models.BooleanField()),
+                    union_shared=Value(True, output_field=models.BooleanField()),
                 )
             )
             .union(
                 district_by_slug.values(
                     **district_fields,
-                    shared=Value(True, output_field=models.BooleanField()),
+                    union_shared=Value(True, output_field=models.BooleanField()),
                 )
             )
         )
@@ -401,20 +395,20 @@ class ArticlesMixin(models.Model):
         if previous_query is not None:
             prepared_query = previous_query.live().specific()
 
-            if source is SharedArticleTypes.DISTRICT:
+            if isinstance(self, DistrictArticlesPage):
                 prepared_query = prepared_query.values(
                     **district_fields,
-                    shared=Value(False, output_field=models.BooleanField()),
+                    union_shared=Value(False, output_field=models.BooleanField()),
                 )
-            elif source is SharedArticleTypes.UNIWEB:
+            elif isinstance(self, UniwebArticlesIndexPage):
                 prepared_query = prepared_query.values(
                     **uniweb_fields,
-                    shared=Value(False, output_field=models.BooleanField()),
+                    union_shared=Value(False, output_field=models.BooleanField()),
                 )
-            elif source is SharedArticleTypes.MAIN:
+            elif isinstance(self, MainArticlesPage):
                 prepared_query = prepared_query.values(
                     **main_fields,
-                    shared=Value(False, output_field=models.BooleanField()),
+                    union_shared=Value(False, output_field=models.BooleanField()),
                 )
 
             results = results.union(prepared_query)
@@ -425,60 +419,35 @@ class ArticlesMixin(models.Model):
             results
         )  # We MUST eval here since we can't turn values() into concrete class instances in QuerySet after union
 
-        if source is SharedArticleTypes.DISTRICT:
+        assign_to_model = lambda unioned: lambda assignment, field: assignment | {
+            field.name: unioned[f"union_{field.name}"]
+        }
+
+        if isinstance(self, DistrictArticlesPage):
             return list(
                 map(
-                    lambda unioned: DistrictArticlePage(
-                        id=unioned["union_id"],
-                        page_ptr_id=unioned["union_page_ptr_id"],
-                        perex=unioned["union_perex"],
-                        date=unioned["union_date"],
-                        author=unioned["union_author"],
-                        image_id=unioned["union_image_id"],
-                        search_image_id=unioned["union_search_image_id"],
-                        content=unioned["union_content"],
-                        author_page_id=unioned["union_author_page_id"],
-                        is_black=unioned["union_is_black"],
-                        thumb_image_id=unioned["union_thumb_image_id"],
+                    lambda unioned: DistrictArticlePage.objects.create(
+                        **reduce(assign_to_model(unioned), district_meta_fields, {})
                     ),
                     evaluated,
                 )
             )
 
-        if source is SharedArticleTypes.UNIWEB:
+        if isinstance(self, UniwebArticlesIndexPage):
             return list(
                 map(
                     lambda unioned: UniwebArticlePage(
-                        id=unioned["union_id"],
-                        page_ptr_id=unioned["union_page_ptr_id"],
-                        perex=unioned["union_perex"],
-                        date=unioned["union_date"],
-                        author=unioned["union_author"],
-                        image_id=unioned["union_image_id"],
-                        search_image_id=unioned["union_search_image_id"],
-                        content=unioned["union_content"],
+                        **reduce(assign_to_model(unioned), uniweb_meta_fields, {})
                     ),
                     evaluated,
                 )
             )
 
-        if source is SharedArticleTypes.MAIN:
+        if isinstance(self, MainArticlesPage):
             return list(
                 map(
                     lambda unioned: MainArticlePage(
-                        id=unioned["union_id"],
-                        page_ptr_id=unioned["union_page_ptr_id"],
-                        perex=unioned["union_perex"],
-                        date=unioned["union_date"],
-                        author=unioned["union_author"],
-                        image_id=unioned["union_image_id"],
-                        search_image_id=unioned["union_search_image_id"],
-                        content=unioned["union_content"],
-                        author_page_id=unioned["union_author_page_id"],
-                        region=unioned["union_author_page_id"],
-                        article_type=unioned["union_article_type"],
-                        is_black=unioned["union_is_black"],
-                        thumb_image_id=unioned["union_thumb_image_id"],
+                        **reduce(assign_to_model(unioned), main_meta_fields, {})
                     ),
                     evaluated,
                 )
diff --git a/uniweb/models.py b/uniweb/models.py
index 72bc8b9e8a95cef5ebdeb075f95608f9f73df4df..ad9e2dde58d6c548598429dd86c9d7623204e5ef 100644
--- a/uniweb/models.py
+++ b/uniweb/models.py
@@ -35,7 +35,6 @@ from shared.models import (
     ExtendedMetadataHomePageMixin,
     ExtendedMetadataPageMixin,
     FooterMixin,
-    SharedArticleTypes,
     SharedTaggedUniwebArticle,
     SubpageMixin,
 )
@@ -550,7 +549,7 @@ class UniwebArticlesIndexPage(
         tag = request.GET.get("tag")
 
         articles = self.append_all_shared_articles(
-            SharedArticleTypes.UNIWEB, UniwebArticlePage.objects.child_of(self)
+            UniwebArticlePage.objects.child_of(self)
         )
 
         if tag is not None: