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].
我创建了一个 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].