Category: Uncategorized

  • ‘formfield_for_foreignkey()’ with Django Permissions: Fine-Grained Control in Admin

    formfield_for_foreignkey()โ€™ with Django## Mastering formfield_for_foreignkey with Django Permissions: Fine-Grained Control in Admin

    Djangoโ€™s admin is famous for giving developers a fully functional interface out of the box. But real-world apps often need fine-grained access control โ€” different users should see different subsets of related objects.

    You may already know about formfield_for_foreignkey, a hook that lets you filter ForeignKey dropdowns in Django Admin. But hereโ€™s where it gets really powerful: combine it with Djangoโ€™s built-in permissions and roles to create a role-aware and secure admin.

    In this article, weโ€™ll explore:

    โœ… Why combine formfield_for_foreignkey with permissions โœ… How to restrict dropdowns using has_perm() โœ… Using groups and roles for finer control โœ… Handling sensitive data with custom rules โœ… Multi-tenant use cases โœ… Best practices


    What is formfield_for_foreignkey?

    Django provides this method inside ModelAdmin classes to customize the queryset for a ForeignKey dropdown. By default, it lists all related objects in the database. But with formfield_for_foreignkey, you can filter, sort, or restrict that list.

    Signature:

    def formfield_for_foreignkey(self, db_field, request, **kwargs):
        # custom logic here
        return super().formfield_for_foreignkey(db_field, request, **kwargs)
    

    Why Combine with Permissions?

    While formfield_for_foreignkey controls what objects appear, Djangoโ€™s permission system controls who can see what. Combining them means:

    • Different roles (staff, manager, superuser) see different dropdown options
    • Sensitive objects can be hidden unless a user has explicit permission
    • Multi-tenant applications prevent cross-tenant data leaks

    Example 1: Restrict by Permission

    Suppose you have Author and Book models. Normally, all authors would appear in the dropdown. But maybe only staff with the app.view_all_authors permission should see everyone. Others should see only their own.

    from django.contrib import admin
    from .models import Author, Book
    
    @admin.register(Book)
    class BookAdmin(admin.ModelAdmin):
        def formfield_for_foreignkey(self, db_field, request, **kwargs):
            if db_field.name == "author":
                if request.user.has_perm("app.view_all_authors"):
                    kwargs["queryset"] = Author.objects.all()
                else:
                    kwargs["queryset"] = Author.objects.filter(created_by=request.user)
            return super().formfield_for_foreignkey(db_field, request, **kwargs)
    

    โœ… Superusers or staff with the permission see all authors. โœ… Other users see only the authors they created.


    Example 2: Role-Based Dropdown Filtering

    If youโ€™re using Django groups or a role field on your User model, you can scope choices based on role.

    def formfield_for_foreignkey(self, db_field, request, **kwargs):
        if db_field.name == "author":
            if request.user.groups.filter(name="Managers").exists():
                # Managers see all active authors
                kwargs["queryset"] = Author.objects.filter(is_active=True)
            else:
                # Regular staff only see their own active authors
                kwargs["queryset"] = Author.objects.filter(
                    created_by=request.user, is_active=True
                )
        return super().formfield_for_foreignkey(db_field, request, **kwargs)
    

    โœ… Managers have broader visibility. โœ… Staff stay scoped to their own data.


    Example 3: Handling Sensitive Data

    Sometimes you want to hide sensitive objects unless the user has explicit permission.

    def formfield_for_foreignkey(self, db_field, request, **kwargs):
        if db_field.name == "project":
            qs = Project.objects.filter(is_active=True)
    
            if not request.user.has_perm("app.can_assign_sensitive_projects"):
                qs = qs.exclude(is_sensitive=True)
    
            kwargs["queryset"] = qs
        return super().formfield_for_foreignkey(db_field, request, **kwargs)
    

    โœ… Sensitive projects donโ€™t even appear in the dropdown unless allowed.


    Example 4: Multi-Tenant Use Case

    In SaaS apps with multiple tenants, you can combine tenant ownership with permissions.

    def formfield_for_foreignkey(self, db_field, request, **kwargs):
        if db_field.name == "customer":
            qs = Customer.objects.filter(tenant=request.user.tenant)
    
            if not request.user.has_perm("app.view_inactive_customers"):
                qs = qs.filter(is_active=True)
    
            kwargs["queryset"] = qs
        return super().formfield_for_foreignkey(db_field, request, **kwargs)
    

    โœ… Users only see customers from their tenant. โœ… Optional permission controls visibility of inactive customers.


    Best Practices

    • Always call super() at the end to retain Djangoโ€™s defaults.
    • Keep queries efficient โ€” avoid heavy joins inside this method.
    • Test with multiple roles (staff, manager, superuser) to avoid hidden bugs.
    • Stay consistent โ€” if you filter dropdowns here, apply the same logic in get_queryset() for list views.

    Final Thoughts

    formfield_for_foreignkey gives you object-level filtering power, while Djangoโ€™s permission system gives you user-level control. Together, they create an admin thatโ€™s secure, role-aware, and tenant-safe.

    Whether youโ€™re managing sensitive data, building a SaaS app, or just keeping the admin clean for staff, mastering this combination will make your Django admin much more robust.


    ๐Ÿ‘‰ With these examples, you can now:

    • Use permissions to decide who sees what in dropdowns.
    • Implement role-based logic with groups.
    • Keep your admin secure in multi-tenant and sensitive-data scenarios.
  • How to Restrict ForeignKey Choices in Django Admin

    Introduction

    If youโ€™ve ever built an application with Django Admin, youโ€™ve probably used dropdowns for related models. These dropdowns appear whenever you have a ForeignKey field.

    But hereโ€™s the problem: By default, Django Admin will show all related objects in that dropdown.

    • What if you only want to show the objects created by the logged-in user?
    • Or maybe you want staff users to only see certain options?
    • Or perhaps you need to filter choices based on business logic (like only โ€œactiveโ€ records)?

    If you landed here by searching things like:

    • โ€œDjango admin limit dropdown choicesโ€
    • โ€œHow to restrict ForeignKey options per user in Djangoโ€
    • โ€œDjango admin filter related objects dynamicallyโ€
    • โ€œRestrict choices in Django admin formโ€
    • โ€œHow to show limited foreign key options in Djangoโ€

    ๐Ÿ‘‰ Then this article is exactly for you.

    The solution lies in a powerful Django Admin method: formfield_for_foreignkey(self, db_field, request, **kwargs)

    In this article, weโ€™ll explore:

    • Why Django shows all ForeignKey objects by default
    • How to filter dropdown choices in the admin
    • Step-by-step examples with code
    • Alternative approaches (querysets, limit_choices_to)
    • Best practices for performance & maintainability
    • Common pitfalls & FAQs

    By the end, youโ€™ll know exactly how to control your admin dropdowns like a pro.


    Why Does Django Show All ForeignKey Choices by Default?

    When Django sees a ForeignKey in your model, it automatically renders a dropdown in the Admin. For example:

    from django.db import models
    
    class Author(models.Model):
        name = models.CharField(max_length=100)
    
    class Book(models.Model):
        title = models.CharField(max_length=200)
        author = models.ForeignKey(Author, on_delete=models.CASCADE)
    

    In the Book Admin form, Django will render a dropdown for author.

    But by default:

    • It will show all authors from the database.
    • Even if you only want to allow some of them.

    Thatโ€™s fine for small projects, but in real-world apps, you often need restrictions.


    When Do You Need to Restrict ForeignKey Choices?

    Here are some common use cases where you might want to filter ForeignKey dropdowns in Django Admin:

    1. User-specific data

      • Example: Only show Projects created by the logged-in user.
      • Useful in multi-tenant apps.
    2. Role-based filtering

      • Example: Staff can only assign orders to employees in their department.
    3. Status-based filtering

      • Example: Only show โ€œactiveโ€ categories, not archived ones.
    4. Security restrictions

      • Example: Prevent staff users from accessing other usersโ€™ data.
    5. Performance reasons

      • If you have thousands of related objects, filtering avoids slow dropdowns.

    The Django Way: Using formfield_for_foreignkey

    Django gives us a built-in method for this exact problem: formfield_for_foreignkey(self, db_field, request, **kwargs)

    This method is part of the ModelAdmin class and runs whenever Django builds a form field for a ForeignKey.

    Method Signature

    def formfield_for_foreignkey(self, db_field, request, **kwargs):
        # your logic here
        return super().formfield_for_foreignkey(db_field, request, **kwargs)
    
    • db_field โ†’ the field object (so you can check if itโ€™s the field you want to customize).
    • request โ†’ the current HTTP request (so you can check the logged-in user).
    • kwargs โ†’ extra options passed to the form field.

    Example 1: Restrict Choices to Logged-in User

    Letโ€™s say each Book belongs to an Author, and you want a user to only select themselves as the author.

    from django.contrib import admin
    from .models import Book, Author
    
    class BookAdmin(admin.ModelAdmin):
        def formfield_for_foreignkey(self, db_field, request, **kwargs):
            if db_field.name == "author":
                kwargs["queryset"] = Author.objects.filter(user=request.user)
            return super().formfield_for_foreignkey(db_field, request, **kwargs)
    
    admin.site.register(Book, BookAdmin)
    

    โœ” Now, the dropdown for author will only show authors tied to the logged-in user.


    Example 2: Restrict Choices Based on User Role

    Letโ€™s say staff users should only see authors in their department.

    class BookAdmin(admin.ModelAdmin):
        def formfield_for_foreignkey(self, db_field, request, **kwargs):
            if db_field.name == "author" and not request.user.is_superuser:
                kwargs["queryset"] = Author.objects.filter(department=request.user.department)
            return super().formfield_for_foreignkey(db_field, request, **kwargs)
    

    โœ” Superusers see all authors, staff see filtered ones.


    Example 3: Show Only Active Records

    class BookAdmin(admin.ModelAdmin):
        def formfield_for_foreignkey(self, db_field, request, **kwargs):
            if db_field.name == "author":
                kwargs["queryset"] = Author.objects.filter(is_active=True)
            return super().formfield_for_foreignkey(db_field, request, **kwargs)
    

    โœ” Only active authors appear in the dropdown.


    Alternative Approaches

    Sometimes you donโ€™t need formfield_for_foreignkey. Here are other options:

    1. Using limit_choices_to in the Model

    class Book(models.Model):
        author = models.ForeignKey(
            Author, 
            on_delete=models.CASCADE,
            limit_choices_to={'is_active': True}
        )
    

    โš ๏ธ Downside: This is static โ€” you canโ€™t use the logged-in user or request context.


    2. Overriding the Form Class

    You can also customize choices in the form itself:

    from django import forms
    from .models import Book, Author
    
    class BookForm(forms.ModelForm):
        class Meta:
            model = Book
            fields = "__all__"
    
        def __init__(self, *args, **kwargs):
            user = kwargs.pop('request').user
            super().__init__(*args, **kwargs)
            self.fields['author'].queryset = Author.objects.filter(user=user)
    

    Then plug the form into your admin:

    class BookAdmin(admin.ModelAdmin):
        form = BookForm
    

    Best Practices

    • โœ… Use formfield_for_foreignkey if you need request-aware filtering.
    • โœ… Use limit_choices_to for static filters.
    • โœ… Cache querysets if you expect heavy load.
    • โœ… Always allow superusers full access.

    Common Pitfalls

    1. Forgetting super() Always call the parent method, otherwise you may break Djangoโ€™s defaults.

    2. Filtering too aggressively If you filter incorrectly, you might prevent staff from editing old data.

    3. Performance issues Large querysets in dropdowns can slow down admin forms โ€” add filters wisely.


    FAQs

    โ“ Can I restrict ForeignKey dropdowns outside the admin?

    Yes โ€” in custom forms, override the __init__ method and filter querysets.

    โ“ Can I hide the dropdown completely?

    Yes โ€” you can set readonly_fields or replace the field with a custom widget.

    โ“ What if I want autocomplete instead of dropdown?

    Use autocomplete_fields in your ModelAdmin. It works well with large datasets.


    Conclusion

    Restricting ForeignKey choices in Django Admin is a common real-world need. And Django makes it easy with the formfield_for_foreignkey method.

    So whether you searched for:

    • โ€œHow to filter related objects in Django admin formโ€
    • โ€œDjango admin restrict choices dynamically per userโ€
    • โ€œLimit ForeignKey dropdown in Djangoโ€

    ๐Ÿ‘‰ This guide gives you the complete solution.

    By overriding formfield_for_foreignkey, you can:

    • Filter dropdowns per user
    • Apply role-based restrictions
    • Improve performance
    • Keep your admin secure
  • ‘formfield_for_foreignkey’ in Django Admin

    Mastering formfield_for_foreignkey in Django Admin: A Complete Guide

    Djangoโ€™s admin is one of its most powerful features. Out of the box, it gives you forms to create, edit, and manage your models. But sometimes, the default dropdowns for ForeignKey fields are too permissive โ€” they show all related objects in the database.

    What if you want to restrict the choices a user can see, based on who is logged in, or some business logic?

    Thatโ€™s where formfield_for_foreignkey comes in.

    In this article, weโ€™ll dive into:

    • โœ… What is formfield_for_foreignkey?
    • โœ… How Django handles ForeignKey fields by default
    • โœ… Real-world examples of overriding formfield_for_foreignkey
    • โœ… When and why you should use it
    • โœ… Best practices

    ๐Ÿ”Ž What is formfield_for_foreignkey in Django Admin?

    In Django Admin, the method formfield_for_foreignkey(self, db_field, request, **kwargs) is a hook method that lets you customize the queryset for ForeignKey dropdown fields in the admin form.

    By default, Django will show all objects of the related model. With this method, you can filter, sort, or limit the available options.

    Method signature:

    def formfield_for_foreignkey(self, db_field, request, **kwargs):
        # custom logic
        return super().formfield_for_foreignkey(db_field, request, **kwargs)
    

    ๐Ÿ›  How Django Handles ForeignKey by Default

    Imagine we have two models:

    class Author(models.Model):
        name = models.CharField(max_length=100)
    
    class Book(models.Model):
        title = models.CharField(max_length=200)
        author = models.ForeignKey(Author, on_delete=models.CASCADE)
    
    • In the Django Admin, when creating a Book, the author dropdown will list all authors in the database.
    • This is the default behavior.

    But what if you only want staff users to see authors they created? Thatโ€™s where you override formfield_for_foreignkey.


    ๐Ÿš€ Example 1: Filter ForeignKey Choices by Logged-in User

    from django.contrib import admin
    from .models import Book, Author
    
    @admin.register(Book)
    class BookAdmin(admin.ModelAdmin):
        
        def formfield_for_foreignkey(self, db_field, request, **kwargs):
            if db_field.name == "author":
                # Only show authors created by the logged-in user
                kwargs["queryset"] = Author.objects.filter(created_by=request.user)
            return super().formfield_for_foreignkey(db_field, request, **kwargs)
    

    โœ… Now, when a staff user opens the Book form, the author dropdown only lists the authors they created. Superusers will still see everything.


    ๐Ÿš€ Example 2: Show Only Active Related Objects

    Sometimes you want to show only active records.

    def formfield_for_foreignkey(self, db_field, request, **kwargs):
        if db_field.name == "author":
            kwargs["queryset"] = Author.objects.filter(is_active=True)
        return super().formfield_for_foreignkey(db_field, request, **kwargs)
    

    โœ… Now, inactive authors wonโ€™t appear in the dropdown.


    ๐Ÿš€ Example 3: Sort the Dropdown Options

    You can also order the queryset to make the dropdown more user-friendly:

    def formfield_for_foreignkey(self, db_field, request, **kwargs):
        if db_field.name == "author":
            kwargs["queryset"] = Author.objects.all().order_by("name")
        return super().formfield_for_foreignkey(db_field, request, **kwargs)
    

    ๐Ÿ”‘ When Should You Use formfield_for_foreignkey?

    You should override this method when:

    • You want to restrict foreign key options based on the logged-in user.
    • You need to hide inactive or irrelevant related objects.
    • You want to improve usability by sorting or limiting dropdown choices.
    • You are working in a multi-tenant application where users should not see each otherโ€™s data.

    โšก Best Practices

    • Always call super() at the end so Django can apply its defaults.
    • Be careful with queries โ€” donโ€™t run expensive queries inside this method.
    • Test both staff and superuser accounts to ensure permissions work as expected.
    • Keep the logic simple โ€” if the filtering is very complex, consider using custom forms instead.

    ๐ŸŽฏ Final Thoughts

    The formfield_for_foreignkey method is one of the most useful hooks in Django Admin. It gives you control over what appears in your ForeignKey dropdowns, making your admin interface safer, more user-friendly, and tenant-aware.

    Whether youโ€™re building a small project or a large SaaS app, mastering this hook will save you a lot of time and prevent accidental data leaks.


    โœ… With this article, you can now:

    • Explain what formfield_for_foreignkey is.
    • Customize dropdowns for different use cases.
    • Improve your Django admin forms for better usability and security.
  • Demystifying db_field in Django Admin

    When working with Django Admin, youโ€™ll often need to customize how fields appear in your forms. Django provides hooks such as formfield_for_foreignkey, formfield_for_choice_field, and formfield_for_dbfield โ€” all of which receive an argument called db_field.

    If youโ€™ve ever wondered what exactly db_field is and how you can use it, this article is for you.


    What is db_field?

    In short, db_field is the model field object being processed when Django builds the admin form.

    When you define a model:

    from django.db import models
    
    class Author(models.Model):
        name = models.CharField(max_length=100)
    
    class Book(models.Model):
        title = models.CharField(max_length=200)
        author = models.ForeignKey(Author, on_delete=models.CASCADE)
    

    Django Admin inspects each field (title, author, etc.) when rendering the form. At that point, it passes the actual field instance (a CharField or ForeignKey) to your override methods as db_field.

    So:

    • For Book.title โ†’ db_field will be a CharField instance.
    • For Book.author โ†’ db_field will be a ForeignKey instance.

    Where is db_field Used?

    The db_field argument appears in several admin customization methods:

    1. formfield_for_foreignkey(self, db_field, request, **kwargs) โ†’ Lets you change how ForeignKey fields are displayed.

    2. formfield_for_choice_field(self, db_field, request, **kwargs) โ†’ Lets you modify dropdowns created from choices.

    3. formfield_for_dbfield(self, db_field, request, **kwargs) โ†’ A generic hook for any field type.


    Example 1 โ€” Filtering a ForeignKey

    Imagine you want to limit which authors appear in the dropdown when creating a book.

    from django.contrib import admin
    
    class BookAdmin(admin.ModelAdmin):
        def formfield_for_foreignkey(self, db_field, request, **kwargs):
            # Only customize the "author" field
            if db_field.name == "author":
                kwargs["queryset"] = Author.objects.filter(name__startswith="A")
            return super().formfield_for_foreignkey(db_field, request, **kwargs)
    

    ๐Ÿ”Ž Whatโ€™s happening?

    • Django passes the Book.author field as db_field.
    • We check db_field.name == "author".
    • Then we override its queryset to only show authors whose names start with โ€œAโ€.

    Example 2 โ€” Customizing Choices

    Suppose you have a field with predefined choices:

    class Book(models.Model):
        GENRE_CHOICES = [
            ("fiction", "Fiction"),
            ("nonfiction", "Non-Fiction"),
            ("poetry", "Poetry"),
        ]
        title = models.CharField(max_length=200)
        genre = models.CharField(max_length=20, choices=GENRE_CHOICES)
    

    You can alter how these choices appear in admin:

    class BookAdmin(admin.ModelAdmin):
        def formfield_for_choice_field(self, db_field, request, **kwargs):
            if db_field.name == "genre":
                # Reorder or filter choices
                kwargs["choices"] = [
                    ("fiction", "Fiction"),
                    ("poetry", "Poetry"),
                ]
            return super().formfield_for_choice_field(db_field, request, **kwargs)
    

    Example 3 โ€” Catch-All with formfield_for_dbfield

    If you want to apply a rule to all fields, use formfield_for_dbfield:

    class BookAdmin(admin.ModelAdmin):
        def formfield_for_dbfield(self, db_field, request, **kwargs):
            # Example: add placeholder text to all CharFields
            if isinstance(db_field, models.CharField):
                kwargs["widget"].attrs["placeholder"] = f"Enter {db_field.verbose_name}"
            return super().formfield_for_dbfield(db_field, request, **kwargs)
    

    Here, every CharField in the model gets a placeholder in its admin input box.


    Why is db_field Useful?

    • ๐ŸŽฏ Granular Control โ€” target individual fields like author or genre.
    • ๐Ÿ‘ฅ User-Specific Filtering โ€” restrict dropdowns per user role.
    • ๐Ÿ›  Custom Widgets โ€” attach custom widgets or attributes.
    • ๐Ÿงน Centralized Logic โ€” all customization stays inside ModelAdmin.

    Key Takeaways

    • db_field is the actual field object from your model.

    • Django sends it to hooks so you can inspect the field and modify its admin form behavior.

    • Use:

      • formfield_for_foreignkey โ†’ control ForeignKey dropdowns.
      • formfield_for_choice_field โ†’ control choices.
      • formfield_for_dbfield โ†’ catch-all for any field type.

    โœ… By leveraging db_field, you can transform the Django Admin from a basic CRUD tool into a finely tuned interface that enforces business rules and improves usability.

  • What is threading in Python?

    ๐Ÿ”น What is threading in Python?

    • Threading means running multiple threads of execution within the same process.
    • A thread is the smallest unit of a program that can run independently.
    • In Python, threads are often used for tasks like:
    • Handling multiple user requests in a web server.
    • Running background tasks (like sending emails, logging, or processing data).
    • Improving responsiveness (so the program doesnโ€™t โ€œfreezeโ€ while waiting for something).

    ๐Ÿ‘‰ Example:

    import threading
    import time
    
    def worker(name):
        print(f"{name} started")
        time.sleep(2)
        print(f"{name} finished")
    
    # Create 2 threads
    t1 = threading.Thread(target=worker, args=("Thread-1",))
    t2 = threading.Thread(target=worker, args=("Thread-2",))
    
    t1.start()
    t2.start()

    This runs two โ€œworkersโ€ at the same time (interleaved).


    ๐Ÿ”น Why use threading in Django?

    • Django (and many web servers like Gunicorn or Uvicorn) may serve multiple users at once.
    • Each request may be handled by a different thread.
    • If you need some data specific to a request/thread (like which website/domain is being used), you can store it in thread-local storage so that it doesnโ€™t get mixed up with another request.

    ๐Ÿ”น What is _thread_local?

    _thread_local = threading.local()
    • threading.local() creates a thread-local storage object.
    • That means each thread can store its own attributes without interfering with other threads.
    • _thread_local is just a variable name (the underscore _ is a Python convention meaning โ€œthis is private, internal useโ€).

    ๐Ÿ‘‰ Example:

    import threading
    
    local_data = threading.local()
    
    def worker(name):
        local_data.value = name
        print(f"In {name}, local_data.value = {local_data.value}")
    
    t1 = threading.Thread(target=worker, args=("Thread-1",))
    t2 = threading.Thread(target=worker, args=("Thread-2",))
    
    t1.start()
    t2.start()

    Each thread has its own local_data.value โ†’ no conflict.


    โœ… Summary in plain words:

    • Threading = running multiple requests at once.
    • threading.local() = keeps request-specific data separate.
    • _thread_local.current_website = acts like a per-request global variable.
    • Underscore _ = naming convention meaning โ€œinternal use onlyโ€.
  • Understanding inspect.stack() in Python with Examples

    ๐Ÿ” Understanding inspect.stack() in Python with Examples

    When you use Pythonโ€™s inspect.stack(), it gives you a list of frames representing the current call stack.
    Each element is a 6-tuple:

    1. frame (frame_record[0]) โ†’ The execution environment (locals, globals).
    2. filename (frame_record[1]) โ†’ The file name where the code lives.
    3. lineno (frame_record[2]) โ†’ The line number being executed.
    4. function (frame_record[3]) โ†’ The function name being executed.
    5. code_context (frame_record[4]) โ†’ A snippet of source code being run.
    6. index (frame_record[5]) โ†’ Which line of the code context is active.

    Letโ€™s break these with 5 different examples each.


    1. Frame (frame_record[0])

    This is the actual frame object: an environment where Python is executing.
    You can use it to see local variables.

    Examples

    import inspect
    
    def foo(x):
        stack = inspect.stack()
        frame = stack[0][0]   # current frame
        print(frame.f_locals) # show local variables
    
    foo(10)

    ๐Ÿ‘‰ Output: {'x': 10, 'stack': [...], 'frame': <frame object ...>}

    Other uses:

    1. See which variables are in scope.
    2. Modify local variables dynamically (advanced).
    3. Access global variables.
    4. Debugging when you donโ€™t know whatโ€™s available.
    5. Introspection tools (like Django debug toolbar).

    2. Filename (frame_record[1])

    This gives you the file name where the function is running.

    Examples

    import inspect
    
    def bar():
        stack = inspect.stack()
        print(stack[0][1])  # filename
    
    bar()

    ๐Ÿ‘‰ Output: /home/user/my_script.py

    Other uses:

    1. Logging errors with file location.
    2. Auto-documentation (e.g., Sphinx-like tools).
    3. Debugging when you forget which file a function lives in.
    4. Security: detect if code is executed from a wrong file.
    5. Cross-file function tracing.

    3. Line Number (frame_record[2])

    This tells you the line number inside the file.

    Examples

    import inspect
    
    def baz():
        stack = inspect.stack()
        print(stack[0][2])  # line number
    
    baz()

    ๐Ÿ‘‰ Output: 7 (or whatever line print is on)

    Other uses:

    1. Show where an error happened.
    2. Trace execution step-by-step.
    3. Build a debugger.
    4. Logging warnings with file + line.
    5. Unit test coverage tools.

    4. Function (frame_record[3])

    This gives you the function name currently executing.

    Examples

    import inspect
    
    def alpha():
        stack = inspect.stack()
        print(stack[0][3])  # function name
    
    alpha()

    ๐Ÿ‘‰ Output: alpha

    Other uses:

    1. Dynamic logging (Entering function alpha).
    2. Profiling which function runs slow.
    3. Security: check only certain functions run.
    4. Frameworks (like Django middleware) detect caller.
    5. Debugging complex recursive functions.

    5. Code Context (frame_record[4])

    This is a list of lines of code currently running.
    Itโ€™s usually 1 line.

    Examples

    import inspect
    
    def beta():
        stack = inspect.stack()
        print(stack[0][4])  # code context
    
    beta()

    ๐Ÿ‘‰ Output: ['print(stack[0][4]) # code context\n']

    Other uses:

    1. Show exact line being run (like traceback).
    2. Pretty error printing.
    3. Static analyzers (linting tools).
    4. Debugger that shows current code.
    5. Learning tools that display executed code.

    6. Index (frame_record[5])

    This is the index of the line in the code_context list.
    Usually itโ€™s 0, but if multiple lines exist, it shows which one is running.

    Examples

    import inspect
    
    def gamma():
        stack = inspect.stack()
        print(stack[0][5])  # index
    
    gamma()

    ๐Ÿ‘‰ Output: 0

    Other uses:

    1. Multi-line expressions debugging.
    2. Syntax highlighting for running line.
    3. Editors showing current cursor position.
    4. Teaching tools for step-by-step code.
    5. Debuggers aligning executed line.

    โœ… Summary

    • frame โ†’ Execution environment (variables).
    • filename โ†’ Which file is running.
    • lineno โ†’ Which line number.
    • function โ†’ Which function name.
    • code_context โ†’ The actual code text.
    • index โ†’ Position inside that code.
  • What is difference between Django vs DRF ( Django REST Framework )

    ๐Ÿ”น 1. Django

    • What it is:
      Django is a full-stack web framework for Python.
      It helps you build websites and web apps (with HTML templates, forms, authentication, ORM, admin panel, etc.).
    • Main focus:
      Django is designed to create server-rendered web pages (like traditional websites).
    • Example use case:
      • Blog website
      • E-commerce site
      • Admin dashboard with HTML pages
    • Typical flow:
      Browser โ†’ URL โ†’ Django view โ†’ HTML template โ†’ Browser displays webpage.

    ๐Ÿ”น 2. Django REST Framework (DRF)

    • What it is:
      DRF is a third-party library built on top of Django.
      Itโ€™s not a separate framework โ€” it extends Django to build REST APIs.
    • Main focus:
      DRF is designed to send and receive data (usually JSON), not HTML.
      It turns your Django models into RESTful API endpoints.
    • Example use case:
      • Mobile app backend (iOS/Android need JSON, not HTML)
      • SPA frontend (React, Vue, Angular) that fetches data via API
      • Exposing APIs to third-party developers
    • Typical flow:
      Mobile App / React Frontend โ†’ API Request โ†’ DRF view โ†’ JSON Response.

    ๐Ÿ”น 3. Key Differences

    FeatureDjangoDRF (Django REST Framework)
    PurposeBuild websites (HTML templates)Build APIs (JSON, XML, etc.)
    Response TypeHTML (via templates)JSON / other API formats
    Viewsviews.py with HttpResponse/render()APIView, ViewSet, GenericViewSet
    SerializationNot needed (works with templates)Required (Serializer converts model โ†’ JSON and back)
    AuthenticationSession-based auth (cookies)Token/JWT/OAuth (API-friendly)
    Front-end IntegrationTightly coupled (Django renders HTML)Decoupled (React, Vue, Flutter, Mobile apps use APIs)

    ๐Ÿ”น 4. Example

    Django View (HTML)

    # views.py
    from django.shortcuts import render
    from .models import Article
    
    def article_list(request):
        articles = Article.objects.all()
        return render(request, "articles.html", {"articles": articles})
    

    This returns an HTML page.


    DRF API View (JSON)

    # views.py
    from rest_framework.response import Response
    from rest_framework.views import APIView
    from .models import Article
    from .serializers import ArticleSerializer
    
    class ArticleListAPI(APIView):
        def get(self, request):
            articles = Article.objects.all()
            serializer = ArticleSerializer(articles, many=True)
            return Response(serializer.data)
    

    This returns JSON like:

    [
      {"id": 1, "title": "Hello World", "content": "First article"},
      {"id": 2, "title": "Another Post", "content": "Second article"}
    ]
    

    ๐Ÿ”น 5. When to use which?

    • Django only โ†’ If youโ€™re building a traditional website where backend renders HTML (like WordPress-style blog, admin dashboards).
    • Django + DRF โ†’ If youโ€™re building a backend for mobile apps, SPAs (React, Vue), or APIs for third-party use.

    โœ… In short:

    • Django โ†’ Web pages
    • DRF โ†’ APIs (JSON)

  • Which architecture does Django follow?

    Django Architecture

    Django follows the MVT architecture (Modelโ€“Viewโ€“Template).
    Itโ€™s very similar to MVC, but with Djangoโ€™s own naming.

    • Model โ†’ Handles database access (ORM).
    • View โ†’ Contains business logic (decides what data to send to the template).
    • Template โ†’ Handles presentation (HTML, CSS, frontend rendering).

    ๐Ÿ“Œ Flow in Django (MVT):

    1. User requests a page โ†’ URL dispatcher routes to a view.
    2. View talks to Model (database).
    3. View passes data to Template.
    4. Template renders HTML page โ†’ sent back to browser.

    ๐Ÿ‘‰ Example:

    • Model = Article (database table)
    • View = article_list function
    • Template = articles.html

    ๐Ÿ”น DRF Architecture

    Django REST Framework extends Django, but shifts the architecture focus.
    Instead of MVT, it aligns more with MVC + REST principles.

    In DRF, the architecture is usually described as Models โ€“ Serializers โ€“ Views:

    • Model โ†’ Same as Django (ORM, database tables).
    • Serializer โ†’ Converts complex data (Models, QuerySets) into JSON (and back).
    • View โ†’ API endpoint (returns JSON instead of HTML).

    ๐Ÿ“Œ Flow in DRF (API call):

    1. Client (mobile app / React frontend) makes HTTP request (e.g. /api/articles/).
    2. DRF View receives the request.
    3. View gets data from Model.
    4. Serializer converts model objects โ†’ JSON.
    5. Response is sent back as JSON.

    ๐Ÿ”น Comparing Django vs DRF Architecture

    AspectDjango (MVT)DRF (API-based)
    ArchitectureMVT (Modelโ€“Viewโ€“Template)MV(S)V (Modelโ€“Viewโ€“Serializer)
    OutputHTML (via Templates)JSON / XML / API response
    Frontend roleDjango Templates handle viewsExternal frontend (React, Vue, Flutter, Mobile apps) consumes JSON
    Extra layerTemplatesSerializers

    ๐Ÿ”น Quick Analogy

    • Django = Chef prepares food (data) and serves it on a plate (HTML Template).
    • DRF = Chef prepares food (data) but packs it in a box (JSON) so you can eat anywhere (React, mobile app, 3rd party).

    โœ… In short:

    • Django = MVT (server-side rendered websites).
    • DRF = Modelโ€“Viewโ€“Serializer (API services with REST architecture).
  • Django ORM vs SQLAlchemy

    Django ORM vs SQLAlchemy in Details

    Both are Object Relational Mappers (ORMs) in Python, but they serve different use cases and philosophies.


    โœ… Django ORM

    • Comes built-in with Django.
    • Opinionated and tightly integrated with Djangoโ€™s ecosystem (models, admin, forms, views).
    • Uses a simpler, declarative style for defining models.
    • Prioritizes developer productivity and โ€œDjango way of doing thingsโ€.

    Example (Django ORM)

    # models.py
    from django.db import models
    
    class Customer(models.Model):
        name = models.CharField(max_length=100)
        is_active = models.BooleanField(default=True)
    
    # Query
    active_customers = Customer.objects.filter(is_active=True)
    

    ๐Ÿ‘‰ Easy to read, quick to build. ๐Ÿ‘‰ Best if you are building a Django app (donโ€™t reinvent the wheel).


    โœ… SQLAlchemy

    • Independent ORM (not tied to any web framework).

    • Used in Flask, FastAPI, Pyramid, or even standalone scripts.

    • Offers two layers:

      1. Core โ†’ Low-level SQL builder.
      2. ORM โ†’ Higher-level object mapping.
    • More flexible and powerful, but requires more setup.

    Example (SQLAlchemy ORM)

    from sqlalchemy import Column, Integer, String, Boolean, create_engine
    from sqlalchemy.ext.declarative import declarative_base
    from sqlalchemy.orm import sessionmaker
    
    Base = declarative_base()
    
    class Customer(Base):
        __tablename__ = "customers"
        id = Column(Integer, primary_key=True)
        name = Column(String(100))
        is_active = Column(Boolean, default=True)
    
    # DB setup
    engine = create_engine("sqlite:///test.db")
    Session = sessionmaker(bind=engine)
    session = Session()
    
    # Query
    active_customers = session.query(Customer).filter(Customer.is_active == True).all()
    

    ๐Ÿ‘‰ More verbose, but extremely flexible (you can drop to raw SQL easily). ๐Ÿ‘‰ Best if you want fine control over queries or use frameworks other than Django.


    ๐Ÿ”ฅ Key Differences

    Feature Django ORM SQLAlchemy
    Integration Built into Django only Framework-agnostic (Flask, FastAPI)
    Ease of Use Easier, less boilerplate More verbose, but powerful
    Flexibility Limited (Django conventions) Very flexible (Core + ORM)
    Learning Curve Easy for beginners Steeper learning curve
    Migrations Built-in with makemigrations Needs Alembic
    Performance Good for typical web apps Optimized for complex queries
    Use Case Quick web apps with Django Complex, non-Django projects, microservices

    ๐Ÿš€ Which one is better?

    ๐Ÿ‘‰ Use Django ORM if

    • You are working on a Django project.
    • You value speed of development over flexibility.
    • You want everything (ORM, admin, migrations, forms) already integrated.

    ๐Ÿ‘‰ Use SQLAlchemy if

    • You are using Flask, FastAPI, or microservices.
    • You need complex queries and DB-specific optimizations.
    • You want fine-grained control over SQL and schema evolution.

    ๐Ÿ”‘ In short:

    • Django ORM = easy, integrated, fast development (but less flexible).
    • SQLAlchemy = powerful, flexible, framework-agnostic (but more boilerplate).