4 changed files with 123 additions and 0 deletions
-
123apps/article/management/commands/populate_article.py
-
BINseeds/images/articl2.jpg
-
BINseeds/images/articl3.jpg
-
BINseeds/images/articl4.jpg
@ -0,0 +1,123 @@ |
|||||
|
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!')) |
||||
|
After Width: 1500 | Height: 1000 | Size: 1.2 MiB |
|
After Width: 1192 | Height: 796 | Size: 254 KiB |
|
After Width: 1192 | Height: 895 | Size: 223 KiB |
Write
Preview
Loading…
Cancel
Save
Reference in new issue