django-application

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Django Application

Django 应用程序

Overview

概述

Build comprehensive Django web applications with proper model design, view hierarchies, database operations, user authentication, and admin functionality following Django conventions and best practices.
遵循Django规范和最佳实践,构建包含合理模型设计、视图层级、数据库操作、用户身份验证和管理功能的全面Django Web应用程序。

When to Use

适用场景

  • Creating Django web applications
  • Designing models and database schemas
  • Implementing views and URL routing
  • Building authentication systems
  • Using Django ORM for database operations
  • Creating admin interfaces and dashboards
  • 创建Django Web应用程序
  • 设计模型和数据库架构
  • 实现视图和URL路由
  • 构建身份验证系统
  • 使用Django ORM进行数据库操作
  • 创建管理界面和仪表板

Instructions

操作步骤

1. Django Project Setup

1. Django 项目搭建

bash
django-admin startproject myproject
cd myproject
python manage.py startapp users
python manage.py startapp products
bash
django-admin startproject myproject
cd myproject
python manage.py startapp users
python manage.py startapp products

2. Model Design with ORM

2. 基于ORM的模型设计

python
undefined
python
undefined

users/models.py

users/models.py

from django.contrib.auth.models import AbstractUser from django.db import models from django.contrib.auth import get_user_model
class CustomUser(AbstractUser): ROLE_CHOICES = [ ('admin', 'Administrator'), ('user', 'Regular User'), ] profile_picture = models.ImageField(upload_to='profiles/', null=True) role = models.CharField(max_length=20, choices=ROLE_CHOICES, default='user') created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True)
class Meta:
    ordering = ['-created_at']
    indexes = [
        models.Index(fields=['email']),
        models.Index(fields=['role']),
    ]

def __str__(self):
    return self.email
from django.contrib.auth.models import AbstractUser from django.db import models from django.contrib.auth import get_user_model
class CustomUser(AbstractUser): ROLE_CHOICES = [ ('admin', 'Administrator'), ('user', 'Regular User'), ] profile_picture = models.ImageField(upload_to='profiles/', null=True) role = models.CharField(max_length=20, choices=ROLE_CHOICES, default='user') created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True)
class Meta:
    ordering = ['-created_at']
    indexes = [
        models.Index(fields=['email']),
        models.Index(fields=['role']),
    ]

def __str__(self):
    return self.email

products/models.py

products/models.py

User = get_user_model()
class Product(models.Model): STATUS_CHOICES = [ ('draft', 'Draft'), ('published', 'Published'), ]
title = models.CharField(max_length=200, db_index=True)
slug = models.SlugField(unique=True)
description = models.TextField()
price = models.DecimalField(max_digits=10, decimal_places=2)
stock = models.PositiveIntegerField(default=0)
status = models.CharField(max_length=10, choices=STATUS_CHOICES, default='draft')
owner = models.ForeignKey(User, on_delete=models.CASCADE, related_name='products')
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)

class Meta:
    ordering = ['-created_at']
    unique_together = ['slug', 'owner']

def __str__(self):
    return self.title
class ProductReview(models.Model): product = models.ForeignKey(Product, on_delete=models.CASCADE, related_name='reviews') author = models.ForeignKey(User, on_delete=models.CASCADE) rating = models.IntegerField(choices=[(i, i) for i in range(1, 6)]) comment = models.TextField() created_at = models.DateTimeField(auto_now_add=True)
class Meta:
    unique_together = ['product', 'author']
undefined
User = get_user_model()
class Product(models.Model): STATUS_CHOICES = [ ('draft', 'Draft'), ('published', 'Published'), ]
title = models.CharField(max_length=200, db_index=True)
slug = models.SlugField(unique=True)
description = models.TextField()
price = models.DecimalField(max_digits=10, decimal_places=2)
stock = models.PositiveIntegerField(default=0)
status = models.CharField(max_length=10, choices=STATUS_CHOICES, default='draft')
owner = models.ForeignKey(User, on_delete=models.CASCADE, related_name='products')
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)

class Meta:
    ordering = ['-created_at']
    unique_together = ['slug', 'owner']

def __str__(self):
    return self.title
class ProductReview(models.Model): product = models.ForeignKey(Product, on_delete=models.CASCADE, related_name='reviews') author = models.ForeignKey(User, on_delete=models.CASCADE) rating = models.IntegerField(choices=[(i, i) for i in range(1, 6)]) comment = models.TextField() created_at = models.DateTimeField(auto_now_add=True)
class Meta:
    unique_together = ['product', 'author']
undefined

3. Views with Class-Based and Function-Based Approaches

3. 基于类和函数的视图实现

python
undefined
python
undefined

products/views.py

products/views.py

