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

如何在Django REST Framework中基于allauth的EmailAddress模型创建用户邮箱ChoiceField

问题原因

你的代码存在两个核心问题:

  1. 自定义字段CustomChoiceField的__init__方法执行时,序列化器的context还未注入到字段实例中,此时无法获取当前登录用户
  2. 序列化器中声明email字段时,误用了默认的serializers.ChoiceField,没有调用你自定义的CustomChoiceField类

解决方案

方案一(更推荐,无需自定义字段):在序列化器__init__方法中动态赋值choices

直接修改users/serializers.py代码如下:

from rest_framework import serializers
from users.models import *

class AuthUserSerializer(serializers.ModelSerializer):
    # 先声明ChoiceField,初始choices设为空,后续动态赋值
    email = serializers.ChoiceField(choices=[])

    class Meta:
        model = User
        fields = ('id', 'username', 'first_name', 'last_name', 'email', 'avatar',
            'bio', 'country', 'is_staff', 'is_active', 'is_superuser', 'last_login',
            'date_joined')
        extra_kwargs = {
            'is_staff': { 'read_only': True },
            'is_superuser': { 'read_only': True },
            'last_login': { 'read_only': True },
            'date_joined': { 'read_only': True }
        }
    
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # 此时context已完成注入,可以正常获取请求对象
        request = self.context.get('request')
        if request and request.user.is_authenticated:
            # 过滤当前登录用户的所有邮箱作为选项
            self.fields['email'].choices = EmailAddress.objects.filter(user=request.user).values_list('email', 'email')

这个方案逻辑更直观,DRF可浏览API可以直接识别到动态赋值的choices,自动将邮箱字段渲染为下拉选择框。

方案二:修复自定义字段逻辑

如果你需要保留自定义字段的实现,修改代码如下:

class CustomChoiceField(serializers.ChoiceField):
    # 重写get_choices方法,此时context已注入完成
    def get_choices(self, cutoff=None):
        request = self.context.get('request')
        if request and request.user.is_authenticated:
            self.choices = EmailAddress.objects.filter(user=request.user).values_list('email', 'email')
        return super().get_choices(cutoff)

class AuthUserSerializer(serializers.ModelSerializer):
    # 注意此处要调用你自定义的CustomChoiceField,不是默认的ChoiceField
    email = CustomChoiceField(choices=[])
    
    class Meta:
        model = User
        fields = ('id', 'username', 'first_name', 'last_name', 'email', 'avatar',
            'bio', 'country', 'is_staff', 'is_active', 'is_superuser', 'last_login',
            'date_joined')
        extra_kwargs = {
            'is_staff': { 'read_only': True },
            'is_superuser': { 'read_only': True },
            'last_login': { 'read_only': True },
            'date_joined': { 'read_only': True }
        }

内容的提问来源于stack exchange,提问作者Ajay Lingayat

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 23:06:00