英文:
Django - Function Based View update record - error - Record Already exists
问题
MODELS.PY:
class Currency(models.Model):
currency_code = models.CharField(max_length=3)
currency_name = models.CharField(max_length=80)
class Meta:
verbose_name_plural = "货币"
def __str__(self):
return self.currency_code
class Forex(models.Model):
currency_code = models.ForeignKey(Currency, on_delete=models.CASCADE)
forex_rate = models.DecimalField(max_digits=8, decimal_places=4)
last_updated_on = models.DateTimeField(auto_now=True)
class Meta:
verbose_name_plural = "外汇汇率"
def __str__(self):
return self.currency_code.currency_code
FORMS.PY:
class UpperCase(forms.CharField):
def to_python(self, value):
if value:
return value.upper()
class CurrencyForm(forms.ModelForm):
currency_code = UpperCase(
label="货币代码",
min_length=3,
max_length=3,
error_messages={"required": "货币代码不能为空"},
required=True,
)
currency_name = UpperCase(
label="货币名称",
min_length=5,
max_length=80,
error_messages={"required": "货币名称不能为空"},
required=True,
)
class Meta:
model = Currency
fields = ["currency_code", "currency_name"]
# 检查重复的第二种方法正常工作
def clean_currency_code(self):
currency_code = self.cleaned_data.get("currency_code")
if Currency.objects.filter(currency_code=currency_code).exists():
raise forms.ValidationError(
"货币代码 {} 已经存在!".format(currency_code)
)
return currency_code
VIEWS.PY:
def currency_edit(request, id):
obj = Currency.objects.get(id=id)
if request.method == 'POST':
form = CurrencyForm(data=request.POST, instance=obj)
if form.is_valid():
form.save()
return redirect('currency_list_page')
else:
form = CurrencyForm(instance=obj)
return render(request, 'main/currency_edit.html', locals())
URLS.PY:
urlpatterns = [
path('currency_list/', views.currency_list, name='currency_list_page'),
path('currency_add/', views.currency_add, name='currency_add_page'),
path('currency_edit/<int:id>/', views.currency_edit, name='currency_edit_page'),
path('currency_delete/<int:id>/', views.currency_delete, name='currency_delete_page'),
]
CURRENCY_EDIT.HTML:
<form action="{% url 'currency_edit_page' id %}" class="row g-3 mt-3" method="POST" novalidate>
{% csrf_token %}
<div class="row">
{{id}}
{{form.currency_code}}
{{form.currency_name}}
</div>
<div class="col-12">
<button class="btn btn-success" type="submit"><i class="fa-solid fa-floppy-disk"></i> 保存</button>
<a class="btn btn-danger" href="{% url 'currency_list_page' %}">
<i class="fa-solid fa-reply"></i> 取消</a>
</div>
</form>
英文:
I am trying to update an existing record using Django 4.2, Crispy Forms, and Function Based View. The field currency_code in the table Currency is used as a ForeignKey in another table(s). I cannot update the currency record without getting the message that the record already exists. What am I doing wrong and where? Below is the code and screenshot:
MODELS.PY:
class Currency(models.Model):
currency_code = models.CharField(max_length=3)
currency_name = models.CharField(max_length=80)
class Meta:
verbose_name_plural = "Currencies"
def __str__(self):
return self.currency_code
class Forex(models.Model):
currency_code = models.ForeignKey(Currency, on_delete=models.CASCADE)
forex_rate = models.DecimalField(max_digits=8, decimal_places=4)
last_updated_on = models.DateTimeField(auto_now=True)
class Meta:
verbose_name_plural = "Forex Rates"
def __str__(self):
return self.currency_code.currency_code
FORMS.PY:
class UpperCase(forms.CharField):
def to_python(self, value):
if value:
return value.upper()
class CurrencyForm(forms.ModelForm):
currency_code = UpperCase(
label="Currency Code",
min_length=3,
max_length=3,
error_messages={"required": "Currency Code Cannot Be Blank"},
required=True,
)
currency_name = UpperCase(
label="Currency Name",
min_length=5,
max_length=80,
error_messages={"required": "Currency Name Cannot Be Blank"},
required=True,
)
class Meta:
model = Currency
fields = ["currency_code", "currency_name"]
# Method 2 for checking duplicates working ok
def clean_currency_code(self):
currency_code = self.cleaned_data.get("currency_code")
if Currency.objects.filter(currency_code=currency_code).exists():
raise forms.ValidationError(
"Currency Code {} already exists!".format(currency_code)
)
return currency_code
VIEWS.PY:
def currency_edit(request, id):
obj = Currency.objects.get(id=id)
if request.method == 'POST':
form = CurrencyForm(data=request.POST, instance=obj)
if form.is_valid():
form.save()
return redirect('currency_list_page')
else:
form = CurrencyForm(instance=obj)
return render(request, 'main/currency_edit.html', locals())
URLS.PY:
urlpatterns = [
path('currency_list/', views.currency_list, name='currency_list_page'),
path('currency_add/', views.currency_add, name='currency_add_page'),
path('currency_edit/<int:id>', views.currency_edit, name='currency_edit_page'),
path('currency_delete/<int:id>', views.currency_delete, name='currency_delete_page'),
]
CURRENCY_EDIT.HTML
<form action="{% url 'currency_edit_page' id %}" class="row g-3 mt-3" method="POST" novalidate>
{% csrf_token %}
<div class="row">
{{id}}
{{form.currency_code}}
{{form.currency_name}}
</div>
<div class="col-12">
<button class="btn btn-success" type="submit"><i
class="fa-solid fa-floppy-disk"></i> Save
</button>
<a class="btn btn-danger" href="{% url 'currency_list_page' %}">
<i class="fa-solid fa-reply"></i> Cancel</a>
</div>
</form>
答案1
得分: 1
抱歉,看起来我错过了你的表单clean_currency_code
上的缩进(下次提问时要小心),这就是问题所在。
当您尝试编辑时,表单将引发您设置的验证。因为该函数将在.is_valid
调用上运行,您还在编辑view
上调用它,当然,如果您试图编辑第二个字段currency_name
,那么code
将不会更改,因此仍然存在。
如果currency_code
字段应该是唯一的,请在您的模型上使用唯一字段选项,让框架为您工作:
models.py
class Currency(models.Model):
currency_code = models.CharField(max_length=3, unique=True)
currency_name = models.CharField(max_length=80)
forms.py
class UpperCase(forms.CharField):
...
class CurrencyForm(forms.ModelForm):
class Meta:
model = Currency
fields = ["currency_code", "currency_name"]
currency_code = UpperCase(
label="Currency Code",
min_length=3,
max_length=3,
error_messages={"required": "Currency Code Cannot Be Blank"},
required=True,
)
currency_name = UpperCase(
label="Currency Name",
min_length=5,
max_length=80,
error_messages={"required": "Currency Name Cannot Be Blank"},
required=True,
)
英文:
Sorry, it seems that I missed indentation on your form clean_currency_code
(careful with that next time asking a question), there is where the problem lies.
When you try to edit, form will raise the validation you set up. Because the function will run on .is_valid
calls, which you also call on edit view
and of course if you are trying to edit the second field currency_name
then the code
will not change and thus exists.
If currency_code
field is supposed to be unique, then use the unique field option on your model and let the framework work for you:
models.py
class Currency(models.Model):
currency_code = models.CharField(max_length=3, unique=True)
currency_name = models.CharField(max_length=80)
forms.py
class UpperCase(forms.CharField):
...
class CurrencyForm(forms.ModelForm):
class Meta:
model = Currency
fields = ["currency_code", "currency_name"]
currency_code = UpperCase(
label="Currency Code",
min_length=3,
max_length=3,
error_messages={"required": "Currency Code Cannot Be Blank"},
required=True,
)
currency_name = UpperCase(
label="Currency Name",
min_length=5,
max_length=80,
error_messages={"required": "Currency Name Cannot Be Blank"},
required=True,
)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论