基于Django 2.0的聊天网站人脸登录认证实现技术问询
Hey there! Let's walk through how to set this up for your Django 2.0 chat app—since you're new to Django, I'll break this down into clear, actionable steps that tie together photo storage during registration and face authentication on login.
First, we need to set up Django to handle file uploads and link user photos to their accounts.
Step 1: Configure Media File Settings
Django needs to know where to store user-uploaded files. Add these lines to your settings.py:
import os # Media files (user-uploaded content) MEDIA_ROOT = os.path.join(BASE_DIR, 'media') MEDIA_URL = '/media/'
Then, update your project's urls.py to serve media files in development (note: this is only for dev—use a web server like Nginx for production):
from django.conf import settings from django.conf.urls.static import static urlpatterns = [ # Your existing routes here (admin, login, etc.) ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Don't forget to install Pillow (required for Django's ImageField):
pip install pillow
Step 2: Extend the User Model (or Create a Profile)
Since Django's default User model doesn't have a photo field, we'll create a linked UserProfile model to store face images:
# models.py from django.db import models from django.contrib.auth.models import User class UserProfile(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE) face_image = models.ImageField(upload_to='user_faces/', blank=False, null=False) def __str__(self): return f"{self.user.username}'s Profile"
Run migrations to create this new table:
python manage.py makemigrations python manage.py migrate
Step 3: Build a Registration Form with Photo Upload
Create a custom registration form that includes the face image field:
# forms.py from django import forms from django.contrib.auth.forms import UserCreationForm from django.contrib.auth.models import User from .models import UserProfile class RegisterForm(UserCreationForm): face_image = forms.ImageField(label="Upload Your Face Photo", required=True) email = forms.EmailField(required=True) class Meta: model = User fields = ['username', 'email', 'password1', 'password2', 'face_image'] def save(self, commit=True): user = super().save(commit=False) user.email = self.cleaned_data['email'] if commit: user.save() # Create and link the profile with the uploaded photo UserProfile.objects.create( user=user, face_image=self.cleaned_data['face_image'] ) return user
Step 4: Registration View & Template
Create a view to handle form submissions:
# views.py from django.shortcuts import render, redirect from .forms import RegisterForm def register(request): if request.method == 'POST': form = RegisterForm(request.POST, request.FILES) if form.is_valid(): form.save() return redirect('face_login') # Redirect to your face login page else: form = RegisterForm() return render(request, 'register.html', {'form': form})
And a template (register.html)—make sure to add enctype="multipart/form-data" to the form, or file uploads won't work:
<!-- register.html --> <h2>Register</h2> <form method="POST" enctype="multipart/form-data"> {% csrf_token %} {{ form.as_p }} <button type="submit">Create Account</button> </form>
Now let's tie your existing face_recognition and cv2 script into Django's login flow.
Step 1: Custom Face Login View
Create a view that captures a photo via cv2, compares it to the stored user photo, and logs the user in if there's a match:
# views.py from django.shortcuts import render, redirect from django.contrib.auth import login from django.contrib.auth.models import User from .models import UserProfile import cv2 import face_recognition import numpy as np def face_login(request): if request.method == 'POST': username = request.POST.get('username') try: user = User.objects.get(username=username) profile = UserProfile.objects.get(user=user) # Load stored face encoding (we'll optimize this later!) stored_image = face_recognition.load_image_file(profile.face_image.path) stored_encodings = face_recognition.face_encodings(stored_image) if not stored_encodings: return render(request, 'face_login.html', {'error': "No face detected in your stored photo."}) stored_encoding = stored_encodings[0] # Capture photo via webcam cap = cv2.VideoCapture(0) ret, frame = cap.read() cap.release() if not ret: return render(request, 'face_login.html', {'error': "Couldn't capture photo from webcam."}) # Get encoding from captured photo current_encodings = face_recognition.face_encodings(frame) if not current_encodings: return render(request, 'face_login.html', {'error': "No face detected in the captured photo."}) current_encoding = current_encodings[0] # Compare faces matches = face_recognition.compare_faces([stored_encoding], current_encoding) if matches[0]: login(request, user) return redirect('chat_home') # Redirect to your chat app homepage else: return render(request, 'face_login.html', {'error': "Face mismatch—authentication failed."}) except User.DoesNotExist: return render(request, 'face_login.html', {'error': "User not found."}) except UserProfile.DoesNotExist: return render(request, 'face_login.html', {'error': "No face photo found for this user."}) else: return render(request, 'face_login.html')
Step 2: Face Login Template
Create a simple template (face_login.html) to collect the username and trigger authentication:
<!-- face_login.html --> <h2>Face Login</h2> <form method="POST"> {% csrf_token %} <label for="username">Username:</label> <input type="text" id="username" name="username" required> {% if error %} <p style="color: red;">{{ error }}</p> {% endif %} <button type="submit">Authenticate with Face</button> </form>
Step 3: Add Routes
Update your app's urls.py to include the new views:
# urls.py from django.urls import path from . import views urlpatterns = [ path('register/', views.register, name='register'), path('face-login/', views.face_login, name='face_login'), # Add your chat homepage route here ]
Precompute Face Encodings: Loading and encoding the stored photo every login is slow. Modify the
UserProfilemodel to store the encoding directly (as a string) when the photo is uploaded:# models.py (updated) class UserProfile(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE) face_image = models.ImageField(upload_to='user_faces/', blank=False, null=False) face_encoding = models.TextField(blank=True) def save(self, *args, **kwargs): # Generate encoding when photo is saved if self.face_image and not self.face_encoding: image = face_recognition.load_image_file(self.face_image.path) encodings = face_recognition.face_encodings(image) if encodings: # Convert numpy array to string for storage self.face_encoding = ','.join(map(str, encodings[0].tolist())) super().save(*args, **kwargs) def get_encoding(self): # Convert string back to numpy array if self.face_encoding: return np.array(list(map(float, self.face_encoding.split(',')))) return NoneThen in your login view, replace the stored image loading with
stored_encoding = profile.get_encoding().Production Media Handling: The
staticmedia route we set up is only for development. In production, configure Nginx/Apache to serve files fromMEDIA_ROOTdirectly—never use Django to serve media in production.Error Handling: Expand the error cases to handle things like webcam permission issues, invalid photo formats, or multiple faces detected in a photo.
内容的提问来源于stack exchange,提问作者AkshatP

