如何通过Django与Ajax提交选中选项并保存至数据库?
问题:多选分类无法保存到数据库
提交表单时,选中的分类选项无法保存到数据库,试过各种方法都无效。已移除之前尝试修复的代码,需要解决该问题,重点是JS中如何正确追加分类数据以实现选中选项的保存。
相关代码
models.py
class Category(models.Model): category = models.CharField(max_length=200) slug = models.SlugField(null=True, blank=True) author = models.ForeignKey(User, on_delete=models.CASCADE) updated = models.DateTimeField(auto_now=True) created = models.DateTimeField(auto_now_add=True) class Gallery(models.Model): title = models.CharField(max_length=200) description = models.TextField(blank=True, null=True) category = models.ManyToManyField(Category,blank=True) thumbnail = models.ImageField(upload_to='thumbnails') slug = models.SlugField(null=True, blank=True) author = models.ForeignKey(User, on_delete=models.CASCADE) updated = models.DateTimeField(auto_now=True) created = models.DateTimeField(auto_now_add=True)
forms.py
class GalleryForm(forms.ModelForm): category = forms.ModelMultipleChoiceField( queryset=Category.objects.all(), widget=forms.SelectMultiple, required=False ) class Meta: model = Gallery fields = ['title', 'description', 'category','thumbnail']
views.py
def gallery_list_and_create(request): form = GalleryForm(request.POST or None, request.FILES or None) if(request.user.is_authenticated): user = User.objects.get(username=request.user.username) gallery_user = user.gallery_set.all() if(is_ajax(request=request)): if(form.is_valid()): instance = form.save(commit=False) instance.author = user instance.save() return JsonResponse({ 'id': instance.id, 'title': instance.title, 'description': instance.description, # 'category': [category.category for category in instance.category.all()], 'thumbnail': instance.thumbnail.url, 'slug': instance.slug, 'author': instance.author.username, 'since': instance.updated_timesince, }) context = { 'form': form, 'gallery': gallery_user, } return render(request, 'Post/index.html', context) return render(request, 'Post/index.html')
JS 文件
postForm.addEventListener("submit", e => { e.preventDefault() const fd = new FormData() fd.append('csrfmiddlewaretoken', csrf[0].value) fd.append('title', titleID.value) fd.append('description', descriptionID.value.length > 0 ? descriptionID.value : "") // 这里如何追加分类? fd.append('thumbnail', thumbnailID.files[0]) })
解决方案
1. JS 中正确追加多选分类
对于SelectMultiple组件,需要获取所有选中的选项,以**相同键名category**逐个追加到FormData中,Django的ModelMultipleChoiceField会自动识别多个同名参数为多选值:
postForm.addEventListener("submit", e => { e.preventDefault() const fd = new FormData() fd.append('csrfmiddlewaretoken', csrf[0].value) fd.append('title', titleID.value) fd.append('description', descriptionID.value.length > 0 ? descriptionID.value : "") // 获取所有选中的分类选项(注意选择器要匹配表单中分类组件的ID) const selectedCategories = document.querySelectorAll('#id_category option:checked'); selectedCategories.forEach(category => { fd.append('category', category.value); // 键名与表单字段名保持一致 }) fd.append('thumbnail', thumbnailID.files[0]) // 补充AJAX发送逻辑(示例) fetch(window.location.href, { method: 'POST', body: fd }) .then(res => res.json()) .then(data => { // 处理返回结果 }) })
2. 修复视图中的多对多保存问题
使用form.save(commit=False)只会保存Gallery实例,多对多关系不会自动保存,必须调用form.save_m2m()完成关联:
if(form.is_valid()): instance = form.save(commit=False) instance.author = user instance.save() form.save_m2m() # 新增该行,保存分类与画廊的多对多关系 return JsonResponse({ 'id': instance.id, 'title': instance.title, 'description': instance.description, 'category': [category.category for category in instance.category.all()], // 可取消注释返回分类数据 'thumbnail': instance.thumbnail.url, 'slug': instance.slug, 'author': instance.author.username, 'since': instance.updated_timesince, })
关键说明
- JS部分:不能用数组形式传递分类,必须逐个以
category为键追加,Django后端会自动解析为多选列表。 - 视图部分:
commit=False会跳过多对多字段的保存流程,手动调用save_m2m()是完成关联的必要步骤。
内容的提问来源于stack exchange,提问作者Endricho Folabessy
相关产品推荐
相关产品推荐

