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

如何在Django Inlineformset_factory中按用户限制工时表项目选择?

解决前端工时表项目下拉限制问题

要实现前端用户只能选择自己参与的项目,我们需要在表单层面过滤项目的查询集,同时把当前用户传递到每个inline表单中。下面是具体步骤:

1. 修改TimesheetRowInlineForm,添加用户过滤逻辑

我们需要在表单的初始化方法中接收当前用户,并据此过滤project字段的可选项目:

class TimesheetRowInlineForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        # 从参数中取出当前用户,默认值为None
        self.current_user = kwargs.pop('user', None)
        super().__init__(*args, **kwargs)
        
        # 如果用户存在,只显示该用户参与的项目(通过staff多对多关联)
        if self.current_user:
            self.fields['project'].queryset = Project.objects.filter(staff=self.current_user)
            
            # (可选)如果用户没有关联项目,你可以选择显示所有项目或者空选项
            # if not self.fields['project'].queryset.exists():
            #     self.fields['project'].queryset = Project.objects.all()

    class Meta:
        model = TimesheetRow
        exclude =['timesheet']
        widgets = {
            'id' : forms.HiddenInput(),
            'project' : forms.Select(attrs={'class' : 'form-control'}),
            'labor' : forms.Select(attrs={'class' : 'form-control'}),
            'sunday' : forms.NumberInput(attrs={'class' : 'form-control'}),
            'monday' : forms.NumberInput(attrs={'class' : 'form-control'}),
            'tuesday' : forms.NumberInput(attrs={'class' : 'form-control'}),
            'wednesday' : forms.NumberInput(attrs={'class' : 'form-control'}),
            'thursday' : forms.NumberInput(attrs={'class' : 'form-control'}),
            'friday' : forms.NumberInput(attrs={'class' : 'form-control'}),
            'saturday' : forms.NumberInput(attrs={'class' : 'form-control'}),
        }

2. 在视图中传递用户到FormSet

接下来,在TimesheetView的get_context_data方法中,初始化formset时通过form_kwargs把当前用户传递给每个inline表单:

class TimesheetView (LoginRequiredMixin, UpdateView):
    # 保留原有代码...
    
    def get_context_data(self, **kwargs):
        data = super(TimesheetView, self).get_context_data(**kwargs)
        current_user = self.request.user
        timesheet_obj = self.get_object()
        
        if self.request.POST:
            # POST请求时,传递用户参数
            data['timesheetrows'] = TimesheetRowInlineFormSet(
                self.request.POST, 
                instance=timesheet_obj,
                form_kwargs={'user': current_user}
            )
        else:
            # GET请求时,同样传递用户参数
            data['timesheetrows'] = TimesheetRowInlineFormSet(
                instance=timesheet_obj,
                form_kwargs={'user': current_user}
            )
        return data
    
    # 保留原有代码...

3. (可选)扩展过滤逻辑

如果需要包含用户作为项目主管的项目,可以修改表单中的过滤条件,和你admin后台的逻辑保持一致:

from django.db.models import Q

# 同时包含用户作为staff和supervisor的项目
self.fields['project'].queryset = Project.objects.filter(
    Q(staff=self.current_user) | Q(supervisor=self.current_user)
)

现在用户打开工时表页面时,project下拉框只会显示他们有权限选择的项目,完全符合你的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:01:58