我有以下表格和模型:
class Book(models.Model):
name = models.CharField(max_length=128, null=True, blank=True)
author = models.CharField(max_length=128, null=True, blank=True)
borrower = models.ForeignKey('core.User')
class BookForm(forms.ModelForm)
class Meta:
model = Book
fields = ("name", "author", "borrower")
@login_required
def private(request):
if request.method == 'POST':
form = BookForm(request.POST)
if form.is_valid():
book = form.save(commit=False)
book.save()
else:
form = BookForm()
return render(request, 'borrow.html', {'form': form, })
该网站允许用户向自己的私人页面提交新书。当用户尝试提交同一用户之前提交过的图书时,就会发生问题。
验证应在哪里实施,如何进行?
-如果我选择以表单清洁方法进行验证,那么我将无法选择请求以查看其身份。
-如果我选择在视图中进行验证,那么如何在验证表单后使它无效?
答案 0 :(得分:0)
您可以通过几种方法执行此操作,但是我在下面列出了2种最简单的方法:
form.add_error(field, error)
messages
框架添加错误消息
方法1 :
在您看来,可以执行所需的验证,以及验证是否失败,即。用户尝试提交这本书两次,则可以使用(假设您的表单名为form
,因为它在您的代码中一样,title
是您要将错误消息添加到的字段,并且第二个参数是您要在该字段旁边显示的错误消息):
form.add_error('title', 'Book already taken out')
方法2 :
您可以进行验证,如果验证失败,则可以进行
messages.add_message(request, messages.WARNING, 'Book already taken out')
然后在模板中,您可以
<ul class="messages">
{% for message in messages %}
<li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li>
{% endfor %}
</ul>
此外,您可以检查是否message.tags == DEFAULT_MESSAGE_LEVELS.ERROR
,然后添加一个额外的类来将字体设置为红色文本,以便使用户更多地知道这是一个错误。
请确保添加
from django.contrib import messages
到您的进口清单。
有关更多信息,请参见 https://docs.djangoproject.com/en/2.1/ref/contrib/messages/。
答案 1 :(得分:0)
对我来说,保持视图简单总是更好的选择。
您可以在表单中使用clean方法,例如:
class BookForm(forms.ModelForm):
class Meta:
model = Book
fields = ("name", "author", "borrower")
def __init__(self, *args, **kwargs):
#add the request in the ModelForm
self.request = kwargs.pop('request', None)
#call the default super
super(BookForm, self).__init__(*args, **kwargs)
def clean(self):
#call the default clean method
cleaned_data = super(BookForm, self).clean()
#get the diffrents cleanned fields
name = cleaned_data.get('name')
author = cleaned_data.get('author')
#get the user from the request
borrower = self.request.user
#try to get the book submited by the user from the database
try:
Book.objects.get(name=name, author=author, borrower=borrower)
#if their is an error, that mean the book doesn't exist in the database at the moment
#so we can return the cleaned data
except Book.DoesNotExist:
return cleaned_data
#otherwise raise an error that could be display directly in the template in the non_field_error
else:
raise ValidationError(_('The borrower already have this book'), code='book_already_exist')
请注意,您的Form.clean()覆盖引发的任何错误都不会与任何特定字段相关联。它们进入一个特殊的“字段”(称为 all ),您可以根据需要通过non_field_errors()方法进行访问。如果要将错误附加到表单中的特定字段,则需要调用add_error()。