from django.views import View from django.views.generic import ListView, DetailView, CreateView from django.contrib.auth.mixins import LoginRequiredMixin from django.shortcuts import render, redirect, get_object_or_404 from django.http import JsonResponse from django.db.models import Q, Count, Avg from rest_framework import viewsets, status from rest_framework.response import Response from rest_framework.decorators import action from rest_framework.permissions import IsAuthenticated
from .models import Product, ProductReview from .serializers import ProductSerializer
from django.views import View from django.views.generic import ListView, DetailView, CreateView from django.contrib.auth.mixins import LoginRequiredMixin from django.shortcuts import render, redirect, get_object_or_404 from django.http import JsonResponse from django.db.models import Q, Count, Avg from rest_framework import viewsets, status from rest_framework.response import Response from rest_framework.decorators import action from rest_framework.permissions import IsAuthenticated
from .models import Product, ProductReview from .serializers import ProductSerializer

Class-based view with authentication

带身份验证的类视图

class ProductListView(LoginRequiredMixin, ListView): model = Product template_name = 'products/list.html' context_object_name = 'products' paginate_by = 20
def get_queryset(self):
    queryset = Product.objects.filter(status='published')

    # Search and filter
    search = self.request.GET.get('q')
    if search:
        queryset = queryset.filter(
            Q(title__icontains=search) | Q(description__icontains=search)
        )

    # Price range filter
    min_price = self.request.GET.get('min_price')
    max_price = self.request.GET.get('max_price')
    if min_price:
        queryset = queryset.filter(price__gte=min_price)
    if max_price:
        queryset = queryset.filter(price__lte=max_price)

    return queryset.annotate(
        review_count=Count('reviews'),
        avg_rating=Avg('reviews__rating')
    ).order_by('-created_at')
class ProductListView(LoginRequiredMixin, ListView): model = Product template_name = 'products/list.html' context_object_name = 'products' paginate_by = 20
def get_queryset(self):
    queryset = Product.objects.filter(status='published')

    # 搜索和过滤
    search = self.request.GET.get('q')
    if search:
        queryset = queryset.filter(
            Q(title__icontains=search) | Q(description__icontains=search)
        )

    # 价格范围过滤
    min_price = self.request.GET.get('min_price')
    max_price = self.request.GET.get('max_price')
    if min_price:
        queryset = queryset.filter(price__gte=min_price)
    if max_price:
        queryset = queryset.filter(price__lte=max_price)

    return queryset.annotate(
        review_count=Count('reviews'),
        avg_rating=Avg('reviews__rating')
    ).order_by('-created_at')

REST API ViewSet

REST API 视图集

class ProductViewSet(viewsets.ModelViewSet): permission_classes = [IsAuthenticated] serializer_class = ProductSerializer queryset = Product.objects.all()
def get_queryset(self):
    return Product.objects.filter(owner=self.request.user)

@action(detail=True, methods=['post'])
def add_review(self, request, pk=None):
    product = self.get_object()
    serializer = ProductReviewSerializer(data=request.data)

    if serializer.is_valid():
        serializer.save(product=product, author=request.user)
        return Response(serializer.data, status=status.HTTP_201_CREATED)
    return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

@action(detail=True, methods=['get'])
def reviews(self, request, pk=None):
    product = self.get_object()
    reviews = product.reviews.all()
    serializer = ProductReviewSerializer(reviews, many=True)
    return Response(serializer.data)
undefined
class ProductViewSet(viewsets.ModelViewSet): permission_classes = [IsAuthenticated] serializer_class = ProductSerializer queryset = Product.objects.all()
def get_queryset(self):
    return Product.objects.filter(owner=self.request.user)

@action(detail=True, methods=['post'])
def add_review(self, request, pk=None):
    product = self.get_object()
    serializer = ProductReviewSerializer(data=request.data)

    if serializer.is_valid():
        serializer.save(product=product, author=request.user)
        return Response(serializer.data, status=status.HTTP_201_CREATED)
    return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

@action(detail=True, methods=['get'])
def reviews(self, request, pk=None):
    product = self.get_object()
    reviews = product.reviews.all()
    serializer = ProductReviewSerializer(reviews, many=True)
    return Response(serializer.data)
undefined

4. Authentication and Permissions

4. 身份验证与权限控制

python
undefined
python
undefined

users/views.py

users/views.py

from django.contrib.auth import authenticate, login, logout from django.views.decorators.http import require_http_methods from django.views.decorators.csrf import csrf_protect from rest_framework.authtoken.models import Token from rest_framework.permissions import BasePermission
class IsOwner(BasePermission): def has_object_permission(self, request, view, obj): return obj.owner == request.user
@require_http_methods(['POST']) @csrf_protect def login_view(request): email = request.POST.get('email') password = request.POST.get('password') user = authenticate(request, username=email, password=password)
if user is not None:
    login(request, user)
    token, created = Token.objects.get_or_create(user=user)
    return JsonResponse({
        'success': True,
        'token': token.key,
        'user_id': user.id
    })

