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

Django Admin添加UserRoleMap数据时提示无效选项问题求助

Django Admin录入UserRoleMap时外键字段报错的解决方案

问题描述

在admin.py中注册模型后,通过Django Admin内置添加表单手动录入UserRoleMap数据时,customer和role字段均出现错误提示:Select a valid choice. That choice is not one of the available choices。

原模型代码如下:

class UserRoles(models.Model):
    _id = models.ObjectIdField(primary_key=True, editable=False)
     role_name = models.CharField(unique=True, max_length=80)

    def __str__(self):
        return f"{self.role_name} (Level {self.role_level})"

  class User(models.Model):
     _id = models.ObjectIdField(primary_key=True, editable=False)
      first_name = models.CharField(max_length=80)
      last_name = models.CharField(max_length=80)
      email = models.EmailField(max_length=255)
      username = models.CharField(max_length=100)

      def __str__(self):
          return str(self.email) + ' | ' + str(self._id)

  class UserRoleMap(models.Model):
    _id = models.ObjectIdField(primary_key=True, editable=False)
    role = models.ForeignKey(
    UserRoles, on_delete=models.CASCADE, related_name='user_role_id') : main problem
    customer = models.ForeignKey(
    User, on_delete=models.CASCADE, related_name='user_id') : main problem


    def __str__(self):
         return f"User: {self.customer.email}

问题原因

核心问题是Django Admin默认的表单组件不支持ObjectIdField类型的主键。Django的ModelChoiceField(外键对应的Admin表单字段)默认以整数类型处理主键,而ObjectIdField是字符串格式的MongoDB ObjectId,导致Admin验证选中项时,无法将提交的字符串与ObjectId类型的主键匹配,从而判定选择无效。

解决方案

1. 自定义处理ObjectId的表单字段

创建一个自定义ModelChoiceField,适配ObjectId类型的主键:

from django import forms
from bson import ObjectId

class ObjectIdModelChoiceField(forms.ModelChoiceField):
    def to_python(self, value):
        if value in self.empty_values:
            return None
        try:
            return self.queryset.get(pk=ObjectId(value))
        except (ValueError, TypeError, self.queryset.model.DoesNotExist):
            raise forms.ValidationError(self.error_messages['invalid_choice'], code='invalid_choice')

    def valid_value(self, value):
        if isinstance(value, ObjectId):
            value = str(value)
        return super().valid_value(value)

2. 为UserRoleMap编写自定义Admin表单

在admin.py中,替换外键字段为自定义的ObjectIdModelChoiceField:

from django.contrib import admin
from .models import User, UserRoles, UserRoleMap

class UserRoleMapForm(forms.ModelForm):
    role = ObjectIdModelChoiceField(queryset=UserRoles.objects.all())
    customer = ObjectIdModelChoiceField(queryset=User.objects.all())

    class Meta:
        model = UserRoleMap
        fields = '__all__'

3. 注册Admin时使用自定义表单

修改UserRoleMap的Admin注册代码,指定使用上述自定义表单:

@admin.register(UserRoleMap)
class UserRoleMapAdmin(admin.ModelAdmin):
    form = UserRoleMapForm

额外:修复模型代码中的语法错误

原模型代码存在几处语法问题,必须先修正才能正常运行:

  • UserRoles的__str__方法引用了未定义的role_level字段,要么删除该部分,要么添加对应的role_level字段
  • UserRoleMap的__str__方法字符串未闭合,补充引号
  • 外键字段定义末尾的: main problem注释需删除,避免语法错误

修正后的模型代码示例:

from django.db import models
from bson import ObjectId

class UserRoles(models.Model):
    _id = models.ObjectIdField(primary_key=True, editable=False)
    role_name = models.CharField(unique=True, max_length=80)
    # 可选:添加role_level字段
    # role_level = models.IntegerField(default=1)

    def __str__(self):
        # 若添加了role_level则保留括号部分,否则直接返回role_name
        return f"{self.role_name}"

class User(models.Model):
    _id = models.ObjectIdField(primary_key=True, editable=False)
    first_name = models.CharField(max_length=80)
    last_name = models.CharField(max_length=80)
    email = models.EmailField(max_length=255)
    username = models.CharField(max_length=100)

    def __str__(self):
        return f"{self.email} | {self._id}"

class UserRoleMap(models.Model):
    _id = models.ObjectIdField(primary_key=True, editable=False)
    role = models.ForeignKey(UserRoles, on_delete=models.CASCADE, related_name='user_role_id')
    customer = models.ForeignKey(User, on_delete=models.CASCADE, related_name='user_id')

    def __str__(self):
        return f"User: {self.customer.email}"

内容的提问来源于stack exchange,提问作者Ritik Sharma

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 03:26:17