Django技术问题:在两个不同视图(表单)中更新用户字段失效
Alright, let's break down why your user profile updates aren't showing up in the Django admin even though POST requests are hitting the server. I've seen this exact issue a handful of times, so let's go through the most likely culprits step by step:
Chances are, your questionnaire view is saving form data without linking it to the user who just registered. For example, if your view looks like this:
def questionnaire(request): if request.method == 'POST': form = QuestionnaireForm(request.POST) if form.is_valid(): form.save() # This creates a NEW instance instead of updating the existing user! return redirect('home') else: form = QuestionnaireForm() return render(request, 'account/questionnaire.html', {'form': form})
This will either create a new, unlinked user (if your form uses the User model) or save data that's never connected to the logged-in user. Fix it by explicitly passing the current user as the form's instance:
from django.contrib.auth.decorators import login_required @login_required # Make sure only logged-in users can access this def questionnaire(request): if request.method == 'POST': # Bind the form to the currently logged-in user form = QuestionnaireForm(request.POST, instance=request.user) if form.is_valid(): form.save() # Now this updates the existing user's data return redirect('profile') else: # Pre-fill the form with the user's existing data (if any) form = QuestionnaireForm(instance=request.user) return render(request, 'account/questionnaire.html', {'form': form})
If you're storing age/weight/height in a separate UserProfile model (a common pattern for extending Django's default User), you need to make sure your form targets that model and links to the user's profile:
Models.py example:
from django.db import models from django.contrib.auth.models import User class UserProfile(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE) age = models.IntegerField(null=True, blank=True) weight = models.FloatField(null=True, blank=True) height = models.FloatField(null=True, blank=True)
Forms.py fix:
from django import forms from .models import UserProfile class QuestionnaireForm(forms.ModelForm): class Meta: model = UserProfile fields = ['age', 'weight', 'height']
View adjustment:
@login_required def questionnaire(request): # Get or create the profile for the logged-in user (avoids missing profile errors) profile, created = UserProfile.objects.get_or_create(user=request.user) if request.method == 'POST': form = QuestionnaireForm(request.POST, instance=profile) if form.is_valid(): form.save() return redirect('profile') else: form = QuestionnaireForm(instance=profile) return render(request, 'account/questionnaire.html', {'form': form})
Double-check your questionnaire.html to ensure:
- The form uses
method="POST" - It includes Django's CSRF token (required for POST requests)
<form method="POST"> {% csrf_token %} {{ form.as_p }} <button type="submit">Save My Info</button> </form>
If you omitted the CSRF token, Django would silently reject the request, but you mentioned seeing POST logs—so this is less likely, but worth confirming.
Just because the server gets a POST request doesn't mean the form passed validation. Add error logging to your view and display errors in the template to debug:
View with logging:
import logging logger = logging.getLogger(__name__) @login_required def questionnaire(request): profile, created = UserProfile.objects.get_or_create(user=request.user) if request.method == 'POST': form = QuestionnaireForm(request.POST, instance=profile) if form.is_valid(): form.save() logger.info(f"User {request.user.username} updated their profile successfully") return redirect('profile') else: # Log validation errors to your server console logger.error(f"Form errors for {request.user.username}: {form.errors}") else: form = QuestionnaireForm(instance=profile) return render(request, 'account/questionnaire.html', {'form': form})
Template with error display:
<form method="POST"> {% csrf_token %} {% if form.errors %} <div style="color: red;"> {% for field in form %} {% for error in field.errors %} <p>{{ field.label }}: {{ error }}</p> {% endfor %} {% endfor %} </div> {% endif %} {{ form.as_p }} <button type="submit">Save My Info</button> </form>
Common validation issues: missing required fields, invalid data types (e.g., entering text for age), or field values that don't match your model's constraints.
If you're using a custom UserProfile model, you need to register it in admin.py to see the data:
from django.contrib import admin from .models import UserProfile class UserProfileAdmin(admin.ModelAdmin): list_display = ['user', 'age', 'weight', 'height'] # Show these columns in the admin list search_fields = ['user__username'] # Let you search by username admin.site.register(UserProfile, UserProfileAdmin)
If you added fields directly to the default User model, you'll need to customize the UserAdmin to display them:
from django.contrib.auth.admin import UserAdmin from django.contrib.auth.models import User class CustomUserAdmin(UserAdmin): # Add your custom fields to the admin detail page fieldsets = UserAdmin.fieldsets + ( ('Profile Details', {'fields': ('age', 'weight', 'height')}), ) # Show them in the admin list view too list_display = UserAdmin.list_display + ('age',) # Unregister the default UserAdmin and register your custom one admin.site.unregister(User) admin.site.register(User, CustomUserAdmin)
Rare but possible: signals, middleware, or transaction code might be rolling back your changes after saving. Temporarily comment out any custom signals or transaction blocks to rule this out. Also, make sure you're not catching exceptions in your view without logging them—this can hide failures where data isn't saved.
Start with the first two steps (binding the form to the user/model) since those are the most common fixes for this exact scenario.
内容的提问来源于stack exchange,提问作者kubeq24