return JsonResponse({'error': 'Invalid credentials'}, status=401)
@require_http_methods(['POST']) def logout_view(request): logout(request) return JsonResponse({'success': True})
undefined
from django.contrib.auth import authenticate, login, logout from django.views.decorators.http import require_http_methods from django.views.decorators.csrf import csrf_protect from rest_framework.authtoken.models import Token from rest_framework.permissions import BasePermission
class IsOwner(BasePermission): def has_object_permission(self, request, view, obj): return obj.owner == request.user
@require_http_methods(['POST']) @csrf_protect def login_view(request): email = request.POST.get('email') password = request.POST.get('password') user = authenticate(request, username=email, password=password)
if user is not None:
    login(request, user)
    token, created = Token.objects.get_or_create(user=user)
    return JsonResponse({
        'success': True,
        'token': token.key,
        'user_id': user.id
    })

return JsonResponse({'error': 'Invalid credentials'}, status=401)
@require_http_methods(['POST']) def logout_view(request): logout(request) return JsonResponse({'success': True})
undefined

5. Database Queries and Optimization

5. 数据库查询与优化

python
undefined
python
undefined

products/queries.py

products/queries.py

from django.db.models import Q, Count, Avg, F, Case, When, Value from django.db.models.functions import Coalesce from .models import Product, ProductReview
from django.db.models import Q, Count, Avg, F, Case, When, Value from django.db.models.functions import Coalesce from .models import Product, ProductReview

Optimized queries with select_related and prefetch_related

使用select_related和prefetch_related优化查询

def get_product_details(product_id): return Product.objects.select_related('owner').prefetch_related( 'reviews__author' ).get(id=product_id)
def get_product_details(product_id): return Product.objects.select_related('owner').prefetch_related( 'reviews__author' ).get(id=product_id)

Aggregation queries

聚合查询

def get_top_products(): return Product.objects.annotate( review_count=Count('reviews'), avg_rating=Avg('reviews__rating'), total_reviews=Count('reviews', distinct=True) ).filter(review_count__gt=0).order_by('-avg_rating')[:10]
def get_top_products(): return Product.objects.annotate( review_count=Count('reviews'), avg_rating=Avg('reviews__rating'), total_reviews=Count('reviews', distinct=True) ).filter(review_count__gt=0).order_by('-avg_rating')[:10]

Complex filtering

复杂过滤

def search_products(query, category=None, min_price=None, max_price=None): queryset = Product.objects.filter( Q(title__icontains=query) | Q(description__icontains=query) )
if category:
    queryset = queryset.filter(category=category)
if min_price:
    queryset = queryset.filter(price__gte=min_price)
if max_price:
    queryset = queryset.filter(price__lte=max_price)

return queryset.select_related('owner')
def search_products(query, category=None, min_price=None, max_price=None): queryset = Product.objects.filter( Q(title__icontains=query) | Q(description__icontains=query) )
if category:
    queryset = queryset.filter(category=category)
if min_price:
    queryset = queryset.filter(price__gte=min_price)
if max_price:
    queryset = queryset.filter(price__lte=max_price)

return queryset.select_related('owner')

Bulk operations

批量操作

def bulk_update_stock(updates): products_to_update = [] for product_id, new_stock in updates.items(): product = Product.objects.get(id=product_id) product.stock = new_stock products_to_update.append(product)
Product.objects.bulk_update(products_to_update, ['stock'])
undefined
def bulk_update_stock(updates): products_to_update = [] for product_id, new_stock in updates.items(): product = Product.objects.get(id=product_id) product.stock = new_stock products_to_update.append(product)
Product.objects.bulk_update(products_to_update, ['stock'])
undefined

6. URL Routing

6. URL路由配置

python
undefined
python
undefined

myproject/urls.py

myproject/urls.py

from django.contrib import admin from django.urls import path, include from rest_framework.routers import DefaultRouter from rest_framework.authtoken.views import obtain_auth_token from products.views import ProductViewSet
router = DefaultRouter() router.register(r'products', ProductViewSet)
urlpatterns = [ path('admin/', admin.site.urls), path('api/', include(router.urls)), path('api-token-auth/', obtain_auth_token), ]
undefined
from django.contrib import admin from django.urls import path, include from rest_framework.routers import DefaultRouter from rest_framework.authtoken.views import obtain_auth_token from products.views import ProductViewSet
router = DefaultRouter() router.register(r'products', ProductViewSet)
urlpatterns = [ path('admin/', admin.site.urls), path('api/', include(router.urls)), path('api-token-auth/', obtain_auth_token), ]
undefined

