Skip to content

Naming View Files

For Django views, there are several best practices for naming view files. Here's a comprehensive guide:

Django Views File Naming Best Practices

1. Standard Approach: views.py

The simplest approach is to use the default views.py within each app:

myapp/
  ├── __init__.py
  ├── models.py
  ├── views.py
  ├── urls.py
  └── ...

This works well for small to medium-sized apps with relatively few views.

2. Splitting By Functionality

For larger apps, it's often better to split views into multiple files based on functionality. Create a views package:

myapp/
  ├── __init__.py
  ├── models.py
  ├── views/
  │   ├── __init__.py
  │   ├── customer_views.py
  │   ├── product_views.py
  │   ├── order_views.py
  │   └── dashboard_views.py
  ├── urls.py
  └── ...

In the views/__init__.py file, you would typically import and expose the views:

from .customer_views import CustomerListView, CustomerDetailView
from .product_views import ProductListView, ProductDetailView
# etc.

3. Splitting By View Type

Another approach is to organize views by their type:

myapp/
  ├── __init__.py
  ├── models.py
  ├── views/
  │   ├── __init__.py
  │   ├── api.py        # API views/viewsets
  │   ├── forms.py      # Form handling views
  │   ├── pages.py      # Regular page views
  │   └── mixins.py     # View mixins
  ├── urls.py
  └── ...

4. Resource-Oriented Naming

For API-focused applications, especially with Django REST Framework:

myapp/
  ├── __init__.py
  ├── models.py
  ├── views/
  │   ├── __init__.py
  │   ├── users.py      # User-related views/viewsets
  │   ├── products.py   # Product-related views/viewsets
  │   └── orders.py     # Order-related views/viewsets
  ├── urls.py
  └── ...

Naming Conventions For Individual Files

  1. Use lowercase with underscores (snake_case)
  2. Be descriptive but concise
  3. Use plural for resource collections
  4. Include context if necessary (e.g., admin_views.py, public_views.py)
  5. Consider adding a suffix to indicate the type of view (_api.py, _viewsets.py)

Example for an E-commerce Application:

ecommerce/
  ├── products/
  │   ├── views/
  │   │   ├── __init__.py
  │   │   ├── catalog_views.py    # Product listing, filtering, searching
  │   │   ├── detail_views.py     # Product detail pages
  │   │   ├── category_views.py   # Category-related views
  │   │   └── api_views.py        # API endpoints for products
  │   └── ...
  ├── orders/
  │   ├── views/
  │   │   ├── __init__.py
  │   │   ├── checkout_views.py   # Checkout process
  │   │   ├── order_views.py      # Order management
  │   │   └── payment_views.py    # Payment processing
  │   └── ...
  └── ...

Key principles to follow:

  • Organize views in a way that makes logical sense for your application
  • Make it easy for other developers to find the right file
  • Keep related functionality together
  • Split files before they become too large (>300-500 lines is a good threshold)
  • Consider future growth and maintenance

This approach helps maintain a clean, organized codebase that's easy to navigate and maintain as your project grows.

For a product module with both admin (dashboard) views and storefront views, you'll want a clear organizational structure that separates these distinct interfaces while maintaining logical cohesion. Here's how you could structure it:

Code Example

File structure
products /
├── __init__.py
├── models.py
├── admin.py
├── views /
│   ├── __init__.py
│   ├── storefront /
│   │   ├── __init__.py
│   │   ├── product_list.py
│   │   ├── product_detail.py
│   │   ├── category.py
│   │   └── search.py
│   ├── dashboard /
│   │   ├── __init__.py
│   │   ├── product_management.py
│   │   ├── inventory.py
│   │   ├── pricing.py
│   │   └── analytics.py
│   └── mixins.py  # Shared mixins for both storefront and dashboard
├── urls /
│   ├── __init__.py
│   ├── storefront.py
│   └── dashboard.py
└── templates /
├── products /
│   ├── storefront /
│   │   ├── product_list.html
│   │   └── product_detail.html
│   └── dashboard /
│       ├── product_list.html
│       └── product_detail.html
products/views/__init__.py
# Import and expose views for easier imports elsewhere
from .storefront.product_list import ProductListView, FeaturedProductsView
from .storefront.product_detail import ProductDetailView
from .storefront.category import CategoryView
from .storefront.search import ProductSearchView

