Challenge 3: CRUD in the Django Shell — Possible Solution ==================================================================== $ python manage.py shell >>> from catalog.models import Book # CREATE >>> book = Book.objects.create( ... title="The Left Hand of Darkness", ... description="An envoy visits a wintry planet whose inhabitants have no fixed gender.", ... price=12.99, ... in_stock=True, ... ) >>> book.pk 1 # READ >>> fetched = Book.objects.get(pk=1) >>> fetched.title 'The Left Hand of Darkness' # UPDATE >>> fetched.price = 9.99 >>> fetched.save() >>> Book.objects.get(pk=1).price Decimal('9.99') # DELETE >>> fetched.delete() (1, {'catalog.Book': 1}) >>> Book.objects.filter(pk=1).exists() False WHY THIS WORKS -------------- - Book.objects.create(...) is a shortcut that both builds a new Book instance AND saves it to the database in one call — equivalent to writing `book = Book(...)` followed by `book.save()`, just more concise for the common "create and immediately persist" case. - Book.objects.get(pk=1) is safe here (per this chapter's gotcha) because a primary key lookup is guaranteed to return at most one row — no risk of DoesNotExist or MultipleObjectsReturned as long as that pk exists. - Updating a field on an already-fetched instance and calling .save() is how the ORM handles updates — there's no separate "update" method; you modify the Python object's attributes and persist the whole object back with .save(). Django only sends the changed field(s) as part of the underlying UPDATE statement. - fetched.delete() removes the row from the database and returns a tuple summarizing what was deleted (useful when a delete cascades to related objects, covered properly in the next chapter on relationships) — after this call, the Python object still exists in memory but no longer corresponds to any row. - Book.objects.filter(pk=1).exists() is a cheap way to confirm deletion without needing to catch a DoesNotExist exception from .get() — .exists() runs an efficient existence check in SQL rather than fetching the whole row.