Close Menu
    DevStackTipsDevStackTips
    • Home
    • News & Updates
      1. Tech & Work
      2. View All

      Error’d: Pickup Sticklers

      September 27, 2025

      From Prompt To Partner: Designing Your Custom AI Assistant

      September 27, 2025

      Microsoft unveils reimagined Marketplace for cloud solutions, AI apps, and more

      September 27, 2025

      Design Dialects: Breaking the Rules, Not the System

      September 27, 2025

      Building personal apps with open source and AI

      September 12, 2025

      What Can We Actually Do With corner-shape?

      September 12, 2025

      Craft, Clarity, and Care: The Story and Work of Mengchu Yao

      September 12, 2025

      Cailabs secures €57M to accelerate growth and industrial scale-up

      September 12, 2025
    • Development
      1. Algorithms & Data Structures
      2. Artificial Intelligence
      3. Back-End Development
      4. Databases
      5. Front-End Development
      6. Libraries & Frameworks
      7. Machine Learning
      8. Security
      9. Software Engineering
      10. Tools & IDEs
      11. Web Design
      12. Web Development
      13. Web Security
      14. Programming Languages
        • PHP
        • JavaScript
      Featured

      Using phpinfo() to Debug Common and Not-so-Common PHP Errors and Warnings

      September 28, 2025
      Recent

      Using phpinfo() to Debug Common and Not-so-Common PHP Errors and Warnings

      September 28, 2025

      Mastering PHP File Uploads: A Guide to php.ini Settings and Code Examples

      September 28, 2025

      The first browser with JavaScript landed 30 years ago

      September 27, 2025
    • Operating Systems
      1. Windows
      2. Linux
      3. macOS
      Featured
      Recent
    • Learning Resources
      • Books
      • Cheatsheets
      • Tutorials & Guides
    Home»Development»How to Use a Foreign Key in Django

    How to Use a Foreign Key in Django

    April 22, 2025

    When you’re building something in Django – whether it’s a blog, a to-do app, or even something way more complex – at some point, you’ll want to connect different pieces of data.

    That’s where ForeignKey comes in. It helps link one model to another, like tying a comment to a post, or an order to a customer.

    It’s one of those things in Django that can seem confusing at first, but once it clicks, you’ll wonder how you ever built apps without it.

    So let’s break it all down. I’ll walk you through everything from what a ForeignKey is, to how to use it in your Django project.

    Here’s what we’ll cover:

    • Here’s what we’ll cover:

    • What is a Foreign Key in Django?

    • Why Use a ForeignKey Instead of Storing IDs Manually?

    • Real-World Example: Blog Posts and Comments

    • What is on_delete and Why Does It Matter?

    • How to Access Related Objects in Django

    • How to Create Foreign Key Relationships in Django Admin

      • What Happens in the Database?
    • How to Query with ForeignKey

      • Get all comments for a post with id=1:

      • Get all posts that have at least one comment by a specific user:

    • FAQs

      • Can a ForeignKey be optional?

      • Can a ForeignKey point to the same model (self)?

      • Can a model have more than one ForeignKey?

    • Final Thoughts

      • Further Resources

    What is a Foreign Key in Django?

    In the simplest terms, a Foreign Key in Django creates a many-to-one relationship between two models. This means many rows in one table can be related to a single row in another.

    For example:

    • One blog post can have many comments

    • One customer can have many orders

    • One author can write many books

    If you’re coming from a spreadsheet background, think of it like linking two sheets using a shared column. In Django, you do this in your model definitions.

    Why Use a ForeignKey Instead of Storing IDs Manually?

    You might be wondering, “Why not just store the ID of the related object in a plain integer field?”

    Well, you could – but you’d lose a ton of power. Without a ForeignKey:

    • You don’t get automatic validation that the related object exists.

    • You can’t follow relationships easily in queries (for example, post.comments.all() wouldn’t be possible).

    • The Django admin can’t provide dropdowns or inline forms for related data.

    • You lose out on helpful features like on_delete behaviour and related object naming.

    ForeignKey fields automate and enforce these relationships, making your code cleaner, more secure, and easier to maintain.

    Real-World Example: Blog Posts and Comments

    Let’s say you’re building a blog. You’ll probably have a Post model and a Comment model. Each comment needs to be linked to a specific post.

    Here’s how that looks in code:

    <span class="hljs-keyword">from</span> django.db <span class="hljs-keyword">import</span> models
    
    <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Post</span>(<span class="hljs-params">models.Model</span>):</span>
        title = models.CharField(max_length=<span class="hljs-number">200</span>)
        content = models.TextField()
        published_at = models.DateTimeField(auto_now_add=<span class="hljs-literal">True</span>)
    
        <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__str__</span>(<span class="hljs-params">self</span>):</span>
            <span class="hljs-keyword">return</span> self.title
    
    <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Comment</span>(<span class="hljs-params">models.Model</span>):</span>
        post = models.ForeignKey(Post, on_delete=models.CASCADE)
        author = models.CharField(max_length=<span class="hljs-number">100</span>)
        text = models.TextField()
        created_at = models.DateTimeField(auto_now_add=<span class="hljs-literal">True</span>)
    
        <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__str__</span>(<span class="hljs-params">self</span>):</span>
            <span class="hljs-keyword">return</span> <span class="hljs-string">f'Comment by <span class="hljs-subst">{self.author}</span>'</span>
    

    Let me explain each part of that:

    • models.ForeignKey(Post, on_delete=models.CASCADE): This line creates the connection. It means each comment is linked to one post. The on_delete=models.CASCADE part tells Django to delete all related comments if a post is deleted.

    • __str__ methods just make it easier to read things in the admin or shell.

    What is on_delete and Why Does It Matter?

    When you create a ForeignKey in Django, you have to include an on_delete argument. This controls what happens to the child rows (like comments) if the parent row (like a blog post) is deleted.

    Here are the common options:

    • models.CASCADE: Delete the child rows, too (like deleting all comments when a post is deleted).

    • models.PROTECT: Prevent deletion if there are related objects.

    • models.SET_NULL: Set the ForeignKey to NULL instead of deleting.

    • models.SET_DEFAULT: Set a default value.

    • models.DO_NOTHING: Do nothing (not recommended unless you really know what you’re doing).

    I usually go with CASCADE for simple apps, but it’s worth thinking through depending on the situation.

    How to Access Related Objects in Django

    Once you’ve set up the ForeignKey, Django gives you a few nice tools to work with related data.

    For example, let’s say you have a post object:

    post = Post.objects.get(id=<span class="hljs-number">1</span>)
    

    You can get all comments for that post like this:

    comments = post.comment_set.all()
    

    The comment_set is automatically created by Django, and you can customize the name with related_name:

    <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Comment</span>(<span class="hljs-params">models.Model</span>):</span>
        post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name=<span class="hljs-string">'comments'</span>)
    

    Now you can do:

    post.comments.all()
    

    Much cleaner, right?

    How to Create Foreign Key Relationships in Django Admin

    The Django admin handles ForeignKeys well. If you’ve got both Post and Comment models registered in admin.py, you’ll get a dropdown in the comment form to select the post it belongs to.

    You can also make inline forms, so you can add comments while editing a post. Here’s a quick example:

    <span class="hljs-keyword">from</span> django.contrib <span class="hljs-keyword">import</span> admin
    <span class="hljs-keyword">from</span> .models <span class="hljs-keyword">import</span> Post, Comment
    
    <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CommentInline</span>(<span class="hljs-params">admin.TabularInline</span>):</span>
        model = Comment
        extra = <span class="hljs-number">1</span>
    
    <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PostAdmin</span>(<span class="hljs-params">admin.ModelAdmin</span>):</span>
        inlines = [CommentInline]
    
    admin.site.register(Post, PostAdmin)
    admin.site.register(Comment)
    

    Now when you’re editing a post, you can add or edit comments right there on the same page.

    What Happens in the Database?

    Django uses a relational database (like PostgreSQL, MySQL, or SQLite), and ForeignKey creates a column in the database table that holds the ID of the related object.

    If you run python manage.py makemigrations and then python manage.py migrate, Django will create the actual database tables with the proper relationships behind the scenes.

    How to Query with ForeignKey

    You can also filter or search based on ForeignKey relationships:

    Get all comments for a post with id=1:

    Comment.objects.filter(post_id=<span class="hljs-number">1</span>)
    

    Or, using the post object:

    post = Post.objects.get(id=<span class="hljs-number">1</span>)
    comments = Comment.objects.filter(post=post)
    

    Get all posts that have at least one comment by a specific user:

    Post.objects.filter(comments__author=<span class="hljs-string">'John'</span>)
    

    That comments__author part is thanks to the related_name='comments' I added earlier.

    FAQs

    Can a ForeignKey be optional?

    Yes, just add null=True, blank=True like this:

    post = models.ForeignKey(Post, on_delete=models.SET_NULL, null=<span class="hljs-literal">True</span>, blank=<span class="hljs-literal">True</span>)
    

    You might want this if the related object isn’t always required. For example, a Comment might optionally belong to a Post, or a Task might optionally have a related Project. It’s useful when building drafts, soft deletes, or handling legacy data.

    Can a ForeignKey point to the same model (self)?

    Absolutely. That’s called a self-referential ForeignKey, often used for things like threaded comments or categories.

    <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Category</span>(<span class="hljs-params">models.Model</span>):</span>
        name = models.CharField(max_length=<span class="hljs-number">100</span>)
        parent = models.ForeignKey(<span class="hljs-string">'self'</span>, null=<span class="hljs-literal">True</span>, blank=<span class="hljs-literal">True</span>, on_delete=models.SET_NULL)
    

    Can a model have more than one ForeignKey?

    Totally. For example, an Order model could have one ForeignKey to a Customer, and another to a ShippingAddress.

    Final Thoughts

    If you’re building anything in Django that deals with more than one model, understanding ForeignKey is essential. It makes your app more structured, easier to query, and way more powerful.

    At first, it might feel like a lot, but once you build one or two relationships and see it all working in the admin and your views, it clicks.

    And if something’s still unclear, that’s normal. I had to build a few mini-projects before it started to feel natural.

    Further Resources

    • Django Docs on ForeignKey

    • Django Model Field Reference

    • Writing Models in Django

    • Django Admin Docs

    Source: freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More 

    Facebook Twitter Reddit Email Copy Link
    Previous ArticleWhat is Typecasting in Go? Explained with Code Examples
    Next Article How to Use PostgreSQL in Django

    Related Posts

    Development

    Using phpinfo() to Debug Common and Not-so-Common PHP Errors and Warnings

    September 28, 2025
    Development

    Mastering PHP File Uploads: A Guide to php.ini Settings and Code Examples

    September 28, 2025
    Leave A Reply Cancel Reply

    For security, use of Google's reCAPTCHA service is required which is subject to the Google Privacy Policy and Terms of Use.

    Continue Reading

    A Step-by-Step Coding Implementation of an Agent2Agent Framework for Collaborative and Critique-Driven AI Problem Solving with Consensus-Building

    Machine Learning

    MOVEit Transfer Faces Increased Threats as Scanning Surges and CVE Flaws Are Targeted

    Development

    Dev Hackathon: Reusable Creativity on Wix Studio

    Development

    How to turn Open Source into a Job with Nick Taylor [Podcast #181]

    Development

    Highlights

    High-Severity Flaw Exposes ASUS Armoury Crate to Authentication Bypass

    June 17, 2025

    High-Severity Flaw Exposes ASUS Armoury Crate to Authentication Bypass

    Gamers and PC enthusiasts relying on ASUS Armoury Crate to manage their high-performance systems are urged to update immediately following the discovery of a serious security vulnerability. Tracked as …
    Read more

    Published Date:
    Jun 17, 2025 (5 hours, 45 minutes ago)

    Vulnerabilities has been mentioned in this article.

    CVE-2025-3464

    CVE-2025-2492

    CVE-2025-2783

    CVE-2024-54085

    CVE-2024-13062

    CVE-2024-12912

    CVE-2023-5716

    Fileless Remcos RAT Delivered via LNK Files and MSHTA in PowerShell-Based Attacks

    May 16, 2025

    Enhance Geospatial Analysis and GIS Workflows with Amazon Bedrock Capabilities

    August 23, 2025

    CVE-2025-32444 (CVSS 10): Critical RCE Flaw in vLLM’s Mooncake Integration Exposes AI Infrastructure

    May 1, 2025
    © DevStackTips 2025. All rights reserved.
    • Contact
    • Privacy Policy

    Type above and press Enter to search. Press Esc to cancel.