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.
514 lines
26 KiB
514 lines
26 KiB
"""
|
|
Django Management Command: populate_books
|
|
|
|
This command creates 20 book objects with related categories and collections,
|
|
including thumbnails and a dummy PDF file.
|
|
|
|
Usage:
|
|
python manage.py populate_books
|
|
"""
|
|
|
|
from django.core.management.base import BaseCommand
|
|
from django.utils.text import slugify
|
|
from apps.library.models import Book, Category, BookCollection
|
|
from dj_language.models import Language
|
|
import random
|
|
from django.conf import settings
|
|
import os
|
|
from django.core.files import File # Import File wrapper
|
|
|
|
class Command(BaseCommand):
|
|
help = 'Create 20 book objects with categories, collections, and a PDF file'
|
|
|
|
def handle(self, *args, **options):
|
|
# 1. DELETE OLD DATA
|
|
self.stdout.write(self.style.WARNING('Deleting existing books...'))
|
|
deleted_count = Book.objects.all().delete()[0]
|
|
self.stdout.write(self.style.SUCCESS(f'✓ Deleted {deleted_count} existing books'))
|
|
|
|
# 2. SETUP PATHS
|
|
base_dir = settings.BASE_DIR
|
|
|
|
# Image Paths
|
|
seeds_images_path = os.path.join(base_dir, 'seeds', 'images')
|
|
image_filenames = [
|
|
'lib-book1.png', 'lib-book2.png', 'lib-book3.png', 'lib-book4.png'
|
|
]
|
|
|
|
# PDF Path
|
|
pdf_path = os.path.join(base_dir, 'seeds', 'pdf', 'e-book.pdf')
|
|
|
|
# Check if PDF exists before starting
|
|
if not os.path.exists(pdf_path):
|
|
self.stdout.write(self.style.ERROR(f'CRITICAL: PDF not found at {pdf_path}'))
|
|
return
|
|
|
|
# 3. GET OR CREATE LANGUAGE
|
|
language, created = Language.objects.get_or_create(
|
|
code='en', defaults={'name': 'English'}
|
|
)
|
|
|
|
# 4. DATA DEFINITION
|
|
book_data = [
|
|
{
|
|
'title': 'To Kill a Mockingbird',
|
|
'slogan': 'A powerful story of racial injustice and childhood innocence',
|
|
'summary_title': 'Classic American Literature',
|
|
'summary': 'Harper Lee\'s timeless novel about courage and morality',
|
|
'description': 'Set in the 1930s, this novel explores themes of racism, justice, and moral growth through the eyes of a young girl.',
|
|
'publisher': 'J.B. Lippincott & Co.',
|
|
'year_of_publication': '1960',
|
|
'author': 'Harper Lee',
|
|
'isbn': '978-0061120084',
|
|
'numnber_of_volume': '1',
|
|
'main_themes': ['racism', 'justice', 'childhood', 'morality'],
|
|
'notable_works': ['Pulitzer Prize Winner', 'American Classic'],
|
|
'pages_count': '376',
|
|
'file_type': 'pdf',
|
|
},
|
|
{
|
|
'title': 'Pride and Prejudice',
|
|
'slogan': 'A witty romance of manners and marriage',
|
|
'summary_title': 'Jane Austen\'s Masterpiece',
|
|
'summary': 'Elizabeth Bennet navigates love, reputation, and society',
|
|
'description': 'This beloved novel follows the spirited Elizabeth Bennet as she deals with issues of manners, upbringing, morality, and marriage.',
|
|
'publisher': 'T. Egerton',
|
|
'year_of_publication': '1813',
|
|
'author': 'Jane Austen',
|
|
'isbn': '978-0141439518',
|
|
'numnber_of_volume': '1',
|
|
'main_themes': ['romance', 'society', 'marriage', 'class'],
|
|
'notable_works': ['British Literature', 'Social Commentary'],
|
|
'pages_count': '432',
|
|
'file_type': 'pdf',
|
|
},
|
|
{
|
|
'title': 'The Great Gatsby',
|
|
'slogan': 'The American Dream in the Jazz Age',
|
|
'summary_title': 'F. Scott Fitzgerald\'s Classic',
|
|
'summary': 'A tale of wealth, love, and the American Dream',
|
|
'description': 'Set in the summer of 1922, this novel explores the lives of wealthy socialites and their obsession with status and love.',
|
|
'publisher': 'Charles Scribner\'s Sons',
|
|
'year_of_publication': '1925',
|
|
'author': 'F. Scott Fitzgerald',
|
|
'isbn': '978-0743273565',
|
|
'numnber_of_volume': '1',
|
|
'main_themes': ['wealth', 'love', 'american dream', 'jazz age'],
|
|
'notable_works': ['Modern Classic', 'American Literature'],
|
|
'pages_count': '180',
|
|
'file_type': 'pdf',
|
|
},
|
|
{
|
|
'title': '1984',
|
|
'slogan': 'A dystopian vision of totalitarian control',
|
|
'summary_title': 'George Orwell\'s Warning',
|
|
'summary': 'Big Brother is watching in this chilling dystopia',
|
|
'description': 'In a totalitarian future where truth is manipulated and privacy is nonexistent, Winston Smith begins to question the regime.',
|
|
'publisher': 'Secker & Warburg',
|
|
'year_of_publication': '1949',
|
|
'author': 'George Orwell',
|
|
'isbn': '978-0451524935',
|
|
'numnber_of_volume': '1',
|
|
'main_themes': ['totalitarianism', 'surveillance', 'freedom', 'truth'],
|
|
'notable_works': ['Dystopian Fiction', 'Political Satire'],
|
|
'pages_count': '328',
|
|
'file_type': 'pdf',
|
|
},
|
|
{
|
|
'title': 'The Catcher in the Rye',
|
|
'slogan': 'A teenager\'s journey through alienation and identity',
|
|
'summary_title': 'J.D. Salinger\'s Coming-of-Age Story',
|
|
'summary': 'Holden Caulfield\'s honest and raw narration of teenage angst',
|
|
'description': 'Sixteen-year-old Holden Caulfield has been expelled from yet another school and wanders New York City in a state of alienation.',
|
|
'publisher': 'Little, Brown and Company',
|
|
'year_of_publication': '1951',
|
|
'author': 'J.D. Salinger',
|
|
'isbn': '978-0316769488',
|
|
'numnber_of_volume': '1',
|
|
'main_themes': ['adolescence', 'alienation', 'identity', 'innocence'],
|
|
'notable_works': ['Coming-of-Age', 'American Literature'],
|
|
'pages_count': '277',
|
|
'file_type': 'pdf',
|
|
},
|
|
{
|
|
'title': 'Harry Potter and the Philosopher\'s Stone',
|
|
'slogan': 'A young wizard\'s magical adventure begins',
|
|
'summary_title': 'J.K. Rowling\'s Magical World',
|
|
'summary': 'Harry discovers he\'s a wizard and attends Hogwarts School',
|
|
'description': 'Orphaned Harry Potter discovers on his 11th birthday that he is a wizard and begins his magical education at Hogwarts.',
|
|
'publisher': 'Bloomsbury',
|
|
'year_of_publication': '1997',
|
|
'author': 'J.K. Rowling',
|
|
'isbn': '978-0747532699',
|
|
'numnber_of_volume': '1',
|
|
'main_themes': ['magic', 'friendship', 'courage', 'good vs evil'],
|
|
'notable_works': ['Fantasy Series', 'Children\'s Literature'],
|
|
'pages_count': '223',
|
|
'file_type': 'pdf',
|
|
},
|
|
{
|
|
'title': 'The Lord of the Rings: The Fellowship of the Ring',
|
|
'slogan': 'An epic tale of adventure and heroism',
|
|
'summary_title': 'J.R.R. Tolkien\'s Masterpiece',
|
|
'summary': 'Frodo\'s quest to destroy the One Ring',
|
|
'description': 'In Middle-earth, the Dark Lord Sauron seeks the One Ring to conquer all. A fellowship forms to prevent this catastrophe.',
|
|
'publisher': 'George Allen & Unwin',
|
|
'year_of_publication': '1954',
|
|
'author': 'J.R.R. Tolkien',
|
|
'isbn': '978-0547928210',
|
|
'numnber_of_volume': '1',
|
|
'main_themes': ['adventure', 'friendship', 'courage', 'destiny'],
|
|
'notable_works': ['Epic Fantasy', 'World Building'],
|
|
'pages_count': '423',
|
|
'file_type': 'pdf',
|
|
},
|
|
{
|
|
'title': 'The Alchemist',
|
|
'slogan': 'Follow your dreams and listen to your heart',
|
|
'summary_title': 'Paulo Coelho\'s Inspirational Tale',
|
|
'summary': 'A shepherd boy\'s journey to find his personal legend',
|
|
'description': 'Santiago, an Andalusian shepherd boy, dreams of finding a worldly treasure and embarks on a journey of self-discovery.',
|
|
'publisher': 'HarperOne',
|
|
'year_of_publication': '1988',
|
|
'author': 'Paulo Coelho',
|
|
'isbn': '978-0061122415',
|
|
'numnber_of_volume': '1',
|
|
'main_themes': ['dreams', 'destiny', 'spirituality', 'journey'],
|
|
'notable_works': ['Inspirational Fiction', 'Self-Discovery'],
|
|
'pages_count': '208',
|
|
'file_type': 'pdf',
|
|
},
|
|
{
|
|
'title': 'The Da Vinci Code',
|
|
'slogan': 'A thriller that uncovers ancient secrets',
|
|
'summary_title': 'Dan Brown\'s Mystery Thriller',
|
|
'summary': 'Robert Langdon races to solve a murder mystery',
|
|
'description': 'Harvard symbologist Robert Langdon becomes involved in a murder mystery that reveals secrets about the Holy Grail.',
|
|
'publisher': 'Doubleday',
|
|
'year_of_publication': '2003',
|
|
'author': 'Dan Brown',
|
|
'isbn': '978-0385504201',
|
|
'numnber_of_volume': '1',
|
|
'main_themes': ['mystery', 'conspiracy', 'religion', 'history'],
|
|
'notable_works': ['Thriller', 'Bestseller'],
|
|
'pages_count': '454',
|
|
'file_type': 'pdf',
|
|
},
|
|
{
|
|
'title': 'Sapiens: A Brief History of Humankind',
|
|
'slogan': 'The story of our species from ancient times to modern day',
|
|
'summary_title': 'Yuval Noah Harari\'s Evolutionary History',
|
|
'summary': 'How Homo sapiens became Earth\'s dominant species',
|
|
'description': 'This book explores the history of humankind from the Stone Age to the modern age, examining how we came to dominate Earth.',
|
|
'publisher': 'Harper',
|
|
'year_of_publication': '2014',
|
|
'author': 'Yuval Noah Harari',
|
|
'isbn': '978-0062316097',
|
|
'numnber_of_volume': '1',
|
|
'main_themes': ['history', 'evolution', 'civilization', 'humanity'],
|
|
'notable_works': ['Non-fiction', 'Anthropology'],
|
|
'pages_count': '443',
|
|
'file_type': 'pdf',
|
|
},
|
|
{
|
|
'title': 'Educated',
|
|
'slogan': 'A memoir of survival and education',
|
|
'summary_title': 'Tara Westover\'s Life Story',
|
|
'summary': 'A woman\'s quest for knowledge despite her isolated upbringing',
|
|
'description': 'Tara Westover grew up in a survivalist family in rural Idaho and fought to educate herself against all odds.',
|
|
'publisher': 'Random House',
|
|
'year_of_publication': '2018',
|
|
'author': 'Tara Westover',
|
|
'isbn': '978-0399590504',
|
|
'numnber_of_volume': '1',
|
|
'main_themes': ['education', 'family', 'survival', 'identity'],
|
|
'notable_works': ['Memoir', 'Education'],
|
|
'pages_count': '334',
|
|
'file_type': 'pdf',
|
|
},
|
|
{
|
|
'title': 'Atomic Habits',
|
|
'slogan': 'Small changes, remarkable results',
|
|
'summary_title': 'James Clear\'s Guide to Better Habits',
|
|
'summary': 'How to build good habits and break bad ones',
|
|
'description': 'This book reveals how tiny changes in your daily habits can lead to remarkable transformation in your life.',
|
|
'publisher': 'Avery',
|
|
'year_of_publication': '2018',
|
|
'author': 'James Clear',
|
|
'isbn': '978-0735211292',
|
|
'numnber_of_volume': '1',
|
|
'main_themes': ['habits', 'productivity', 'self-improvement', 'psychology'],
|
|
'notable_works': ['Self-Help', 'Psychology'],
|
|
'pages_count': '320',
|
|
'file_type': 'pdf',
|
|
},
|
|
{
|
|
'title': 'The Psychology of Money',
|
|
'slogan': 'Timeless lessons on wealth, greed, and happiness',
|
|
'summary_title': 'Morgan Housel\'s Financial Wisdom',
|
|
'summary': 'Understanding the strange ways people think about money',
|
|
'description': 'This book explores the psychology behind our financial decisions and how our behavior often defies logic.',
|
|
'publisher': 'Harriman House',
|
|
'year_of_publication': '2020',
|
|
'author': 'Morgan Housel',
|
|
'isbn': '978-0857197689',
|
|
'numnber_of_volume': '1',
|
|
'main_themes': ['finance', 'psychology', 'behavior', 'wealth'],
|
|
'notable_works': ['Finance', 'Psychology'],
|
|
'pages_count': '256',
|
|
'file_type': 'pdf',
|
|
},
|
|
{
|
|
'title': 'Thinking, Fast and Slow',
|
|
'slogan': 'The groundbreaking investigation of how we think',
|
|
'summary_title': 'Daniel Kahneman\'s Cognitive Psychology',
|
|
'summary': 'How our minds work in two different modes',
|
|
'description': 'Nobel Prize winner Daniel Kahneman explores the two systems that drive how we think: fast, intuitive thinking and slow, deliberate thinking.',
|
|
'publisher': 'Farrar, Straus and Giroux',
|
|
'year_of_publication': '2011',
|
|
'author': 'Daniel Kahneman',
|
|
'isbn': '978-0374533557',
|
|
'numnber_of_volume': '1',
|
|
'main_themes': ['psychology', 'decision-making', 'cognitive bias', 'behavior'],
|
|
'notable_works': ['Psychology', 'Nobel Prize'],
|
|
'pages_count': '499',
|
|
'file_type': 'pdf',
|
|
},
|
|
{
|
|
'title': 'The Silent Patient',
|
|
'slogan': 'A woman refuses to speak after committing murder',
|
|
'summary_title': 'Alex Michaelides\' Psychological Thriller',
|
|
'summary': 'A psychotherapist becomes obsessed with his patient\'s silence',
|
|
'description': 'Alicia Berenson\'s refusal to speak after allegedly murdering her husband becomes the ultimate mystery for psychotherapist Theo Faber.',
|
|
'publisher': 'Celadon Books',
|
|
'year_of_publication': '2019',
|
|
'author': 'Alex Michaelides',
|
|
'isbn': '978-1250301697',
|
|
'numnber_of_volume': '1',
|
|
'main_themes': ['mystery', 'psychology', 'silence', 'obsession'],
|
|
'notable_works': ['Thriller', 'Psychological Fiction'],
|
|
'pages_count': '336',
|
|
'file_type': 'pdf',
|
|
},
|
|
{
|
|
'title': 'The Midnight Library',
|
|
'slogan': 'Between life and death, every choice matters',
|
|
'summary_title': 'Matt Haig\'s Philosophical Fiction',
|
|
'summary': 'A woman gets to live out different versions of her life',
|
|
'description': 'Between life and death, Nora Seed finds herself in a library where she can try out different lives she might have lived.',
|
|
'publisher': 'Canongate Books',
|
|
'year_of_publication': '2020',
|
|
'author': 'Matt Haig',
|
|
'isbn': '978-0525559474',
|
|
'numnber_of_volume': '1',
|
|
'main_themes': ['life choices', 'regret', 'possibility', 'self-discovery'],
|
|
'notable_works': ['Philosophical Fiction', 'Contemporary'],
|
|
'pages_count': '288',
|
|
'file_type': 'pdf',
|
|
},
|
|
{
|
|
'title': 'Where the Crawdads Sing',
|
|
'slogan': 'A mystery wrapped in a coming-of-age story',
|
|
'summary_title': 'Delia Owens\' Natural Mystery',
|
|
'summary': 'A young woman raised by the marsh becomes a suspect in a murder',
|
|
'description': 'Kya Clark, the "Marsh Girl," becomes a suspect in a murder while living in isolation in the North Carolina marshes.',
|
|
'publisher': 'G.P. Putnam\'s Sons',
|
|
'year_of_publication': '2018',
|
|
'author': 'Delia Owens',
|
|
'isbn': '978-0735219090',
|
|
'numnber_of_volume': '1',
|
|
'main_themes': ['nature', 'isolation', 'mystery', 'coming-of-age'],
|
|
'notable_works': ['Literary Fiction', 'Mystery'],
|
|
'pages_count': '384',
|
|
'file_type': 'pdf',
|
|
},
|
|
{
|
|
'title': 'The Seven Husbands of Evelyn Hugo',
|
|
'slogan': 'A reclusive Hollywood icon tells her story',
|
|
'summary_title': 'Taylor Jenkins Reid\'s Glamorous Tale',
|
|
'summary': 'A journalist uncovers the secrets of a legendary star',
|
|
'description': 'Reclusive Hollywood icon Evelyn Hugo chooses an unknown journalist to tell her life story and the truth about her seven marriages.',
|
|
'publisher': 'Washington Square Press',
|
|
'year_of_publication': '2017',
|
|
'author': 'Taylor Jenkins Reid',
|
|
'isbn': '978-1501139239',
|
|
'numnber_of_volume': '1',
|
|
'main_themes': ['hollywood', 'secrets', 'identity', 'love'],
|
|
'notable_works': ['Historical Fiction', 'Romance'],
|
|
'pages_count': '400',
|
|
'file_type': 'pdf',
|
|
},
|
|
{
|
|
'title': 'Circe',
|
|
'slogan': 'The story of the witch from The Odyssey',
|
|
'summary_title': 'Madeline Miller\'s Mythological Tale',
|
|
'summary': 'A mortal woman becomes a goddess and discovers her power',
|
|
'description': 'Circe, daughter of the sun god Helios, is banished to an island where she hones her witchcraft and encounters legendary figures.',
|
|
'publisher': 'Little, Brown and Company',
|
|
'year_of_publication': '2018',
|
|
'author': 'Madeline Miller',
|
|
'isbn': '978-0316556347',
|
|
'numnber_of_volume': '1',
|
|
'main_themes': ['mythology', 'power', 'identity', 'transformation'],
|
|
'notable_works': ['Mythological Fiction', 'Feminism'],
|
|
'pages_count': '393',
|
|
'file_type': 'pdf',
|
|
},
|
|
{
|
|
'title': 'Normal People',
|
|
'slogan': 'A story of first love and complicated friendship',
|
|
'summary_title': 'Sally Rooney\'s Contemporary Romance',
|
|
'summary': 'Two young people navigate love and connection',
|
|
'description': 'Marianne and Connell\'s relationship evolves from high school classmates to university students, exploring themes of love, class, and mental health.',
|
|
'publisher': 'Faber & Faber',
|
|
'year_of_publication': '2018',
|
|
'author': 'Sally Rooney',
|
|
'isbn': '978-0571334650',
|
|
'numnber_of_volume': '1',
|
|
'main_themes': ['love', 'friendship', 'class', 'mental health'],
|
|
'notable_works': ['Contemporary Fiction', 'Romance'],
|
|
'pages_count': '304',
|
|
'file_type': 'pdf',
|
|
},
|
|
{
|
|
'title': 'The Vanishing Half',
|
|
'slogan': 'Twin sisters choose different racial identities',
|
|
'summary_title': 'Brit Bennett\'s Family Saga',
|
|
'summary': 'The story of twin sisters who grow up to live in two very different worlds',
|
|
'description': 'The Vignes twin sisters grow up in a small black community but choose to live in two very different racial worlds—one white and one black.',
|
|
'publisher': 'Riverhead Books',
|
|
'year_of_publication': '2020',
|
|
'author': 'Brit Bennett',
|
|
'isbn': '978-0525536963',
|
|
'numnber_of_volume': '1',
|
|
'main_themes': ['race', 'identity', 'family', 'belonging'],
|
|
'notable_works': ['Literary Fiction', 'Social Commentary'],
|
|
'pages_count': '352',
|
|
'file_type': 'pdf',
|
|
},
|
|
]
|
|
|
|
# 5. CREATE NEW DATA
|
|
created_books = []
|
|
|
|
for idx, book_info in enumerate(book_data):
|
|
try:
|
|
slug = slugify(book_info['title'])
|
|
|
|
# Create the book instance (WITHOUT the image/file first)
|
|
book = Book(
|
|
title=book_info['title'],
|
|
slug=slug,
|
|
slogan=book_info['slogan'],
|
|
summary_title=book_info['summary_title'],
|
|
summary=book_info['summary'],
|
|
description=book_info['description'],
|
|
publisher=book_info['publisher'],
|
|
year_of_publication=book_info['year_of_publication'],
|
|
author=book_info['author'],
|
|
isbn=book_info['isbn'],
|
|
numnber_of_volume=book_info['numnber_of_volume'],
|
|
language=language,
|
|
main_themes=book_info['main_themes'],
|
|
notable_works=book_info['notable_works'],
|
|
pages_count=book_info['pages_count'],
|
|
file_type=book_info['file_type'],
|
|
status=True,
|
|
pin=True,
|
|
)
|
|
|
|
# HANDLE THE IMAGE
|
|
img_name = image_filenames[idx % len(image_filenames)]
|
|
img_full_path = os.path.join(seeds_images_path, img_name)
|
|
|
|
if os.path.exists(img_full_path):
|
|
with open(img_full_path, 'rb') as f:
|
|
# Copy to media folder
|
|
book.thumbnail.save(img_name, File(f), save=False)
|
|
else:
|
|
self.stdout.write(self.style.WARNING(f"Image not found: {img_full_path}"))
|
|
|
|
# HANDLE THE PDF (NEW LOGIC)
|
|
# We rename the PDF to match the slug to ensure unique filenames in media
|
|
pdf_filename = f"{slug}.pdf"
|
|
if os.path.exists(pdf_path):
|
|
with open(pdf_path, 'rb') as pdf_f:
|
|
# Copy to media folder
|
|
book.book_file.save(pdf_filename, File(pdf_f), save=False)
|
|
|
|
# Now save the book to DB
|
|
book.save()
|
|
created_books.append(book)
|
|
|
|
self.stdout.write(self.style.SUCCESS(f'✓ Created: {book.title}'))
|
|
|
|
except Exception as e:
|
|
self.stdout.write(self.style.ERROR(f'Error creating book {book_info["title"]}: {e}'))
|
|
|
|
|
|
# 6. RELATIONS
|
|
category_ids = [1, 2, 3, 4, 15, 16, 17, 18, 19, 20]
|
|
collection_ids = [1, 2, 3, 4, 5, 6, 13, 14, 15]
|
|
|
|
self.stdout.write(self.style.SUCCESS('Starting relation assignment...'))
|
|
|
|
# Connect books with categories
|
|
self.stdout.write(self.style.SUCCESS('\nConnecting books to categories...'))
|
|
for idx, book in enumerate(created_books):
|
|
try:
|
|
# Select 2-3 random categories for each book
|
|
num_categories = random.randint(2, 3)
|
|
selected_categories = random.sample(category_ids, num_categories)
|
|
|
|
for category_id in selected_categories:
|
|
try:
|
|
category = Category.objects.get(id=category_id)
|
|
book.categories.add(category)
|
|
except Category.DoesNotExist:
|
|
self.stdout.write(
|
|
self.style.WARNING(f' ⚠ Category with ID {category_id} not found')
|
|
)
|
|
|
|
self.stdout.write(
|
|
self.style.SUCCESS(f' ✓ Connected {book.title} to categories')
|
|
)
|
|
|
|
except Exception as e:
|
|
self.stdout.write(
|
|
self.style.ERROR(f' ✗ Error connecting categories for {book.title}: {str(e)}')
|
|
)
|
|
continue
|
|
|
|
# Connect books with collections
|
|
self.stdout.write(self.style.SUCCESS('\nConnecting books to collections...'))
|
|
for idx, book in enumerate(created_books):
|
|
try:
|
|
# Select 1-2 random collections for each book
|
|
num_collections = random.randint(1, 2)
|
|
selected_collections = random.sample(collection_ids, num_collections)
|
|
|
|
for collection_id in selected_collections:
|
|
try:
|
|
collection = BookCollection.objects.get(id=collection_id)
|
|
book.collections.add(collection)
|
|
except BookCollection.DoesNotExist:
|
|
self.stdout.write(
|
|
self.style.WARNING(f' ⚠ Collection with ID {collection_id} not found')
|
|
)
|
|
|
|
self.stdout.write(
|
|
self.style.SUCCESS(f' ✓ Connected {book.title} to collections')
|
|
)
|
|
|
|
except Exception as e:
|
|
self.stdout.write(
|
|
self.style.ERROR(f' ✗ Error connecting collections for {book.title}: {str(e)}')
|
|
)
|
|
continue
|
|
|
|
# Summary
|
|
self.stdout.write(self.style.SUCCESS('\n' + '='*50))
|
|
self.stdout.write(
|
|
self.style.SUCCESS(f'Successfully created {len(created_books)} books!')
|
|
)
|
|
self.stdout.write(self.style.SUCCESS('='*50))
|