Closed duker33 closed 5 years ago
it's the version to fix the DB structure
import typing
from stroyprombeton.models import Product, Category
from pages.models import Page
from contextlib import contextmanager
from django.db import transaction
@contextmanager
def non_persistence():
with transaction.atomic():
point = transaction.savepoint()
yield
transaction.savepoint_rollback(point)
def get_bad_products():
bad_products = []
for p in Product.objects.all():
pages = p.page.get_ancestors(include_self=False).values_list('id', flat=True)[1:]
categories = p.category.get_ancestors(include_self=True)
categories_list = [c.page.id for c in categories]
if not all(p == c for p, c in zip(pages, categories_list)):
bad_products.append(p)
return bad_products
def get_bad_categories():
bad_categories = []
bad_pairs = []
for c in Category.objects.all():
pages = c.page.get_ancestors(include_self=True).values_list('id', flat=True)[1:]
categories = c.get_ancestors(include_self=True)
categories_list = [c.page.id for c in categories]
if not all(p == c for p, c in zip(pages, categories_list)):
bad_categories.append(c)
bad_pairs.append((pages, categories_list))
# print('\n---\n'.join(['\n'.join([p, c]) for p, c in bad_pairs[:20]]))
return bad_categories
def fix_ancestors(category: Category):
ancestors = category.get_ancestors(ascending=True, include_self=True)
for cur, next in zip(ancestors, ancestors[1:]):
cur.page.parent = next.page
cur.page.save()
def fix_categories(bad_categories: typing.List[Category]):
for category in Category.objects.filter(id__in=[c.id for c in bad_categories]):
fix_ancestors(category)
def fix_products(bad_products: typing.List[Product]):
for product in Product.objects.filter(id__in=[p.id for p in bad_products]):
product.page.parent = product.category.page
product.page.save()
fix_ancestors(product.category)
with non_persistence():
bad_categories = get_bad_categories()
bad_products = get_bad_products()
print(f'bad categories before: {len(bad_categories)}')
print(f'bad products before: {len(bad_products)}')
fix_categories(bad_categories)
fix_products(bad_products)
Page.objects.rebuild()
print(f'bad categories after: {len(get_bad_categories())}')
print(f'bad products after: {len(get_bad_products())}')
It's output. Seems all is correct
bad categories after: 14
bad products after: 19
bad categories before: 0
bad products before: 0
Take the wrong products and categories from the script from comment and fix them automatically or manually https://github.com/fidals/stroyprombeton/issues/691#issuecomment-503016706