【发布时间】:2018-01-12 14:20:18
【问题描述】:
我有一个时间表应用程序,我想限制用户可以将时间分配给他们正在从事的项目的项目。
模型我的模型看起来像这样
class Project (models.Model):
name = models.CharField(
verbose_name = 'Project Title',
max_length = 80
)
code = models.CharField(
verbose_name = 'Project Code',
max_length = 15
)
supervisor = models.ForeignKey (
User,
on_delete=models.CASCADE
)
staff = models.ManyToManyField (
User,
related_name= "project_resources"
)
def __str__(self):
return u'%s' % (self.name)
class Meta:
ordering = ['name']
class Timesheet (models.Model):
user = models.ForeignKey (
User,
on_delete=models.CASCADE)
start_date = models.DateField (
verbose_name = "Start Date"
)
def __str__(self):
return u'%s | %s' % (self.user, self.start_date)
class Meta:
ordering = ['user','start_date']
class TimesheetRow (models.Model):
''' specifies a timesheet row which is unique based on Timesheet, Project and Labour Category
'''
timesheet = models.ForeignKey(
Timesheet,
on_delete=models.CASCADE
)
project = models.ForeignKey(
Project,
on_delete=models.CASCADE
)
labor = models.ForeignKey(
LaborCategory,
on_delete=models.CASCADE
)
sunday = models.DecimalField (default = 0, max_digits=4, decimal_places=2)
monday = models.DecimalField (default = 0, max_digits=4, decimal_places=2)
tuesday = models.DecimalField (default = 0, max_digits=4, decimal_places=2)
wednesday = models.DecimalField (default = 0, max_digits=4, decimal_places=2)
thursday = models.DecimalField (default = 0, max_digits=4, decimal_places=2)
friday = models.DecimalField (default = 0, max_digits=4, decimal_places=2)
saturday = models.DecimalField (default = 0, max_digits=4, decimal_places=2)
def __str__(self):
return u'%s | %s' % (self.timesheet.user, self.timesheet.start_date)
class Meta:
unique_together = ('timesheet', 'project', 'labor',)
ordering = ['timesheet', 'project','labor']
而我的 FORMS 看起来像这样。
class TimesheetForm(forms.ModelForm):
class Meta:
model = Timesheet
fields = ['id', 'user', 'start_date']
widgets = {
'user' : forms.HiddenInput(),
'id' : forms.HiddenInput(),
'start_date' : forms.HiddenInput(),
}
class TimesheetRowInlineForm(forms.ModelForm):
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'}),
}
TimesheetRowInlineFormSet = forms.inlineformset_factory(
Timesheet,
TimesheetRow,
form=TimesheetRowInlineForm,
extra=1,
exclude = ['id'],
can_delete=True,
can_order=False)
这为我提供了一个很好的表单,并且通过视图一切正常,但我无法弄清楚如何将 TimesheetRowInlineForm 上的项目下拉列表限制为 staff 中的用户。
为了完整起见,这是 VIEW
class TimesheetView (LoginRequiredMixin, UpdateView):
model = Timesheet
form_class = TimesheetForm
success_url = '/'
def get_start_date(self, *args, **kwargs):
try:
start_date = self.kwargs['start_date']
except:
today = datetime.date.today()
start_date = today - datetime.timedelta(7+ ((today.weekday()+1)%7) )
return start_date
def get_object(self, *args, **kwargs):
obj, created = Timesheet.objects.get_or_create(user=self.request.user, start_date=self.get_start_date())
return obj
def get_context_data(self, **kwargs):
data = super(TimesheetView, self).get_context_data(**kwargs)
if self.request.POST:
data['timesheetrows'] = TimesheetRowInlineFormSet(self.request.POST, instance=self.get_object())
else:
data['timesheetrows'] = TimesheetRowInlineFormSet(instance=self.get_object())
return data
def get_initial(self):
return { 'user': self.request.user,
'start_date' : self.get_start_date() }
def form_valid(self, form):
context = self.get_context_data()
timesheetrows = context['timesheetrows']
with transaction.atomic():
self.object = form.save()
if timesheetrows.is_valid():
timesheetrows.instance = self.object
timesheetrows.save()
return super(TimesheetView, self).form_valid(form)
编辑
我已经想出了如何在管理员中执行此操作,即:
class TimesheetRowAdmin(admin.ModelAdmin):
def get_model_perms(self, request):
"""
Return empty perms dict thus hiding the model from admin index.
"""
return {}
admin.site.register(TimesheetRow, TimesheetRowAdmin)
class TimesheetRowInline(admin.TabularInline):
model = TimesheetRow
can_delete = True
extra = 1
def formfield_for_foreignkey(self, db_field, request=None,**kwargs):
field = super(TimesheetRowInline, self).formfield_for_foreignkey(db_field, request, **kwargs)
if db_field.name == 'project':
if request.user is not None:
field.queryset = field.queryset.filter(staff=request._obj_.user)
if not field.queryset:
field.queryset = field.queryset.all()
else:
field.queryset = field.queryset.none()
return field
class TimesheetAdmin(admin.ModelAdmin):
list_display = ['user', 'start_date']
ordering = ['user','start_date']
inlines = [TimesheetRowInline]
def get_form(self, request, obj=None, **kwargs):
request._obj_ = obj
return super().get_form(request, obj, **kwargs)
admin.site.register(Timesheet, TimesheetAdmin)
我仍然需要为编外用户反映这一点。
【问题讨论】:
-
这是一种常见的做法——限制访问。可以用
has_perm,用is_staff,用特定的查询等等。你试过什么? -
如果这很常见,我无法理解为什么我看不到有人以前是如何做到的。我很难相信我是唯一一个对此不明显的人。我在任何地方都找不到任何我想要达到的目标的例子。
标签: django django-forms