基于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
相关产品推荐
相关产品推荐

