You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
123 lines
5.1 KiB
123 lines
5.1 KiB
import os
|
|
import random
|
|
from django.core.management.base import BaseCommand
|
|
from django.core.files import File
|
|
from django.conf import settings
|
|
from django.db import transaction
|
|
|
|
# REPLACE 'apps.article.models' WITH YOUR ACTUAL APP PATH
|
|
from apps.article.models import (
|
|
Article,
|
|
ArticleCategory,
|
|
ArticleCollection,
|
|
ArticleInCollection,
|
|
ArticleContent,
|
|
ContentPart,
|
|
TextSection
|
|
)
|
|
|
|
class Command(BaseCommand):
|
|
help = 'Seeds 25 articles with categories, collections, and structured content.'
|
|
|
|
def handle(self, *args, **kwargs):
|
|
self.stdout.write('Seeding Articles...')
|
|
|
|
# 1. Configuration
|
|
TOTAL_ARTICLES = 25
|
|
CATEGORY_IDS = [6, 7, 8, 9]
|
|
CONTENT_SOURCE_IDS = range(13, 24) # IDs 13 to 23
|
|
IMAGE_DIR = os.path.join(settings.BASE_DIR, 'seeds', 'images')
|
|
IMAGE_NAMES = [f'articl{i}.jpg' for i in range(2, 5)]
|
|
|
|
# 2. Fetch Existing Dependencies
|
|
categories = list(ArticleCategory.objects.filter(id__in=CATEGORY_IDS))
|
|
if not categories:
|
|
self.stdout.write(self.style.WARNING(f"Categories with IDs {CATEGORY_IDS} not found. Skipping category assignment."))
|
|
|
|
# 3. Create 4 New Collections
|
|
collections = []
|
|
for i in range(1, 5):
|
|
col, created = ArticleCollection.objects.get_or_create(
|
|
title=f'Seeded Collection {i}',
|
|
defaults={
|
|
'slug': f'seeded-collection-{i}',
|
|
'summary': f'This is a generated summary for collection {i}',
|
|
'display_position': ArticleCollection.DisplayPosition.MIDDLE
|
|
}
|
|
)
|
|
collections.append(col)
|
|
self.stdout.write(self.style.SUCCESS(f'Created/Loaded {len(collections)} collections.'))
|
|
|
|
# 4. Fetch Source Content for Cloning
|
|
# NOTE: Since ArticleContent is a ForeignKey (One-to-Many), we cannot
|
|
# link existing content objects to new articles without removing them
|
|
# from their old articles. Instead, we will CLONE their data.
|
|
source_contents = list(ArticleContent.objects.filter(id__in=CONTENT_SOURCE_IDS))
|
|
if not source_contents:
|
|
self.stdout.write(self.style.WARNING(f"ArticleContents with IDs 13-23 not found. Creating generic content instead."))
|
|
|
|
# 5. Main Loop: Create Articles
|
|
with transaction.atomic():
|
|
for i in range(1, TOTAL_ARTICLES + 1):
|
|
title = f'Seeded Article Title {i}'
|
|
|
|
# Create Article
|
|
article = Article.objects.create(
|
|
title=title,
|
|
description=f'Description for article {i}. Lorem ipsum dolor sit amet.',
|
|
content=f'Full content body for article {i}.',
|
|
status=True
|
|
)
|
|
|
|
# Assign Thumbnail (Cycle through images 1-5)
|
|
img_name = IMAGE_NAMES[(i - 1) % len(IMAGE_NAMES)]
|
|
img_path = os.path.join(IMAGE_DIR, img_name)
|
|
|
|
if os.path.exists(img_path):
|
|
with open(img_path, 'rb') as f:
|
|
article.thumbnail.save(img_name, File(f), save=True)
|
|
else:
|
|
self.stdout.write(self.style.WARNING(f"Image not found at {img_path}"))
|
|
|
|
# Assign Categories (Randomly pick 1 or 2)
|
|
if categories:
|
|
article.categories.add(*random.sample(categories, k=random.randint(1, 2)))
|
|
|
|
# Assign to Collections (Randomly pick 1)
|
|
random_col = random.choice(collections)
|
|
ArticleInCollection.objects.create(
|
|
article=article,
|
|
collection=random_col,
|
|
order=i
|
|
)
|
|
|
|
# Create Article Content (Cloning from IDs 13-23 or Generic)
|
|
if source_contents:
|
|
# Pick a random template from the requested IDs
|
|
template = random.choice(source_contents)
|
|
content_title = f"{template.title} (Copy for Article {i})"
|
|
content_body = template.content
|
|
else:
|
|
content_title = f"Structured Content for Article {i}"
|
|
content_body = "This is a section of structured content."
|
|
|
|
# Create the ArticleContent object linked to this NEW article
|
|
ac = ArticleContent.objects.create(
|
|
article=article,
|
|
title=content_title,
|
|
content=content_body,
|
|
priority=1
|
|
)
|
|
|
|
# Create nested ContentParts and TextSections
|
|
part = ContentPart.objects.create(article_content=ac, order=1)
|
|
TextSection.objects.create(
|
|
content_part=part,
|
|
arabic_text="نص تجريبي باللغة العربية",
|
|
translation="Experimental text in English translation",
|
|
order=1
|
|
)
|
|
|
|
self.stdout.write(f'Created Article: {article.title}')
|
|
|
|
self.stdout.write(self.style.SUCCESS(f'Successfully seeded {TOTAL_ARTICLES} articles!'))
|