Django+MySQL接口开发完全指南

前言

本文将详细介绍如何使用Django结合MySQL数据库开发RESTful API接口。我们将从环境搭建开始,一步步实现一个完整的接口项目。

环境准备

首先需要安装以下组件:

  • Python 3.8+
  • Django 4.2
  • MySQL 8.0
  • mysqlclient
  • djangorestframework

安装命令

bash 复制代码
# 创建虚拟环境
python -m venv venv
source venv/bin/activate  # Windows使用 venv\Scripts\activate

# 安装依赖
pip install django==4.2
pip install mysqlclient
pip install djangorestframework

项目创建与配置

1. 创建项目

bash 复制代码
django-admin startproject myproject
cd myproject
python manage.py startapp api

2. 配置settings.py

python 复制代码
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework',  # 添加rest_framework
    'api',  # 添加api应用
]

# 数据库配置
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'django_demo',
        'USER': 'root',
        'PASSWORD': 'your_password',
        'HOST': '127.0.0.1',
        'PORT': '3306',
    }
}

# REST框架配置
REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
    'PAGE_SIZE': 10,
}

数据库模型设计

1. 创建模型(api/models.py)

python 复制代码
from django.db import models

class Book(models.Model):
    title = models.CharField(max_length=100, verbose_name='书名')
    author = models.CharField(max_length=50, verbose_name='作者')
    price = models.DecimalField(max_digits=5, decimal_places=2, verbose_name='价格')
    publish_date = models.DateField(verbose_name='出版日期')
    created_at = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
    updated_at = models.DateTimeField(auto_now=True, verbose_name='更新时间')

    class Meta:
        db_table = 'books'
        verbose_name = '图书'
        verbose_name_plural = verbose_name
        ordering = ['-created_at']

    def __str__(self):
        return self.title

2. 生成并应用数据库迁移

python 复制代码
python manage.py makemigrations
python manage.py migrate

序列化器开发

1. 创建序列化器(api/serializers.py)

python 复制代码
from rest_framework import serializers
from .models import Book

class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = ['id', 'title', 'author', 'price', 'publish_date', 'created_at', 'updated_at']
        read_only_fields = ['created_at', 'updated_at']

视图开发

1. 创建视图(api/views.py)

python 复制代码
from rest_framework import viewsets, filters
from rest_framework.response import Response
from rest_framework.decorators import action
from django_filters.rest_framework import DjangoFilterBackend
from .models import Book
from .serializers import BookSerializer

class BookViewSet(viewsets.ModelViewSet):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    filter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
    filterset_fields = ['author']
    search_fields = ['title', 'author']
    ordering_fields = ['price', 'publish_date']

    @action(detail=False, methods=['get'])
    def get_book_stats(self, request):
        """获取图书统计信息"""
        total_books = Book.objects.count()
        total_authors = Book.objects.values('author').distinct().count()
        avg_price = Book.objects.aggregate(avg_price=models.Avg('price'))

        return Response({
            'total_books': total_books,
            'total_authors': total_authors,
            'average_price': avg_price['avg_price']
        })

URL配置

1. 配置项目URLs(myproject/urls.py)

python 复制代码
from django.contrib import admin
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from api.views import BookViewSet

router = DefaultRouter()
router.register(r'books', BookViewSet)

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/', include(router.urls)),
]

中间件开发

1. 创建自定义中间件(api/middleware.py)

python 复制代码
import time
from django.utils.deprecation import MiddlewareMixin
import logging

logger = logging.getLogger(__name__)

class RequestLogMiddleware(MiddlewareMixin):
    def process_request(self, request):
        request.start_time = time.time()

    def process_response(self, request, response):
        if hasattr(request, 'start_time'):
            duration = time.time() - request.start_time
            logger.info(f'{request.method} {request.path} - {response.status_code} - {duration:.2f}s')
        return response

2. 在settings.py中注册中间件

python 复制代码
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'api.middleware.RequestLogMiddleware',  # 添加自定义中间件
]

异常处理

1. 创建自定义异常处理(api/exceptions.py)

python 复制代码
from rest_framework.views import exception_handler
from rest_framework.response import Response
from rest_framework import status

def custom_exception_handler(exc, context):
    response = exception_handler(exc, context)

    if response is None:
        return Response({
            'error': str(exc),
            'message': '服务器内部错误'
        }, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

    return response

2. 在settings.py中配置异常处理器

python 复制代码
REST_FRAMEWORK = {
    'EXCEPTION_HANDLER': 'api.exceptions.custom_exception_handler'
}

API接口测试

1. 创建测试用例(api/tests.py)

python 复制代码
from rest_framework.test import APITestCase
from rest_framework import status
from .models import Book
from datetime import date

class BookTests(APITestCase):
    def setUp(self):
        self.book_data = {
            'title': 'Django实战',
            'author': '张三',
            'price': '59.99',
            'publish_date': '2024-01-01'
        }
        self.book = Book.objects.create(**self.book_data)

    def test_create_book(self):
        """测试创建图书"""
        response = self.client.post('/api/books/', self.book_data, format='json')
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)
        self.assertEqual(Book.objects.count(), 2)

    def test_get_book_list(self):
        """测试获取图书列表"""
        response = self.client.get('/api/books/')
        self.assertEqual(response.status_code, status.HTTP_200_OK)
        self.assertEqual(len(response.data['results']), 1)

