You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Django+Raspberry Pi,如何用AJAX调用Python脚本实现拍照?

实现Django + Raspberry Pi摄像头Web交互方案

Hey there! Let's break down exactly how to build this web interface that triggers your Pi camera to snap photos when you click a button. Since you're new to Django, I'll keep each step straightforward and include all the code snippets you need.

1. 先搞定Django项目基础

First, make sure you have Django installed on your Raspberry Pi (run pip install django if not). Then:

  • 创建Django项目:django-admin startproject pi_camera_project
  • 进入项目目录:cd pi_camera_project
  • 创建一个处理摄像头功能的app:python manage.py startapp camera
  • 把这个app加到项目的settings.py里的INSTALLED_APPS列表:
    INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'camera',  # 添加这一行
    ]
    

2. 编写摄像头控制的Python脚本

在camera app里创建camera_utils.py文件,编写拍照逻辑(需要先安装picamera库:pip install picamera,并且通过raspi-config启用Pi的摄像头模块,重启Pi生效):

from picamera import PiCamera
from datetime import datetime
import os

def take_photo():
    # 设置照片保存目录(先在项目根目录创建media文件夹)
    photo_dir = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'media')
    if not os.path.exists(photo_dir):
        os.makedirs(photo_dir)
    
    # 用时间戳做文件名,避免重复
    photo_name = f"photo_{datetime.now().strftime('%Y%m%d_%H%M%S')}.jpg"
    photo_path = os.path.join(photo_dir, photo_name)
    
    # 初始化摄像头并拍照
    camera = PiCamera()
    camera.start_preview()
    camera.capture(photo_path)
    camera.stop_preview()
    camera.close()
    
    return photo_name  # 返回文件名,供前端显示照片

3. 配置Django后端的视图和路由

编写视图函数

修改camera/views.py,创建处理AJAX请求的视图:

from django.shortcuts import render
from django.http import JsonResponse
from django.views.decorators.http import require_POST
from .camera_utils import take_photo

# 前端页面视图
def index(request):
    return render(request, 'camera/index.html')

# 处理拍照请求的视图(仅允许POST)
@require_POST
def capture_photo(request):
    try:
        photo_filename = take_photo()
        return JsonResponse({'status': 'success', 'photo_url': f'/media/{photo_filename}'})
    except Exception as e:
        return JsonResponse({'status': 'error', 'message': str(e)})

设置URL路由

首先修改项目根目录的pi_camera_project/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('', include('camera.urls')),  # 关联camera app的路由
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)  # 让Django能访问media文件夹的照片

然后在camera app里创建urls.py:

from django.urls import path
from . import views

urlpatterns = [
    path('', views.index, name='index'),  # 前端页面路由
    path('capture/', views.capture_photo, name='capture_photo'),  # AJAX请求路由
]

最后在pi_camera_project/settings.py末尾添加媒体文件配置:

import os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'

4. 编写前端页面(带AJAX按钮)

在camera app里创建templates/camera文件夹,然后创建index.html:

<!DOCTYPE html>
<html>
<head>
    <title>Pi Camera Controller</title>
</head>
<body>
    <h1>Raspberry Pi Camera Web Interface</h1>
    <button id="capture-btn" style="padding: 10px 20px; font-size: 16px;">Take Photo</button>
    <div id="photo-container" style="margin-top: 20px;">
        <!-- 拍摄的照片会显示在这里 -->
    </div>

    <!-- 自动生成CSRF令牌,用于安全的AJAX请求 -->
    <form style="display: none;">
        {% csrf_token %}
    </form>

    <script>
        document.addEventListener('DOMContentLoaded', function() {
            const captureBtn = document.getElementById('capture-btn');
            const photoContainer = document.getElementById('photo-container');
            const csrfToken = document.querySelector('[name=csrfmiddlewaretoken]').value;
            
            captureBtn.addEventListener('click', function() {
                // 创建AJAX请求
                const xhr = new XMLHttpRequest();
                xhr.open('POST', '/capture/', true);
                // 设置请求头,带上CSRF令牌
                xhr.setRequestHeader('X-CSRFToken', csrfToken);
                
                xhr.onload = function() {
                    if (xhr.status === 200) {
                        const response = JSON.parse(xhr.responseText);
                        if (response.status === 'success') {
                            // 显示刚拍摄的照片
                            photoContainer.innerHTML = `<img src="${response.photo_url}" alt="Latest Photo" style="max-width: 600px; border: 1px solid #ccc;">`;
                            alert('Photo captured successfully!');
                        } else {
                            alert(`Oops, something went wrong: ${response.message}`);
                        }
                    } else {
                        alert('Failed to communicate with the server.');
                    }
                };
                
                xhr.onerror = function() {
                    alert('Network error occurred.');
                };
                
                // 发送请求
                xhr.send();
            });
        });
    </script>
</body>
</html>

5. 测试和关键注意事项

  • 启用树莓派摄像头:运行sudo raspi-config,选择"Interface Options" -> "Camera" -> 启用,重启Pi。
  • 启动Django开发服务器:python manage.py runserver 0.0.0.0:8000(用0.0.0.0让同一局域网的设备也能访问)。
  • 访问http://<你的Pi的IP地址>:8000,点击按钮就能拍照并在页面显示照片了!
  • 权限问题:确保Django进程有读写media文件夹的权限,必要时运行sudo chmod -R 755 media。

内容的提问来源于stack exchange,提问作者mimi829

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 09:30:43