Chapter 12: Django Insert Data

1. The Four Main Ways to Insert Data (Quick Overview Table)

Method Use Case Speed (relative) Signals sent? Validation? Returns PKs? Best for
save() on instance Single object, full control Slow (1 query) Yes Yes Yes Normal CRUD, forms
Model.objects.create() Single object, one-liner Slow (1 query) Yes Yes Yes Quick single inserts
get_or_create() Upsert (get if exists, create if not) Medium Yes Yes Yes Seed data, avoid duplicates
bulk_create() Many objects at once Very fast (1 query) No No Optional Imports, migrations, tests

2. Method 1: The Classic – Create Instance + .save()

Most basic & explicit way.

In python manage.py shell:

Python

Add a related Choice:

Python

When to use: When you need to do extra logic before/after save (e.g. set slug, send email, resize image).

Pro tip: Override .save() in model if you want auto-logic (e.g. auto-slugify).

3. Method 2: One-Liner – objects.create()

Same as above but shorter & safer (handles save automatically).

Python

Advantages:

  • Atomic (create or fail)
  • Returns the saved object with PK

Common mistake: Forgetting to assign ForeignKey → IntegrityError.

4. Method 3: Smart Upsert – get_or_create()

Very useful for seed data, config tables, or avoiding duplicates.

Returns tuple: (object, created) where created is boolean.

Python

Warning: get_or_create() is not atomic in high-concurrency (rare race condition possible). For critical cases use select_for_update() or database constraints.

Best for: Loading countries, tags, initial users, settings.

5. Method 4: The Speed King – bulk_create() (Bulk Insert)

Insert many rows in one SQL query — 10–100× faster than looping .save() or .create().

Perfect for:

  • Importing CSV/JSON data
  • Test fixtures
  • Data migrations
  • Seeding large lists

Example: Create 5 questions at once.

Python

Important options in 6.0:

  • ignore_conflicts=True → skips rows that violate unique constraints (very useful)
  • update_conflicts + update_fields → upsert style (newer Django)
  • return_defaults=True → fills auto fields like created_at if using db_default

Limitations:

  • No pre_save / post_save signals
  • No full model validation
  • No .save() overrides called
  • PKs assigned only if database supports returning IDs (SQLite/PostgreSQL/MySQL yes)

Pro tip: For huge imports (10k+ rows), combine with transaction.atomic() or disable constraint checking temporarily.

6. Quick Bonus: Insert via Admin, Fixtures, or Data Migrations

  • Admin: Already doing this — easiest for manual entry
  • Fixtures (JSON/YAML): python manage.py loaddata initial_data.json
  • Data migrations: Create empty migration → python manage.py makemigrations –empty polls → add RunPython with bulk_create inside

Example data migration snippet:

Python

Recap & Your Next Steps

You now know all major ways to insert data — from single elegant .create() to blazing-fast bulk_create().

Try this right now:

  1. Open shell
  2. Run the bulk_create() example above
  3. Go to /admin/ → see your new questions & choices
  4. Visit /polls/ → see them in your template if wired up

Tell me:

  • “It worked! Show me how to insert from CSV file”
  • “Explain signals & why bulk_create skips them”
  • “How to handle bulk upsert (update if exists)?”
  • “Error: NOT NULL constraint failed — help!”
  • Or next topic: “Django Forms” or “Full voting flow”

You’re moving like a pro now — data is flowing! 🚀 Keep it up, boss! 🇮🇳

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *