Django FormView:如果记录不存在则添加,如果存在则更新

Django FormView: Add if record does not exist and update if it does exist

我创建了一个 FormView,如果用户第一次执行该过程,它可以正常工作。但是,当它第二次执行时,我收到一条错误消息,指出该记录已经存在。这是预期的,因为模型中的用户是唯一的。如果记录已经存在,我该如何解决这个问题,以便当前记录被 form.save 覆盖。

models.py

class ttemp_selection(models.Model):
    select_account = models.ForeignKey(tledger_account, on_delete=models.CASCADE)
    date_from = models.DateField(default=datetime.today)
    date_to = models.DateField(default=datetime.today)
    user = models.ForeignKey(custom_user, on_delete=models.CASCADE, unique=True)

    def __str__(self):
        return self.select_account

forms.py

class Meta:
    model = ttemp_selection
    fields = ['select_account', 'date_from', 'date_to', 'user']

def __init__(self, *args, **kwargs):
    self.request = kwargs.pop('request')
    super(SelectAccountForm, self).__init__(*args, **kwargs)
    user = self.request.user
    current_company = user.current_company
    self.fields['select_account'].queryset = tledger_account.objects.filter(
        company=current_company, gl_category='Cash and Bank')

view.py

class sasView(FormView):
    template_name = 'cashflow/select_account.html'
    form_class = SelectAccountForm
    success_url = 'home'
    def form_valid(self, form):
        form.save()
        return super().form_valid(form)

    def get_form_kwargs(self):

        kwargs = super(sasView, self).get_form_kwargs()
        kwargs['request'] = self.request
        return kwargs
    

我可以使用ttemp_selection.objects.get(user=request.user)来确定记录 我知道我可以使用 UpdateView class 但是当记录不存在时这会产生问题。它还将添加一个不必要的额外步骤。 将不胜感激。

您可以使用 CreateView,并稍微改变行为以指定 self.object(如果存在):

from django.contrib.auth.mixins import LoginRequiredMixin

class sasView(<b>LoginRequiredMixin</b>, CreateView):
    template_name = 'cashflow/select_account.html'
    form_class = SelectAccountForm
    success_url = 'home'
    
    def get_form(self, *args, **kwargs):
        <b>self.object</b> = ttemp_selection.objects.filter(
            <b>user=self.request.user</b>
        ).first()
        return super().get_form(*args, **kwargs)

    def form_valid(self, form):
        form.instance.user = self.request.user
        return super().form_valid(form)

    def get_form_kwargs(self):
        kwargs = super(sasView, self).get_form_kwargs()
        kwargs['request'] = self.request
        return kwargs

然而,将用户作为字段包括在内是没有意义的,因为 - 如果我理解正确的话 - 您使用的是登录用户。通过包含它,您可以伪造一个 POST 请求,从而更改 不同 用户的帐户。您应该省略此字段:

class SelectAccountForm(forms.ModelForm):
    class Meta:
        model = ttemp_selection
        #                                        <i>no</i> user ↓
        fields = ['select_account', 'date_from', 'date_to']
    
    # …

Note: You can limit views to a class-based view to authenticated users with the LoginRequiredMixin mixin [Django-doc].