Django中如何从下拉选项保存课程名称与Slug两个值?
解决方案
首先明确核心问题:当前模板传递的是课程名称(可能重复),且未利用Django表单的关联验证逻辑,导致无法正确关联课程的slug并保存关联关系。以下是分步修正方案:
1. 确认模型字段类型
确保Welcome模型中的courses字段是多对多关联(因为模板是多选下拉):
# models.py class Welcome(models.Model): message = models.TextField() courses = models.ManyToManyField(Course, related_name='welcome_entries') # 多对多关联Course
2. 修正模板的下拉选项值
将option的value从课程名称改为唯一的slug,确保提交的是可精准匹配的标识:
<select class="form-select" data-search="on" name="courses" multiple> <option></option> {% for data in courses %} <option value="{{ data.slug }}">{{ data.name }}</option> {% endfor %} </select>
3. 调整ModelForm的字段配置
自定义courses字段,指定用slug作为匹配字段,让表单能正确识别提交的slug并关联到Course对象:
# forms.py class WelcomeForm(ModelForm): message = forms.CharField(widget=forms.Textarea) # 自定义多对多选择字段,基于slug匹配 courses = forms.ModelMultipleChoiceField( queryset=Course.objects.all(), to_field_name='slug', # 指定用slug作为匹配字段 widget=forms.SelectMultiple(attrs={'class': 'form-select', 'data-search': 'on'}) ) class Meta: model = Welcome fields = ['message', 'courses']
4. 修正视图逻辑(修复缩进+完善关联保存)
视图存在缩进错误,且多对多关系需要额外调用save_m2m()完成保存:
# views.py from django.shortcuts import render from django.contrib import messages from .models import Welcome, Course from .forms import WelcomeForm def add_welcome(request): courses = Course.objects.all() # all()不会抛出ObjectDoesNotExist,无需try-except form = WelcomeForm() if request.method == 'POST': form = WelcomeForm(request.POST) if form.is_valid(): welcome_instance = form.save(commit=False) welcome_instance.save() form.save_m2m() # 必须调用此方法保存多对多关联 messages.success(request, 'Welcome settings has been added successfully') context = {'courses': courses, 'form': form} return render(request, 'welcome/add_form.html', context)
可选:完全不用Django Forms的手动处理方案
如果坚持不使用ModelForm,可直接手动解析POST数据并关联课程:
# views.py def add_welcome(request): courses = Course.objects.all() if request.method == 'POST': message = request.POST.get('message') selected_slugs = request.POST.getlist('courses') # 多选需用getlist获取所有值 # 通过slug筛选对应的课程对象 selected_courses = Course.objects.filter(slug__in=selected_slugs) # 创建Welcome实例并关联课程 welcome = Welcome.objects.create(message=message) welcome.courses.add(*selected_courses) messages.success(request, 'Welcome settings has been added successfully') context = {'courses': courses} return render(request, 'welcome/add_form.html', context)
模板保持和之前一致即可,这种方式需自行处理数据验证(比如判断slug是否存在),不如ModelForm安全规范。
内容的提问来源于stack exchange,提问作者yoknamitru
相关产品推荐
相关产品推荐

