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

如何通过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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 11:52:28