Merge branch 'fix_news_slug_unique' into 'develop'
Fix news slug unique See merge request gm/gm-backend!269
This commit is contained in:
commit
ae71fde843
|
|
@ -24,6 +24,8 @@ from utils.models import (
|
||||||
TJSONField, TranslatedFieldsMixin, TypeDefaultImageMixin,
|
TJSONField, TranslatedFieldsMixin, TypeDefaultImageMixin,
|
||||||
CarouselMixin)
|
CarouselMixin)
|
||||||
from utils.querysets import TranslationQuerysetMixin
|
from utils.querysets import TranslationQuerysetMixin
|
||||||
|
from location.models import Country
|
||||||
|
from utils.parsers import NewsSlug
|
||||||
|
|
||||||
|
|
||||||
class Agenda(ProjectBaseMixin, TranslatedFieldsMixin):
|
class Agenda(ProjectBaseMixin, TranslatedFieldsMixin):
|
||||||
|
|
@ -362,9 +364,36 @@ class News(GalleryMixin,
|
||||||
return f'news: {next(iter(self.slugs.values()))}'
|
return f'news: {next(iter(self.slugs.values()))}'
|
||||||
|
|
||||||
def create_duplicate(self, new_country, view_count_model):
|
def create_duplicate(self, new_country, view_count_model):
|
||||||
|
country_codes = list(Country.objects.all().values_list('code', flat=True))
|
||||||
|
|
||||||
|
# Get all existed slugs
|
||||||
|
all_slugs = {slug_value
|
||||||
|
for slug_dict in News.objects.all().values_list('slugs', flat=True)
|
||||||
|
for slug_value in slug_dict.values()}
|
||||||
|
|
||||||
|
new_slugs = {}
|
||||||
|
for locale, raw_slug in self.slugs.items():
|
||||||
|
slug = NewsSlug.parse(raw_slug, country_codes)
|
||||||
|
|
||||||
|
# all slugs LIKE% slug
|
||||||
|
similar_slugs = sorted(x for x in all_slugs if NewsSlug.parse(x, country_codes).value == slug.value)
|
||||||
|
|
||||||
|
if len(similar_slugs) == 0:
|
||||||
|
# It is impossible because at least current instance has slug
|
||||||
|
raise ValueError('Duplicating unsaved object')
|
||||||
|
else:
|
||||||
|
# The last slug in similar_slugs is slug with largest count
|
||||||
|
last_slug = NewsSlug.parse(similar_slugs[-1], country_codes)
|
||||||
|
|
||||||
|
new_slug = NewsSlug(slug.value, new_country.code, last_slug.count)
|
||||||
|
if last_slug.country_code is not None:
|
||||||
|
new_slug.count += 1
|
||||||
|
|
||||||
|
new_slugs[locale] = str(new_slug)
|
||||||
|
|
||||||
self.pk = None
|
self.pk = None
|
||||||
self.state = self.UNPUBLISHED
|
self.state = self.UNPUBLISHED
|
||||||
self.slugs = {locale: f'{slug}-{new_country.code}' for locale, slug in self.slugs.items()}
|
self.slugs = new_slugs
|
||||||
self.country = new_country
|
self.country = new_country
|
||||||
self.views_count = view_count_model
|
self.views_count = view_count_model
|
||||||
self.duplication_date = timezone.now()
|
self.duplication_date = timezone.now()
|
||||||
|
|
|
||||||
49
apps/utils/parsers.py
Normal file
49
apps/utils/parsers.py
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
|
||||||
|
|
||||||
|
class NewsSlug:
|
||||||
|
def __init__(self, value=None, country_code=None, count=0):
|
||||||
|
self.value = value
|
||||||
|
self.country_code = country_code
|
||||||
|
self.count = count
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def parse(cls, raw_slug, country_codes):
|
||||||
|
slug, *rest = raw_slug.split('-')
|
||||||
|
instance = NewsSlug()
|
||||||
|
|
||||||
|
if len(rest) >= 1 and rest[-1] in country_codes:
|
||||||
|
# It is like 'slug-en'
|
||||||
|
|
||||||
|
instance.value = '-'.join([slug, *rest[:-1]])
|
||||||
|
instance.country_code = rest[-1]
|
||||||
|
elif len(rest) >= 2 and rest[-1].isdigit() and rest[-2] in country_codes:
|
||||||
|
# It is like 'slug-en-1'
|
||||||
|
|
||||||
|
instance.value = '-'.join([slug, *rest[:-2]])
|
||||||
|
instance.country_code = rest[-2]
|
||||||
|
instance.count = int(rest[-1])
|
||||||
|
else:
|
||||||
|
# It is like 'slug'
|
||||||
|
|
||||||
|
instance.value = '-'.join([slug, *rest])
|
||||||
|
|
||||||
|
return instance
|
||||||
|
|
||||||
|
def __lt__(self, other):
|
||||||
|
return self.value < other.value
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
if self.value is None:
|
||||||
|
raise ValueError('No value for slug')
|
||||||
|
|
||||||
|
slug_parts = [self.value]
|
||||||
|
if self.country_code is not None:
|
||||||
|
slug_parts.append(self.country_code)
|
||||||
|
|
||||||
|
if self.count != 0:
|
||||||
|
slug_parts.append(str(self.count))
|
||||||
|
|
||||||
|
return '-'.join(slug_parts)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f'<{self.__class__.__name__} {self.value}, {self.country_code}, {self.count}>'
|
||||||
Loading…
Reference in New Issue
Block a user