如何在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
相关产品推荐
相关产品推荐

