Browse Source
Add management commands for category and collection seeding
Add management commands for category and collection seeding
- Introduced a new command to evenly distribute source types across existing HadisCategory instances. - Added a command to seed categories and collections in the library, relating existing books to them. - Enhanced HadisCategory model to allow Unicode in slugs through a migration. - Updated Nginx configuration to include a new location for proxying requests to a FastAPI agent.master
5 changed files with 139 additions and 1 deletions
-
42apps/hadis/management/commands/category_fix.py
-
19apps/hadis/migrations/0005_alter_hadiscategory_slug.py
-
2apps/hadis/models/category.py
-
66apps/library/management/commands/seed_category_collection.py
-
11nginx/dovodi.conf
@ -0,0 +1,42 @@ |
|||||
|
from django.core.management.base import BaseCommand |
||||
|
from django.db import transaction |
||||
|
from apps.hadis.models import HadisCategory |
||||
|
|
||||
|
class Command(BaseCommand): |
||||
|
help = 'توزیع متعادل انواع منابع (Source Types) بین تمام دستهبندیهای موجود' |
||||
|
|
||||
|
def handle(self, *args, **options): |
||||
|
self.stdout.write(self.style.WARNING('--- در حال بهروزرسانی انواع منابع ---')) |
||||
|
|
||||
|
# دریافت تمام گزینههای موجود در SourceType |
||||
|
source_choices = [choice[0] for choice in HadisCategory.SourceType.choices] |
||||
|
num_choices = len(source_choices) |
||||
|
|
||||
|
# دریافت تمام دستهبندیها به ترتیب شناسه یا ترتیب دلخواه |
||||
|
categories = HadisCategory.objects.all().order_by('id') |
||||
|
total_count = categories.count() |
||||
|
|
||||
|
if total_count == 0: |
||||
|
self.stdout.write(self.style.ERROR('هیچ دستهبندی یافت نشد.')) |
||||
|
return |
||||
|
|
||||
|
updated_count = 0 |
||||
|
|
||||
|
with transaction.atomic(): |
||||
|
for index, category in enumerate(categories): |
||||
|
# انتخاب نوع منبع به صورت چرخشی |
||||
|
# این کار باعث میشود اگر ۱۲۰ مورد دارید، به هر نوع منبع دقیقاً ۲۴ مورد برسد |
||||
|
new_source = source_choices[index % num_choices] |
||||
|
|
||||
|
category.source_type = new_source |
||||
|
# استفاده از update_fields برای افزایش سرعت و جلوگیری از اجرای سیگنالهای اضافی در صورت تمایل |
||||
|
category.save(update_fields=['source_type']) |
||||
|
updated_count += 1 |
||||
|
|
||||
|
self.stdout.write(self.style.SUCCESS(f'✓ عملیات با موفقیت انجام شد.')) |
||||
|
self.stdout.write(self.style.SUCCESS(f'تعداد {updated_count} دستهبندی بهروزرسانی شدند.')) |
||||
|
|
||||
|
# نمایش آمار نهایی برای اطمینان از تعادل |
||||
|
for source in source_choices: |
||||
|
count = HadisCategory.objects.filter(source_type=source).count() |
||||
|
self.stdout.write(f" - {source}: {count} مورد") |
||||
@ -0,0 +1,19 @@ |
|||||
|
# Generated by Django 4.2.27 on 2026-01-28 10:31 |
||||
|
|
||||
|
from django.db import migrations, models |
||||
|
|
||||
|
|
||||
|
class Migration(migrations.Migration): |
||||
|
dependencies = [ |
||||
|
("hadis", "0004_alter_hadiscollection_thumbnail_and_more"), |
||||
|
] |
||||
|
|
||||
|
operations = [ |
||||
|
migrations.AlterField( |
||||
|
model_name="hadiscategory", |
||||
|
name="slug", |
||||
|
field=models.SlugField( |
||||
|
allow_unicode=True, blank=True, max_length=255, null=True |
||||
|
), |
||||
|
), |
||||
|
] |
||||
@ -0,0 +1,66 @@ |
|||||
|
import random |
||||
|
from django.core.management.base import BaseCommand |
||||
|
from django.db import transaction |
||||
|
from apps.library.models import Book, Category, BookCollection |
||||
|
|
||||
|
class Command(BaseCommand): |
||||
|
help = 'Seeds categories and collections and relates all existing books to them.' |
||||
|
|
||||
|
def handle(self, *args, **options): |
||||
|
self.stdout.write(self.style.WARNING('--- Starting Library Relation Seeding ---')) |
||||
|
|
||||
|
with transaction.atomic(): |
||||
|
# 1. CREATE CATEGORIES (10 Instances) |
||||
|
categories_data = [ |
||||
|
'Classic Literature', 'Dystopian Fiction', 'Modern Philosophy', |
||||
|
'Historical Mystery', 'Self-Improvement', 'Biographical Memoir', |
||||
|
'Fantasy & Adventure', 'Social Science', 'Science & Technology', |
||||
|
'Religious Studies' |
||||
|
] |
||||
|
|
||||
|
category_objs = [] |
||||
|
for title in categories_data: |
||||
|
cat, created = Category.objects.get_or_create(title=title) |
||||
|
category_objs.append(cat) |
||||
|
if created: |
||||
|
self.stdout.write(f"Created Category: {title}") |
||||
|
|
||||
|
# 2. CREATE COLLECTIONS (5 Instances) |
||||
|
collections_data = [ |
||||
|
{'title': 'Editor\'s Choice 2026', 'pos': BookCollection.DisplayPosition.PINNED}, |
||||
|
{'title': 'Most Downloaded This Month', 'pos': BookCollection.DisplayPosition.PINNED}, |
||||
|
{'title': 'New Arrivals', 'pos': BookCollection.DisplayPosition.MIDDLE}, |
||||
|
{'title': 'Essential Reading List', 'pos': BookCollection.DisplayPosition.MIDDLE}, |
||||
|
{'title': 'Summer Recommendations', 'pos': BookCollection.DisplayPosition.MIDDLE}, |
||||
|
] |
||||
|
|
||||
|
collection_objs = [] |
||||
|
for item in collections_data: |
||||
|
col, created = BookCollection.objects.get_or_create( |
||||
|
title=item['title'], |
||||
|
defaults={'display_position': item['pos'], 'pin_top': True} |
||||
|
) |
||||
|
collection_objs.append(col) |
||||
|
if created: |
||||
|
self.stdout.write(f"Created Collection: {item['title']}") |
||||
|
|
||||
|
# 3. RELATE BOOKS |
||||
|
books = Book.objects.all() |
||||
|
if not books.exists(): |
||||
|
self.stdout.write(self.style.ERROR('No books found! Please run the book population script first.')) |
||||
|
return |
||||
|
|
||||
|
self.stdout.write(self.style.SUCCESS(f'Processing {books.count()} books...')) |
||||
|
|
||||
|
for book in books: |
||||
|
# Rule: Every book must have at least 3 categories |
||||
|
# We pick 3 to 4 random categories to ensure variety |
||||
|
selected_cats = random.sample(category_objs, k=random.randint(3, 4)) |
||||
|
book.categories.set(selected_cats) |
||||
|
|
||||
|
# Rule: Every book must be in 1 or 2 collections |
||||
|
selected_cols = random.sample(collection_objs, k=random.randint(1, 2)) |
||||
|
book.collections.set(selected_cols) |
||||
|
|
||||
|
self.stdout.write(self.style.SUCCESS('--- Seeding Completed Successfully ---')) |
||||
|
self.stdout.write(f'Summary: {len(category_objs)} Categories, {len(collection_objs)} Collections applied to {books.count()} books.') |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue