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

在Django REST Framework中扩展User ModelSerializer以返回用户最新订阅信息

Alright, let's tackle this problem step by step. You need to extend your UserInfoSerializer to include details from the user's latest SubPurchase and its associated Subscription—specifically the subscription ID, name, and the expiry date (30 days after the purchase date). Here's how you can do it cleanly:

Step 1: Update the UserInfoSerializer

Modify your serializers.py to add custom fields using SerializerMethodField, which lets you define custom logic for fetching and calculating the required data:

from rest_framework import serializers
from django.utils import timezone
from datetime import timedelta
from .models import get_user_model, SubPurchase

class UserInfoSerializer(serializers.ModelSerializer):
    # Custom fields for subscription details
    current_subscription_id = serializers.SerializerMethodField()
    current_subscription_name = serializers.SerializerMethodField()
    subscription_expiry_date = serializers.SerializerMethodField()

    class Meta:
        model = get_user_model()
        fields = (
            'userID', 'username','email', 'name', 'balance', 
            'emailActivation', 'isSuspended',
            'current_subscription_id', 'current_subscription_name', 
            'subscription_expiry_date'
        )
        read_only_fields = fields  # All fields are read-only

    def get_current_subscription_id(self, obj):
        # Get the latest SubPurchase for the user
        latest_purchase = SubPurchase.objects.filter(user=obj).order_by('-dateOf').first()
        if latest_purchase and latest_purchase.subscription:
            return latest_purchase.subscription.subID
        return None

    def get_current_subscription_name(self, obj):
        latest_purchase = SubPurchase.objects.filter(user=obj).order_by('-dateOf').first()
        if latest_purchase and latest_purchase.subscription:
            return latest_purchase.subscription.nameOf
        return None

    def get_subscription_expiry_date(self, obj):
        latest_purchase = SubPurchase.objects.filter(user=obj).order_by('-dateOf').first()
        if latest_purchase:
            # Calculate expiry: purchase date + 30 days
            expiry_date = latest_purchase.dateOf + timedelta(days=30)
            # Return in ISO format (consistent with Django's datetime serialization)
            return timezone.localtime(expiry_date).isoformat()
        return None

Key Notes:

  • Fetching the latest subscription: We use order_by('-dateOf').first() to get the most recent SubPurchase for the user. This ensures we're always pulling the active/latest subscription.
  • Handling empty states: We check if latest_purchase and its associated subscription exist before accessing their attributes. This prevents errors if the user has never made a subscription purchase.
  • Timezone awareness: Using timezone.localtime() ensures the expiry date is adjusted to your app's timezone (if you have USE_TZ = True in settings.py), which is best practice for datetime handling.
  • Read-only fields: We set read_only_fields = fields since all data here is for display purposes and shouldn't be modified via this API.

Step 2: Verify the View

Your existing UserInfoViewSet doesn't need any changes—since we've added the custom fields directly to the serializer, the view will automatically include them in the response when fetching the user's data.

Example Response

When a user has an active subscription, your API response will look like this:

{
  "userID": 1,
  "username": "johndoe",
  "email": "john@example.com",
  "name": "John Doe",
  "balance": 500,
  "emailActivation": true,
  "isSuspended": false,
  "current_subscription_id": 2,
  "current_subscription_name": "Premium Plan",
  "subscription_expiry_date": "2024-05-20T14:30:00+02:00"
}

If the user has no subscriptions, those three fields will return null.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 10:57:38