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

Django表单联动:选择Sprint组后显示关联用户选项

需求与解决方案

需求

接触Django仅3个月,现有Sprint 1、Sprint 2等分组,每个分组对应特定用户集合。需要实现:选择某个Sprint分组时,下方自动显示该分组关联的用户选项,供选择。

现有代码

models.py

class Bug(models.Model):
    name = models.CharField(max_length=200, blank= False, null= False)
    info = models.TextField()
    status = models.CharField(max_length=25, choices=status_choice, default="Pending")
    assign_to = models.ForeignKey(User, on_delete=models.CASCADE, related_name='assigned', blank= True, null= True)
    assign_sprint = models.ForeignKey(Sprint, on_delete= models.CASCADE)
    phn_number = PhoneNumberField()
    uploaded_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete= models.CASCADE, related_name='user_name')
    created_at = models.DateTimeField(auto_now_add= True)
    updated_at = models.DateTimeField(blank= True, null = True)
    updated_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete= models.CASCADE, related_name='updated_user', null = True, blank=True)
    screeenshot = models.ImageField(upload_to='pics')
    platform = models.CharField(max_length=15, choices= platform_choice, default="Web") 

forms.py

class BugForm(ModelForm):
    name = forms.CharField(max_length=200)
    info = forms.TextInput()
    status = forms.ChoiceField(choices = status_choice, widget= forms.Select(),initial="Pending", disabled=True)
    platform = forms.ChoiceField(choices = platform_choice, widget= forms.Select())
    phn_number = PhoneNumberField()
    screeenshot = forms.ImageField()
    assigned_to = ??

    class Meta:
        model = Bug
        fields = ['name', 'info','platform' ,'status', 'assign_sprint', 'phn_number', 'screeenshot']
        widgets = {'assign_sprint': forms.Select()}

views.py

class BugUpload(LoginRequiredMixin, generic.CreateView):
    login_url = 'Login'
    model = Bug
    form_class = BugForm
    template_name = 'upload.html'
    success_url = reverse_lazy('index')


    def form_valid(self, form):
        form.instance.uploaded_by = self.request.user
        inst = form.save(commit=True)
        message = f"Bug created. Bug id:{inst.bug_id}"
        messages.add_message(self.request, messages.SUCCESS, message)
        return super().form_valid(form)

实现步骤

1. 完善Sprint模型(假设未关联用户)

先确保Sprint模型与User建立多对多关联,让每个Sprint可对应多个用户:

# models.py
from django.contrib.auth.models import User

class Sprint(models.Model):
    name = models.CharField(max_length=100)
    users = models.ManyToManyField(User, related_name='sprints')

    def __str__(self):
        return self.name

2. 修改forms.py

添加assigned_to字段,初始为空查询集,同时将其加入字段列表:

# forms.py
class BugForm(ModelForm):
    name = forms.CharField(max_length=200)
    info = forms.Textarea()  # 替换原TextInput,适配models中的TextField
    status = forms.ChoiceField(choices=status_choice, widget=forms.Select(), initial="Pending", disabled=True)
    platform = forms.ChoiceField(choices=platform_choice, widget=forms.Select())
    phn_number = PhoneNumberField()
    screeenshot = forms.ImageField()
    assigned_to = forms.ModelChoiceField(
        queryset=User.objects.none(),
        required=False,
        widget=forms.Select()
    )

    class Meta:
        model = Bug
        fields = ['name', 'info','platform' ,'status', 'assign_sprint', 'assigned_to', 'phn_number', 'screeenshot']
        widgets = {'assign_sprint': forms.Select()}

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # 编辑场景下,加载对应Sprint的用户
        if 'assign_sprint' in self.data:
            try:
                sprint_id = int(self.data.get('assign_sprint'))
                self.fields['assigned_to'].queryset = Sprint.objects.get(id=sprint_id).users.all()
            except (ValueError, TypeError, Sprint.DoesNotExist):
                pass
        elif self.instance.pk:
            self.fields['assigned_to'].queryset = self.instance.assign_sprint.users.all()

3. 添加API视图获取Sprint对应用户

在views.py中新增视图,根据Sprint ID返回关联用户列表:

# views.py
from django.http import JsonResponse
from django.contrib.auth.decorators import login_required

@login_required
def get_sprint_users(request):
    sprint_id = request.GET.get('sprint_id')
    if not sprint_id:
        return JsonResponse({'users': []})
    try:
        sprint = Sprint.objects.get(id=sprint_id)
        users = sprint.users.values('id', 'username')
        return JsonResponse({'users': list(users)})
    except Sprint.DoesNotExist:
        return JsonResponse({'users': []})

在urls.py中添加对应路由:

# urls.py
from django.urls import path
from . import views

urlpatterns = [
    # 其他路由...
    path('get-sprint-users/', views.get_sprint_users, name='get_sprint_users'),
]

4. 修改模板upload.html

添加JS监听Sprint选择事件,动态更新用户选项:

<!-- upload.html -->
<form method="post" enctype="multipart/form-data">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">提交</button>
</form>

<script>
document.addEventListener('DOMContentLoaded', function() {
    const sprintSelect = document.getElementById('id_assign_sprint');
    const userSelect = document.getElementById('id_assigned_to');

    // 监听Sprint选择变化
    sprintSelect.addEventListener('change', function() {
        const sprintId = this.value;
        userSelect.innerHTML = '<option value="">请选择用户</option>';
        if (!sprintId) return;

        // 请求API获取用户列表
        fetch(`/get-sprint-users/?sprint_id=${sprintId}`)
            .then(response => response.json())
            .then(data => {
                data.users.forEach(user => {
                    const option = document.createElement('option');
                    option.value = user.id;
                    option.textContent = user.username;
                    userSelect.appendChild(option);
                });
            })
            .catch(error => console.error('获取用户失败:', error));
    });

    // 页面加载时若已有Sprint值,触发一次change事件
    if (sprintSelect.value) {
        sprintSelect.dispatchEvent(new Event('change'));
    }
});
</script>

注意事项

  • 若Sprint模型已有用户关联逻辑,可调整查询用户的代码
  • 确保测试时处于登录状态,API视图添加了登录验证

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 21:50:24