from .dashboard.product_management import (
    DashboardProductListView,
    DashboardProductCreateView,
    DashboardProductUpdateView,
    DashboardProductDeleteView,
)
from .dashboard.inventory import InventoryManagementView
from .dashboard.pricing import PricingManagementView
from .dashboard.analytics import ProductAnalyticsView
products/views/storefront/product_list.py
from django.views.generic import ListView
from products.models import Product


class ProductListView(ListView):
    model = Product
    template_name = 'products/storefront/product_list.html'
    context_object_name = 'products'

    def get_queryset(self):
        # Only show active products to customers
        return Product.objects.filter(is_active=True)
products/views/dashboard/product_management.py
from django.views.generic import ListView, CreateView, UpdateView, DeleteView
from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin
from products.models import Product


class DashboardProductListView(LoginRequiredMixin, PermissionRequiredMixin, ListView):
    model = Product
    template_name = 'products/dashboard/product_list.html'
    context_object_name = 'products'
    permission_required = 'products.view_product'

    def get_queryset(self):
        # Show all products in admin dashboard, including inactive
        return Product.objects.all()

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['low_stock_count'] = Product.objects.filter(stock__lt=10).count()
        return context
products/urls/storefront.py
from django.urls import path
from products.views import (
    ProductListView,
    ProductDetailView,
    CategoryView,
    ProductSearchView,
)

app_name = 'products-storefront'

urlpatterns = [
    path('', ProductListView.as_view(), name='product-list'),
    path('<slug:slug>/', ProductDetailView.as_view(), name='product-detail'),
    path('category/<slug:category_slug>/', CategoryView.as_view(), name='category'),
    path('search/', ProductSearchView.as_view(), name='search'),
]
products/urls/dashboard.py
from django.urls import path
from products.views import (
    DashboardProductListView,
    DashboardProductCreateView,
    DashboardProductUpdateView,
    DashboardProductDeleteView,
    InventoryManagementView,
    PricingManagementView,
    ProductAnalyticsView,
)

app_name = 'products-dashboard'

urlpatterns = [
    path('', DashboardProductListView.as_view(), name='product-list'),
    path('create/', DashboardProductCreateView.as_view(), name='product-create'),
    path('<int:pk>/edit/', DashboardProductUpdateView.as_view(), name='product-update'),
    path('<int:pk>/delete/', DashboardProductDeleteView.as_view(), name='product-delete'),
    path('inventory/', InventoryManagementView.as_view(), name='inventory'),
    path('pricing/', PricingManagementView.as_view(), name='pricing'),
    path('analytics/', ProductAnalyticsView.as_view(), name='analytics'),
]
project/urls.py (main project URLs file)
from django.urls import path, include

urlpatterns = [
    # Other URL patterns...

    # Storefront URLs
    path('products/', include('products.urls.storefront', namespace='products-storefront')),

    # Dashboard URLs
    path('dashboard/products/', include('products.urls.dashboard', namespace='products-dashboard')),
]

Key Organizational Benefits of This Structure

  1. Clear Separation of Concerns

    • Storefront views and dashboard views are completely separated
    • Each has its own URL patterns, templates, and view logic
    • Permissions and access control can be applied at the appropriate level
  2. Maintainable Directory Structure

    • Follows a logical hierarchy based on interface type
    • Similar views are grouped together
    • Makes it easy to find specific files
  3. Namespaced URLs

    • URLs are organized into separate namespaces (products-storefront, products-dashboard)
    • Avoids URL name collisions
    • Makes template URL references clearer
  4. Template Organization

    • Templates follow the same organizational pattern
    • No risk of template name collisions
    • Enables different styling for dashboard vs. storefront
  5. Code Reusability

    • Common functionality can be extracted to mixins
    • Base classes can be used for shared behavior
    • Models are shared between interfaces

Additional Best Practices

  1. Use appropriate base classes

    • Dashboard views should inherit from admin-specific mixins (LoginRequired, PermissionRequired)
    • Storefront views may focus on performance and caching
  2. Consider separate serializers/forms

    • If using a REST API, consider separate serializers for admin vs public endpoints
    • Different validation rules may apply in each context
  3. Naming conventions

    • Prefix dashboard views with "Dashboard" to avoid confusion
    • Keep naming consistent across the application
  4. Access control

    • Implement appropriate permission checks for dashboard views
    • Use middleware for additional security if needed

This structure scales well as your application grows and makes it clear which views serve which purpose, improving maintainability and developer experience.