Django 管理器、ModelForms 和一些混乱

Django Managers, ModelForms and some confusion

我正计划使用 Django 编写一个基本的 clock-in/clock-out 应用程序来跟踪工作时间。现在我的代码可以工作(start/stop 轮班或暂停),但我不使用任何 ModelForms 或 ModelManagers。所有业务代码都在我的视图和一个 services.py 文件中,这似乎不是正确的方法。

我试图阅读 ModelManagers 和 ModelForms,但我认为这让我很困惑。

假设我有一个模型 WorkTime:

class WorkTime(models.Model):
    employee = models.ForeignKey(User)
    created_at = models.DateTimeField(auto_now_add=True)
    shift_started = models.DateTimeField()
    shift_finished = models.DateTimeField(blank=True, null=True)
    shift_duration = models.DurationField(blank=True, null=True)
    work_reason = models.TextField(null=True)

我现在想有两种可能:

就像我现在的代码一样,它不是真正的美,绝对不是 DRY。我怎样才能以最聪明的方式解决问题,比如定义一个适合所有可能情况的 ModelForm(只需开始一个新班次,结束 运行 班次(仅通过访问浏览器中的视图)或手动添加整个班次使用 HTML 形式)。或者我会把它分成一个 ModelManager 来执行 shift starting/stopping 部分和一个 ModelForm 用于手动添加狗屎作为实际的 HTML-form?

仅通过普通 GET 请求输入一些 URL 来更改班次开始和停止时间不是一个好主意。浏览器可以缓存该请求或触发多个请求(刷新页面时不会弹出它可以执行两次操作,例如 POST 请求)。所以你最好把它改成 POST requests.

对于所有这些视图,您当然可以使用一个 ModelForm:

class SiftForm(forms.ModelForm):

    class Meta:
        model = WorkTime
        fields = ('created_at', 'shift_started', 'shift_finished') # you shouldn't pass user and duration time here



class ShiftStartView(CreateView):
    model = WorkTime
    form_class = ShiftForm
    success_url = "some_url" # after creating WorkTime, view will redirect to that url. You can (and really should) pass reverse_lazy() here, instead of URL as string, if you don't want to hardcode URL.

    def dispatch(self, request, *args, **kwargs):

        # if you want to prevent creating 2 started but not stopped WorkTimes for one user, you should put logic preventing it here.

        return super(ShiftStartView, self).dispatch(self, request, *args, **kwargs)

    def form_valid(self, form):
        worktime = form.save(commit=False)
        worktime.employee = self.request.user

        worktime.save()
        return super(ShiftStartView, self).form_valid(form)

这样您还可以创建用于手动创建 WorkTime 的表单。要创建停止视图,您应该使用 UpdateView 并在 get_object 方法中为用户获取当前 WorkTime