如何在Django REST Framework中调用函数实现用户创建时双表更新?
Alright, let's walk through how to make this work. You need to run a custom function when hitting your Serializer's URL (specifically on create requests) that updates both the users table and the linked SMS table (where SMS.users_id is a foreign key to users.id). Here's a step-by-step implementation tailored for Django REST Framework:
Start by defining the logic that updates the User and SMS records. This keeps your code clean and reusable:
from django.db import transaction from django.utils import timezone from .models import SMS @transaction.atomic # Ensures both operations succeed or fail together def update_user_and_sms(user, sms_data=None): # Update the User record (customize this to your actual needs) user.last_active = timezone.now() # Example field update user.save() # Handle the SMS record: create if it doesn't exist, update if it does sms, created = SMS.objects.get_or_create(users_id=user.id) if sms_data: sms.message = sms_data.get("message", "Default update message") sms.status = sms_data.get("status", "processed") sms.save()
The @transaction.atomic decorator is critical here—it prevents partial updates if one operation fails (e.g., saving the User works but saving SMS fails).
If your create logic is tightly tied to the data being serialized, override the create method in your Serializer:
from rest_framework import serializers from .models import YourTargetModel # Replace with your actual model class YourModelSerializer(serializers.ModelSerializer): # Add a write-only field to capture SMS data from the request sms_message = serializers.CharField(write_only=True, required=False) class Meta: model = YourTargetModel fields = ["id", "title", "description", "user", "sms_message"] def create(self, validated_data): # Extract SMS data from the validated input (remove it before saving the main model) sms_data = {"message": validated_data.pop("sms_message", None)} # Create the main model instance first instance = super().create(validated_data) # Get the associated User (adjust this based on your model's relationship) target_user = instance.user # Use self.context['request'].user if targeting the logged-in user # Run your custom function update_user_and_sms(target_user, sms_data) return instance
If you prefer to keep serializer logic focused on data validation, override the perform_create method in your view (works for CreateAPIView or ModelViewSet):
from rest_framework import generics from rest_framework.permissions import IsAuthenticated from .models import YourTargetModel from .serializers import YourModelSerializer class YourModelCreateView(generics.CreateAPIView): serializer_class = YourModelSerializer permission_classes = [IsAuthenticated] # Restrict to logged-in users def perform_create(self, serializer): # Create the main model instance instance = serializer.save() # Get the user (use self.request.user if creating for the logged-in user) target_user = instance.user # Pull SMS data directly from the request if needed sms_data = {"message": self.request.data.get("sms_message")} # Execute your custom logic update_user_and_sms(target_user, sms_data)
- User Source: If you're creating a resource for the currently logged-in user, replace
instance.userwithself.request.user(in views) orself.context['request'].user(in serializers). - Update Operations: For PUT/PATCH requests, use the same pattern but override the
updatemethod in the serializer orperform_updatein the view. - Permissions: Always add permission classes (like
IsAuthenticated) to your view to restrict who can trigger these updates.
内容的提问来源于stack exchange,提问作者mohamadrezach

