本文将详细介绍如何使用 Django 和 Django REST Framework (DRF) 为安卓应用构建稳定、安全、高效的 RESTful API 接口。
第一阶段:项目基础设置
1.1 安装必要的包
pip install django djangorestframework django-cors-headers djangorestframework-simplejwt pillow
1.2 创建Django项目和应用
django-admin startproject backend
cd backend
python manage.py startapp api
1.3 配置 settings.py
# settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# 第三方应用
'rest_framework',
'rest_framework_simplejwt',
'corsheaders',
# 自定义应用
'api',
]
# DRF 配置
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_simplejwt.authentication.JWTAuthentication',
),
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated', # 默认需要认证
),
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 20
}
# JWT 配置
from datetime import timedelta
SIMPLE_JWT = {
'ACCESS_TOKEN_LIFETIME': timedelta(days=1),
'REFRESH_TOKEN_LIFETIME': timedelta(days=7),
}
# CORS 配置(允许安卓应用访问)
CORS_ALLOWED_ORIGINS = [
"http://localhost:8080", # 开发时安卓模拟器
"http://192.168.1.100:8080", # 本地网络地址
"https://yourdomain.com", # 生产域名
]
CORS_ALLOW_CREDENTIALS = True
# 允许所有域名访问(开发阶段,生产环境应限制)
# CORS_ALLOW_ALL_ORIGINS = True
MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware', # 尽量放在最前
'django.middleware.security.SecurityMiddleware',
# ... 其他中间件
]
第二阶段:数据模型设计
2.1 定义核心模型(api/models.py)
from django.db import models
from django.contrib.auth.models import User
class Category(models.Model):
name = models.CharField(max_length=100)
description = models.TextField(blank=True)
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.name
class Product(models.Model):
name = models.CharField(max_length=200)
description = models.TextField()
price = models.DecimalField(max_digits=10, decimal_places=2)
category = models.ForeignKey(Category, on_delete=models.CASCADE)
image = models.ImageField(upload_to='products/', null=True, blank=True)
stock = models.IntegerField(default=0)
is_active = models.BooleanField(default=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.name
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
phone = models.CharField(max_length=15, blank=True)
avatar = models.ImageField(upload_to='avatars/', null=True, blank=True)
address = models.TextField(blank=True)
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.user.username
class Order(models.Model):
STATUS_CHOICES = [
('pending', '待处理'),
('processing', '处理中'),
('shipped', '已发货'),
('delivered', '已送达'),
('cancelled', '已取消'),
]
user = models.ForeignKey(User, on_delete=models.CASCADE)
total_amount = models.DecimalField(max_digits=10, decimal_places=2)
status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='pending')
shipping_address = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class OrderItem(models.Model):
order = models.ForeignKey(Order, on_delete=models.CASCADE)
product = models.ForeignKey(Product, on_delete=models.CASCADE)
quantity = models.IntegerField()
price = models.DecimalField(max_digits=10, decimal_places=2)
2.2 执行数据库迁移
python manage.py makemigrations
python manage.py migrate
第三阶段:序列化器创建
3.1 创建序列化器(api/serializers.py)
from rest_framework import serializers
from django.contrib.auth.models import User
from .models import Category, Product, UserProfile, Order, OrderItem
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('id', 'username', 'email', 'first_name', 'last_name')
class UserProfileSerializer(serializers.ModelSerializer):
user = UserSerializer(read_only=True)
class Meta:
model = UserProfile
fields = '__all__'
class CategorySerializer(serializers.ModelSerializer):
class Meta:
model = Category
fields = '__all__'
class ProductSerializer(serializers.ModelSerializer):
category_name = serializers.CharField(source='category.name', read_only=True)
class Meta:
model = Product
fields = ('id', 'name', 'description', 'price', 'category',
'category_name', 'image', 'stock', 'is_active', 'created_at')
class OrderItemSerializer(serializers.ModelSerializer):
product_name = serializers.CharField(source='product.name', read_only=True)
class Meta:
model = OrderItem
fields = ('id', 'product', 'product_name', 'quantity', 'price')
class OrderSerializer(serializers.ModelSerializer):
items = OrderItemSerializer(many=True, read_only=True)
user_info = UserSerializer(source='user', read_only=True)
class Meta:
model = Order
fields = ('id', 'user', 'user_info', 'total_amount', 'status',
'shipping_address', 'items', 'created_at', 'updated_at')
第四阶段:视图和API端点
4.1 创建视图(api/views.py)
from rest_framework import viewsets, status, permissions
from rest_framework.decorators import action
from rest_framework.response import Response
from django.contrib.auth.models import User
from .models import Category, Product, UserProfile, Order, OrderItem
from .serializers import (UserSerializer, UserProfileSerializer,
CategorySerializer, ProductSerializer,
OrderSerializer, OrderItemSerializer)
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
permission_classes = [permissions.IsAdminUser] # 只有管理员可以管理用户
class UserProfileViewSet(viewsets.ModelViewSet):
queryset = UserProfile.objects.all()
serializer_class = UserProfileSerializer
def get_queryset(self):
# 用户只能访问自己的资料
if self.request.user.is_staff:
return UserProfile.objects.all()
return UserProfile.objects.filter(user=self.request.user)
class CategoryViewSet(viewsets.ModelViewSet):
queryset = Category.objects.all()
serializer_class = CategorySerializer
permission_classes = [permissions.IsAuthenticatedOrReadOnly] # 读不需要认证
class ProductViewSet(viewsets.ModelViewSet):
queryset = Product.objects.filter(is_active=True)
serializer_class = ProductSerializer
@action(detail=False, methods=['get'])
def by_category(self, request):
category_id = request.query_params.get('category')
products = Product.objects.filter(category_id=category_id, is_active=True)
serializer = self.get_serializer(products, many=True)
return Response(serializer.data)
class OrderViewSet(viewsets.ModelViewSet):
serializer_class = OrderSerializer
def get_queryset(self):
# 用户只能查看自己的订单,管理员可以查看所有
if self.request.user.is_staff:
return Order.objects.all()
return Order.objects.filter(user=self.request.user)
def perform_create(self, serializer):
# 自动设置当前用户为订单所有者
serializer.save(user=self.request.user)
class AuthViewSet(viewsets.ViewSet):
"""认证相关接口"""
@action(detail=False, methods=['post'], permission_classes=[permissions.AllowAny])
def register(self, request):
# 用户注册逻辑
serializer = UserSerializer(data=request.data)
if serializer.is_valid():
user = User.objects.create_user(
username=request.data['username'],
email=request.data.get('email', ''),
password=request.data['password']
)
# 创建用户资料
UserProfile.objects.create(user=user)
return Response({'message': '用户注册成功'}, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
第五阶段:路由配置
5.1 配置URL路由(api/urls.py)
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from rest_framework_simplejwt.views import TokenObtainPairView, TokenRefreshView
from .views import (UserViewSet, UserProfileViewSet, CategoryViewSet,
ProductViewSet, OrderViewSet, AuthViewSet)
router = DefaultRouter()
router.register(r'users', UserViewSet)
router.register(r'profiles', UserProfileViewSet)
router.register(r'categories', CategoryViewSet)
router.register(r'products', ProductViewSet)
router.register(r'orders', OrderViewSet)
router.register(r'auth', AuthViewSet, basename='auth')
urlpatterns = [
path('', include(router.urls)),
path('token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),
path('token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),
]
5.2 主项目路由配置(backend/urls.py)
from django.contrib import admin
from django.urls import path, include
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include('api.urls')), # API路由
]
# 开发环境提供媒体文件服务
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
第六阶段:安卓端接口调用示例
6.1 登录获取Token
// Kotlin 示例代码
interface ApiService {
@POST("api/token/")
suspend fun login(@Body request: LoginRequest): TokenResponse
@POST("api/auth/register/")
suspend fun register(@Body request: RegisterRequest): Response<MessageResponse>
}
data class LoginRequest(val username: String, val password: String)
data class TokenResponse(val access: String, val refresh: String)
data class RegisterRequest(val username: String, val email: String, val password: String)
data class MessageResponse(val message: String)
6.2 获取商品列表
@GET("api/products/")
suspend fun getProducts(
@Header("Authorization") token: String,
@Query("page") page: Int = 1
): Response<ProductListResponse>
@GET("api/products/by_category/")
suspend fun getProductsByCategory(
@Header("Authorization") token: String,
@Query("category") categoryId: Int
): Response<List<ProductResponse>>
6.3 创建订单
@POST("api/orders/")
suspend fun createOrder(
@Header("Authorization") token: String,
@Body request: CreateOrderRequest
): Response<OrderResponse>
第七阶段:生产环境部署配置
7.1 安全配置(settings.py)
# 生产环境设置
DEBUG = False
# 允许的域名
ALLOWED_HOSTS = ['yourdomain.com', 'api.yourdomain.com']
# CORS 白名单
CORS_ALLOWED_ORIGINS = [
"https://yourapp.android.com",
"https://yourdomain.com",
]
# 数据库配置
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'mydatabase',
'USER': 'myuser',
'PASSWORD': 'mypassword',
'HOST': 'localhost',
'PORT': '5432',
}
}
# 静态文件和媒体文件配置
STATIC_URL = '/static/'
STATIC_ROOT = '/var/www/backend/static/'
MEDIA_URL = '/media/'
MEDIA_ROOT = '/var/www/backend/media/'
7.2 添加限流和缓存
REST_FRAMEWORK = {
# ... 其他配置
'DEFAULT_THROTTLE_CLASSES': [
'rest_framework.throttling.AnonRateThrottle',
'rest_framework.throttling.UserRateThrottle'
],
'DEFAULT_THROTTLE_RATES': {
'anon': '100/day', # 匿名用户100次/天
'user': '1000/day' # 认证用户1000次/天
},
'DEFAULT_CACHE_RESPONSE_TIMEOUT': 300 # 5分钟缓存
}
第八阶段:API文档和测试
8.1 安装DRF Spectacular用于API文档
pip install drf-spectacular
8.2 配置API文档
# settings.py
INSTALLED_APPS = [
# ...
'drf_spectacular',
]
REST_FRAMEWORK = {
# ...
'DEFAULT_SCHEMA_CLASS': 'drf_spectacular.openapi.AutoSchema',
}
SPECTACULAR_SETTINGS = {
'TITLE': '安卓APP API',
'DESCRIPTION': '为安卓应用提供的RESTful API接口',
'VERSION': '1.0.0',
}
8.3 添加文档路由
# urls.py
from drf_spectacular.views import SpectacularAPIView, SpectacularRedocView, SpectacularSwaggerView
urlpatterns = [
# ...
path('api/schema/', SpectacularAPIView.as_view(), name='schema'),
path('api/docs/', SpectacularSwaggerView.as_view(url_name='schema'), name='swagger-ui'),
path('api/redoc/', SpectacularRedocView.as_view(url_name='schema'), name='redoc'),
]
完整的功能特性
✅ 用户系统: 注册、登录、JWT认证、用户资料管理
✅ 商品管理: 分类、商品列表、搜索、详情
✅ 订单系统: 创建订单、订单状态管理、历史订单
✅ 权限控制: 用户权限、管理员权限
✅ 文件上传: 用户头像、商品图片
✅ 分页和过滤: 大数据量分页显示
✅ API文档: 自动生成的交互式文档
✅ 安全机制: CORS、限流、SQL注入防护
✅ 错误处理: 统一的错误响应格式
这个完整的API后端可以为安卓应用提供所有必要的接口服务,具有良好的扩展性和安全性。