这是我的 models.py。 请注意,对于容量模型:“年”、“月”、“员工”是唯一的。
class Employee(models.Model):
last_name = models.CharField('Nachname', max_length=200)
first_name = models.CharField('Vorname', max_length=200)
address = models.CharField('Strasse und Hausnummer', max_length=200)
zip_code = models.IntegerField('PLZ', default=4000)
place = models.CharField('Wohnort', max_length=200)
birth_date = models.DateField('Geburtsdatum')
entry_date = models.DateField('Startdatum')
email = models.CharField(max_length=200)
phone = models.CharField(max_length=15, blank=True)
ahv_no = models.CharField('AHV Nummer', max_length=200, blank=True)
HEBAMME = 'HEBAMME'
PFLEGEFACHFRAU = 'PFLEGEFACHFRAU'
JOB_CHOICES = [
(HEBAMME, 'Hebamme'),
(PFLEGEFACHFRAU, 'Pflegefachfrau'),
]
job = models.CharField(
max_length=20,
choices=JOB_CHOICES,
default=HEBAMME,
)
workload = models.IntegerField('Pensum', validators=[MaxValueValidator(100)], default=100)
active = models.BooleanField(default=True)
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
blank=True,
null=True,
on_delete=models.CASCADE
)
services = models.ManyToManyField(
'customers.Service',
default=1,
blank=True
)
def __str__(self):
return self.first_name + ' ' + self.last_name
class Capacity(models.Model):
employee = models.ForeignKey(
Employee,
blank=True,
null=True,
on_delete=models.CASCADE
)
number_wobe = models.IntegerField(
'Anzahl Wochenbett',
default=0
)
year_choices = (
(2023, '2023'),
(2024, '2024'),
(2025, '2025'),
)
month_choices = (
(1, 'Januar'),
(2, 'Februar'),
(3, 'März'),
(4, 'April'),
(5, 'Mai'),
(6, 'Juni'),
(7, 'Juli'),
(8, 'August'),
(9, 'September'),
(10, 'Oktober'),
(11, 'November'),
(12, 'Dezember'),
)
year = models.IntegerField(
'Jahr',
choices=year_choices)
month = models.IntegerField(
'Monat',
choices=month_choices)
class Meta:
unique_together = ('year', 'month', 'employee')
views.py 请注意,我的过滤器 kwargs 是年、月和员工(unique_together),要更新的项目是“number_wobe”。
def UpdateCreateCapacityView(request, year, month, employee_id):
if request.method == 'POST':
next = request.POST.get('next', '/')
form = CapacityForm(request.POST)
if form.is_valid():
capacity = form['number_wobe'].value()
cap, created = Capacity.objects.update_or_create(
year=year,
month=month,
employee=employee_id,
defaults={"number_wobe": capacity},
)
return HttpResponseRedirect(next)
else:
capacity = Capacity.objects.filter(year=year).filter(month=month).filter(employee=employee_id).values_list('number_wobe', flat=True)
for item in capacity:
capacity = item
form = CapacityForm(initial={'employee': employee_id, 'year': year, 'month': month, 'number_wobe': capacity})
return render(request,
'planning/add_capacity.html',
{'form': form})
add_capacity.html
{% extends 'dashboard/base.html' %}
{% load crispy_forms_tags %}
{% block title %}Kapazität verwalten{% endblock %}
{% block content %}
{% if user.is_authenticated %}
<h1 class="title is-2">Kapazität verwalten</h1>
<form action="" method="post" novalidate>
{% csrf_token %}
{{ form|crispy }}
<input type="hidden" name="next" value="{{ request.path }}">
<input type="submit" value="Submit">
</form>
{% else %}
<h3 class="title is-3 has-text-centered has-text-weight-light">Du musst eingeloggt sein, um diese Seite zu sehen:</h3>
<br>
<div class="columns is-centered">
<div class="colum is-half">
<a class="button has-text-centered is-rounded is-primary is-large" href="{% url 'accounts:login' %}">Login</a>
</div>
</div>
{% endif %}
{% endblock %}
问题: 提交表单时,我收到“已存在”错误。当使用 update_or_create() 时,我希望它只是更新对象(如果存在)。我(想我)已经根据 Django 文档使用了该函数(https://docs.djangoproject.com/en/4.2/ref/models/querysets/#update-or-create)。
虽然您没有显示您的
CapacityForm
,但我相信ModelForm
是您问题的根源,而不是您对update_or_create()
的使用。
当您调用
.is_valid()
的 ModelForm
方法时,它首先会验证您定义的表单,然后 然后 它会验证模型本身,如 Django 文档 中所述。这意味着,如果您提交具有现有年份、月份和员工的表单,则 is_valid()
函数将在到达 update_or_create()
方法之前抛出“已经存在”错误。您可以尝试使用断点进行验证,以显示表单在
is_valid()
调用后已经失效,或者在条件条件中使用打印语句来显示它从未被输入过。
我知道的两种处理方法是:
ModelForm.clean() 方法设置一个标志,使模型 验证步骤验证模型字段的唯一性 标记为 unique、unique_together 或 unique_for_date|month|year。
如果您想重写 clean() 方法并维护它 验证时,必须调用父类的clean()方法。
您可以查看 BaseModelForm 定义来亲自查看这个干净的方法,但您可以在您的CapacityForm中重写它,例如:
def clean(self):
self._validate_unique = False
return self.cleaned_data
这将跳过
is_valid()
调用的唯一验证,但请考虑在代码的其余部分中这是否可能导致使用表单的错误,并且它应该检查唯一性。
forms.Form
而不是 ModelForm
。然后它不会执行模型验证步骤。如果您的模型上有很多约束和验证逻辑,那么您也必须在表单字段上重复,这可能会很烦人。