Django阻止书籍提交两次

时间:2018-12-11 15:58:24

标签: django django-forms django-views

我有以下表格和模型:

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, })

该网站允许用户向自己的私人页面提交新书。当用户尝试提交同一用户之前提交过的图书时,就会发生问题。 验证应在哪里实施,如何进行?
-如果我选择以表单清洁方法进行验证,那么我将无法选择请求以查看其身份。
-如果我选择在视图中进行验证,那么如何在验证表单后使它无效?

2 个答案:

答案 0 :(得分:0)

您可以通过几种方法执行此操作,但是我在下面列出了2种最简单的方法:

  1. 使用form.add_error(field, error)
  2. 向表单字段添加错误
  3. 使用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()。