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

ViewSet中SlugField无法在JSON自动表单渲染下拉选项的解决方法

Fixing SlugRelatedField Dropdown in DRF Browsable API Form

Got it, let's sort out that form rendering issue you're facing. The problem is that DRF's auto-generated browsable API doesn't default to a dropdown for SlugRelatedField—it uses a plain text input instead. But we can tweak your serializer to keep your existing API behavior intact while making the form show a proper dropdown of department names.

Solution: Update the CourseSerializer

Modify your CourseSerializer to explicitly tell DRF to use a select widget for the department field:

from django import forms
from rest_framework import serializers
import your_app.models as models  # Adjust this import to match your app's structure

class CourseSerializer(serializers.ModelSerializer):
    department = serializers.SlugRelatedField(
        many=False,
        read_only=False,
        slug_field='name',
        queryset=models.Department.objects.all(),
        # Add this form_field configuration to enable the dropdown
        form_field=forms.ModelChoiceField(
            queryset=models.Department.objects.all(),
            to_field_name='name',
            label='Department'
        )
    )

    class Meta:
        model = models.Course
        fields = (
            'id',
            'course_name',
            'department',
            'course_number',
            'credits'
        )

What this does:

  • The form_field parameter overrides DRF's default text input for this field, replacing it with a ModelChoiceField that renders as a dropdown.
  • to_field_name='name' ensures the form submits the department's name (matching your SlugRelatedField's slug_field), so your existing POST request logic works exactly as before—no changes needed to your viewset or API behavior.
  • The dropdown automatically populates with all existing Department names from your database, and will update dynamically if you add new departments later.

Alternative Approach (DRF-Native)

If you'd rather avoid importing Django forms directly, you can override the serializer's get_fields method to adjust the widget only for the browsable API:

from django import forms
from rest_framework import serializers
from rest_framework.renderers import HTMLFormRenderer
import your_app.models as models

class CourseSerializer(serializers.ModelSerializer):
    department = serializers.SlugRelatedField(
        many=False,
        read_only=False,
        slug_field='name',
        queryset=models.Department.objects.all()
    )

    def get_fields(self):
        fields = super().get_fields()
        # Only adjust the widget if we're rendering the HTML form
        if self.context.get('request') and HTMLFormRenderer.format in self.context['request'].accepted_renderer.format:
            fields['department'].widget = forms.Select(choices=[(dept.name, dept.name) for dept in models.Department.objects.all()])
        return fields

    class Meta:
        model = models.Course
        fields = (
            'id',
            'course_name',
            'department',
            'course_number',
            'credits'
        )

This checks if we're rendering for the browsable API's HTML form and swaps the widget to a dropdown only in that scenario, leaving your API's JSON response and programmatic POST behavior completely unchanged.

内容的提问来源于stack exchange,提问作者Justin Dearing

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 03:54:53