API接口文档

使用drf-yasg生成Swagger文档:

1. 安装drf-yasg

bash 复制代码
pip install drf-yasg

2. 配置settings.py

python 复制代码
INSTALLED_APPS = [
    ...
    'drf_yasg',
]

3. 配置URLs(myproject/urls.py)

python 复制代码
from django.urls import path, include, re_path
from rest_framework import permissions
from drf_yasg.views import get_schema_view
from drf_yasg import openapi

schema_view = get_schema_view(
   openapi.Info(
      title="图书管理API",
      default_version='v1',
      description="图书管理系统API文档",
      terms_of_service="https://www.yourapp.com/terms/",
      contact=openapi.Contact(email="contact@yourapp.com"),
      license=openapi.License(name="BSD License"),
   ),
   public=True,
   permission_classes=(permissions.AllowAny,),
)

urlpatterns = [
    ...
    re_path(r'^swagger(?P<format>\.json|\.yaml)$', schema_view.without_ui(cache_timeout=0), name='schema-json'),
    path('swagger/', schema_view.with_ui('swagger', cache_timeout=0), name='schema-swagger-ui'),
    path('redoc/', schema_view.with_ui('redoc', cache_timeout=0), name='schema-redoc'),
]

接口使用示例

1. 创建图书

bash 复制代码
curl -X POST http://localhost:8000/api/books/ \
     -H "Content-Type: application/json" \
     -d '{"title":"Django实战","author":"张三","price":"59.99","publish_date":"2024-01-01"}'

2. 获取图书列表

python 复制代码
curl http://localhost:8000/api/books/

3. 更新图书

bash 复制代码
curl -X PUT http://localhost:8000/api/books/1/ \
     -H "Content-Type: application/json" \
     -d '{"title":"Django实战(第二版)","author":"张三","price":"69.99","publish_date":"2024-01-01"}'

4. 删除图书

bash 复制代码
curl -X DELETE http://localhost:8000/api/books/1/

性能优化建议

  1. 使用数据库索引

    python 复制代码
    class Book(models.Model):
        ...
        class Meta:
            indexes = [
                models.Index(fields=['title']),
                models.Index(fields=['author']),
            ]
  2. 使用缓存

    python 复制代码
    from django.core.cache import cache
    
    class BookViewSet(viewsets.ModelViewSet):
        def list(self, request):
            cache_key = 'book_list'
            cached_data = cache.get(cache_key)
            
            if cached_data is None:
                queryset = self.filter_queryset(self.get_queryset())
                serializer = self.get_serializer(queryset, many=True)
                cached_data = serializer.data
                cache.set(cache_key, cached_data, timeout=300)  # 缓存5分钟
                
            return Response(cached_data)

总结

本文详细介绍了使用Django开发RESTful API的完整流程,包括:

  1. 环境搭建和项目配置
  2. 数据库模型设计
  3. 序列化器开发
  4. 视图和URL配置
  5. 中间件和异常处理
  6. 测试用例编写
  7. API文档生成
  8. 性能优化建议

通过按照本教程的步骤,你可以快速搭建一个功能完善的Django API项目。建议在实际开发中根据具体需求进行适当调整和扩展。

相关推荐
Icomi_1 小时前
【神经网络】0.深度学习基础:解锁深度学习,重塑未来的智能新引擎
c语言·c++·人工智能·python·深度学习·神经网络
蠟筆小新工程師1 小时前
Deepseek可以通过多种方式帮助CAD加速工作
开发语言·python·seepdeek
NoBarLing1 小时前
python将目录下的所欲md文件转化为html和pdf
python·pdf·html
项目題供诗1 小时前
ES语法学习
学习·elasticsearch·django
岱宗夫up2 小时前
【Python】Django 中的算法应用与实现
数据库·python·opencv·django·sqlite
天道有情战天下2 小时前
python flask
开发语言·python·flask
秀儿还能再秀4 小时前
淘宝母婴购物数据可视化分析(基于脱敏公开数据集)
python·数据分析·学习笔记·数据可视化
夏炎正好眠4 小时前
mysql练习
数据库·mysql
计算机老学长4 小时前
基于Python的商品销量的数据分析及推荐系统
开发语言·python·数据分析
千益5 小时前
玩转python:系统设计模式在Python项目中的应用
python·设计模式