diff --git a/shared/models.py b/shared/models.py index f9e149ca8f963356da7c5549cd9b82d22a975085..f45f82be2d3e2fe7df8fc85459bf8891e524de5f 100644 --- a/shared/models.py +++ b/shared/models.py @@ -429,10 +429,19 @@ class ArticlesMixin(models.Model): district_meta_fields = DistrictArticlePage._meta.fields uniweb_meta_fields = UniwebArticlePage._meta.fields + # dictionary of class types of fields, assumes that a field cannot have a different type in each web + fields_dict = reduce( + lambda class_dict, field: self.merge_dict( + class_dict, {f"union_{field.column}": field} + ), + [*main_meta_fields, *district_meta_fields, *uniweb_meta_fields], + {}, + ) + fields_reducer = ( lambda assigned, field: assigned if field.column == "shared_from_id" or field.column == "shared_type" - else assigned | {f"union_{field.column}": F(field.column)} + else self.merge_dict(assigned, {f"union_{field.column}": F(field.column)}) ) setup_fields_order = lambda orderBy, orderFrom: reduce( lambda orderTo, field: self.merge_dict(orderTo, {field: orderFrom[field]}), @@ -440,34 +449,69 @@ class ArticlesMixin(models.Model): {}, ) - main_fields = reduce(fields_reducer, main_meta_fields, {}) | { + district_only_fields = reduce(fields_reducer, district_meta_fields, {}) + uniweb_only_fields = reduce(fields_reducer, uniweb_meta_fields, {}) + main_only_fields = reduce(fields_reducer, main_meta_fields, {}) + + key_fields_default_values = { "union_thumb_image_id": F("search_image_id"), + "union_article_type": Value(2, models.PositiveSmallIntegerField()), } + create_complementary_field = lambda key: ( + key_fields_default_values[key] + if key in key_fields_default_values + else ( + # any type will suffice in the foreign key + Value( + None, + models.ForeignKey( + DistrictArticlePage, blank=True, on_delete=models.SET_NULL + ), + ) + if isinstance(fields_dict[key], models.ForeignKey) + else Value(None, fields_dict[key].__class__()) + ) + ) + + reduce_complementary_fields = lambda complementary, item, notIn: ( + self.merge_dict( + complementary, {item[0]: create_complementary_field(item[0])} + ) + if item[0] not in notIn + else complementary + ) + + create_complementary_fields = lambda notIn, fromFields: reduce( + lambda complementary, item: reduce_complementary_fields( + complementary, item, dict(notIn) + ), + reduce( + lambda sources, source: sources + list(source.items()), fromFields, [] + ), + {}, + ) + + district_complementary_fields = create_complementary_fields( + district_only_fields, [uniweb_only_fields, main_only_fields] + ) + uniweb_complementary_fields = create_complementary_fields( + uniweb_only_fields, [district_only_fields, main_only_fields] + ) + main_complementary_fields = create_complementary_fields( + main_only_fields, [uniweb_only_fields, district_only_fields] + ) + + main_fields = main_only_fields | main_complementary_fields + district_fields = setup_fields_order( main_fields, - reduce(fields_reducer, district_meta_fields, {}) - | { - "union_region": Value(None, models.CharField()), - "union_article_type": Value(2, models.PositiveSmallIntegerField()), - }, + district_only_fields | district_complementary_fields, ) uniweb_fields = setup_fields_order( main_fields, - reduce(fields_reducer, uniweb_meta_fields, {}) - | { - "union_author_page_id": Value( - None, - output_field=models.ForeignKey( - DistrictArticlePage, blank=True, on_delete=models.SET_NULL - ), - ), - "union_region": Value(None, models.CharField()), - "union_article_type": Value(2, models.PositiveSmallIntegerField()), - "union_is_black": Value(False, models.BooleanField()), - "union_thumb_image_id": F("search_image_id"), - }, + uniweb_only_fields | uniweb_complementary_fields, ) district_article_query: models.QuerySet = DistrictArticlePage.objects