7. Admin Interface Customization

7. 管理界面定制

python
undefined
python
undefined

products/admin.py

products/admin.py

from django.contrib import admin from .models import Product, ProductReview
@admin.register(Product) class ProductAdmin(admin.ModelAdmin): list_display = ['title', 'price', 'stock', 'status', 'owner', 'created_at'] list_filter = ['status', 'created_at', 'owner'] search_fields = ['title', 'description'] readonly_fields = ['created_at', 'updated_at'] fieldsets = ( ('Basic Info', { 'fields': ('title', 'slug', 'owner') }), ('Details', { 'fields': ('description', 'price', 'stock', 'status') }), ('Metadata', { 'fields': ('created_at', 'updated_at'), 'classes': ('collapse',) }), )
def save_model(self, request, obj, form, change):
    if not change:
        obj.owner = request.user
    super().save_model(request, obj, form, change)
@admin.register(ProductReview) class ProductReviewAdmin(admin.ModelAdmin): list_display = ['product', 'author', 'rating', 'created_at'] list_filter = ['rating', 'created_at'] readonly_fields = ['created_at']
undefined
from django.contrib import admin from .models import Product, ProductReview
@admin.register(Product) class ProductAdmin(admin.ModelAdmin): list_display = ['title', 'price', 'stock', 'status', 'owner', 'created_at'] list_filter = ['status', 'created_at', 'owner'] search_fields = ['title', 'description'] readonly_fields = ['created_at', 'updated_at'] fieldsets = ( ('Basic Info', { 'fields': ('title', 'slug', 'owner') }), ('Details', { 'fields': ('description', 'price', 'stock', 'status') }), ('Metadata', { 'fields': ('created_at', 'updated_at'), 'classes': ('collapse',) }), )
def save_model(self, request, obj, form, change):
    if not change:
        obj.owner = request.user
    super().save_model(request, obj, form, change)
@admin.register(ProductReview) class ProductReviewAdmin(admin.ModelAdmin): list_display = ['product', 'author', 'rating', 'created_at'] list_filter = ['rating', 'created_at'] readonly_fields = ['created_at']
undefined

Best Practices

最佳实践

✅ DO

✅ 建议做法

  • Use models for database operations
  • Implement proper indexes on frequently queried fields
  • Use select_related and prefetch_related for query optimization
  • Implement authentication and permissions
  • Use Django Forms for form validation
  • Cache expensive queries
  • Use management commands for batch operations
  • Implement logging for debugging
  • Use middleware for cross-cutting concerns
  • Validate user input
  • 使用模型进行数据库操作
  • 在频繁查询的字段上创建合适的索引
  • 使用select_related和prefetch_related优化查询
  • 实现身份验证和权限控制
  • 使用Django Forms进行表单验证
  • 缓存开销大的查询
  • 使用管理命令执行批量操作
  • 实现日志记录用于调试
  • 使用中间件处理横切关注点
  • 验证用户输入

❌ DON'T

❌ 避免做法

  • Use raw SQL without ORM
  • N+1 query problems without optimization
  • Store secrets in code
  • Trust user input directly
  • Override init in models unnecessarily
  • Make synchronous heavy operations in views
  • Use inheritance models unless necessary
  • Expose stack traces in production
  • 不使用ORM而直接编写原生SQL
  • 不进行优化导致N+1查询问题
  • 在代码中存储敏感信息
  • 直接信任用户输入
  • 不必要地在模型中重写__init__方法
  • 在视图中执行同步的重量级操作
  • 除非必要否则不使用模型继承
  • 在生产环境中暴露堆栈跟踪

Complete Example

完整示例

python
undefined
python
undefined

settings.py

settings.py

INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'rest_framework', 'users', 'products' ]
AUTH_USER_MODEL = 'users.CustomUser'
REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': [ 'rest_framework.authentication.TokenAuthentication', ], 'DEFAULT_PERMISSION_CLASSES': [ 'rest_framework.permissions.IsAuthenticated', ] }
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'rest_framework', 'users', 'products' ]
AUTH_USER_MODEL = 'users.CustomUser'
REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': [ 'rest_framework.authentication.TokenAuthentication', ], 'DEFAULT_PERMISSION_CLASSES': [ 'rest_framework.permissions.IsAuthenticated', ] }

models.py + views.py (see sections above)

models.py + views.py (参考上述章节)

urls.py + admin.py (see sections above)

urls.py + admin.py (参考上述章节)

undefined
undefined