Django 通用创建视图。我们可以添加条件来保存表单中的数据吗?
Django generic create view . Can we add conditions to save data from the form?
这就是我的代码的样子,我想向 Borrower create view 添加一些条件,例如 book returns 0 的库存方法,然后在创建新的时不要在字段中列出该书borrower 或者如果不可能至少在将 borrower 添加到那本书时抛出一些错误。
models.py:
class Book(models.Model):
id = models.UUIDField(primary_key=True, unique=True,
default=uuid.uuid4, editable=False)
title = models.CharField(max_length=200)
author = models.CharField(max_length=100)
summary = models.TextField(
max_length=1000, help_text="Enter a brief description of the book")
isbn = models.CharField('ISBN', max_length=13,
help_text='13 Character https://www.isbn-international.org/content/what-isbn')
genre = models.ManyToManyField(
Genre, help_text="Select a genre for this book")
language = models.ForeignKey(
'Language', on_delete=models.SET_NULL, null=True)
total_copies = models.IntegerField()
pic = models.ImageField(blank=True, null=True, upload_to='books')
def stock(self):
total_copies = self.total_copies
available_copies = total_copies - \
Borrower.objects.filter(book=self).count()
if available_copies > 0:
return available_copies
else:
return 0
def __str__(self):
return self.title
class Borrower(models.Model):
id = models.UUIDField(primary_key=True, unique=True,
default=uuid.uuid4, editable=False)
student = models.ForeignKey('Account', on_delete=models.CASCADE)
book = models.ForeignKey('Book', on_delete=models.CASCADE)
issue_date = models.DateField(
null=True, blank=True, help_text='YYYY-MM-DD', default=date.today)
return_date = models.DateField(
null=True, blank=True, help_text='YYYY-MM-DD')
def __str__(self):
return self.student.name.title()+" borrowed "+self.book.title.title()
def fine(self):
today = date.today()
fine = 0
if self.return_date <= today:
fine += 5 * (today - self.return_date).days
return fine
views.py:
class BorrowerView(LoginRequiredMixin, ListView):
model=Borrower
context_object_name='borrowers'
template_name = 'library/borrower_list.html'
def get_context_data(self, **kwargs):
context=super().get_context_data(**kwargs)
if self.request.user.is_admin or self.request.user.is_superuser:
context['borrowers']=context['borrowers']
else:
context['borrowers']=context['borrowers'].filter(student = self.request.user.id)
return context
class BorrowerCreate(LoginRequiredMixin, UserAccessMixin, CreateView):
model=Borrower
permission_required= 'borrowers.add_borrowers'
fields='__all__'
success_url=reverse_lazy('library:borrower-list')
def form_valid(self, form):
form.instance.user=self.request.user
return super(BorrowerCreate, self).form_valid(form)
class BorrowerDetail(LoginRequiredMixin, DetailView):
model=Borrower()
context_object_name='borrower'
template_name='library/borrower.html'
class Book(models.Model):
id = models.UUIDField(primary_key=True, unique=True,
default=uuid.uuid4, editable=False)
title = models.CharField(max_length=200)
author = models.CharField(max_length=100)
summary = models.TextField(
max_length=1000, help_text="Enter a brief description of the book")
isbn = models.CharField('ISBN', max_length=13,
help_text='13 Character https://www.isbn-international.org/content/what-isbn')
genre = models.ManyToManyField(
Genre, help_text="Select a genre for this book")
language = models.ForeignKey(
'Language', on_delete=models.SET_NULL, null=True)
total_copies = models.IntegerField()
pic = models.ImageField(blank=True, null=True, upload_to='books')
#new, use this to keep track of available books
available_copies = models.IntegerField()
def __str__(self):
return self.title
当任何借阅者借出本书的副本时,您将从总副本中减去它。
class BorrowerCreate(LoginRequiredMixin, UserAccessMixin, CreateView):
model=Borrower
permission_required= 'borrowers.add_borrowers'
fields='__all__'
success_url=reverse_lazy('library:borrower-list')
#remember to get the object using slug or 404
def form_valid(self, form):
instance = form.save(commit=False)
instance.user = self.request.user
book = Book.objects.get(id=instance.book.id)
#get the book id from the form and check if the book is still available, then subtract.
if book.available_copies > 0:
book.available_copies -= 1
book.save()
instance.save()
message.success(self.request, _("successful")
message.error(self.request, _("Book not in stock")
return super(BorrowerCreate, self).form_valid(form)
如果用户 return 这本书并单击 returned。您可以通过添加到可用副本来执行类似的操作。
这不是解决方案,您可以使用同时处理借用和 return 的方法编写胖模型。像这样
def borrow(self):
self.available_copies -= 1
def returned(self):
self.available_copies += 1
您可以在不同的视图中调用这两个方法,或者定义一个调用它们的信号 pre_save
是:
与其定义一个名为 stock 的新方法,不如将 stock 添加为字段而不是进行数据库查询。
第二名:
在同一个 class 中调用 class 并不是在 class.
中进行查询的最佳方式
第三:
添加对象的同时添加条件,需要像这样重写对象的保存方法
def save(self, *args, **kwargs):
# do_something() here.....
# then
return super().save(*args, **kwargs)
以上代码将使您能够在保存对象之前执行任何操作。
另一种方法是在 form_valid 函数中执行此操作。
def form_valid(self, form):
instance = form.save(commit=False)
# commit = False will make sure that the form is not saved
# then you can now query the database and check conditions like
if Borrower.object.all().count() > 0:
instance.save()
messages.success(self.request, _("saved successfully")
else:
messages.error(self.request, _("Error")
return redirect("URL")
这就是我的代码的样子,我想向 Borrower create view 添加一些条件,例如 book returns 0 的库存方法,然后在创建新的时不要在字段中列出该书borrower 或者如果不可能至少在将 borrower 添加到那本书时抛出一些错误。
models.py:
class Book(models.Model):
id = models.UUIDField(primary_key=True, unique=True,
default=uuid.uuid4, editable=False)
title = models.CharField(max_length=200)
author = models.CharField(max_length=100)
summary = models.TextField(
max_length=1000, help_text="Enter a brief description of the book")
isbn = models.CharField('ISBN', max_length=13,
help_text='13 Character https://www.isbn-international.org/content/what-isbn')
genre = models.ManyToManyField(
Genre, help_text="Select a genre for this book")
language = models.ForeignKey(
'Language', on_delete=models.SET_NULL, null=True)
total_copies = models.IntegerField()
pic = models.ImageField(blank=True, null=True, upload_to='books')
def stock(self):
total_copies = self.total_copies
available_copies = total_copies - \
Borrower.objects.filter(book=self).count()
if available_copies > 0:
return available_copies
else:
return 0
def __str__(self):
return self.title
class Borrower(models.Model):
id = models.UUIDField(primary_key=True, unique=True,
default=uuid.uuid4, editable=False)
student = models.ForeignKey('Account', on_delete=models.CASCADE)
book = models.ForeignKey('Book', on_delete=models.CASCADE)
issue_date = models.DateField(
null=True, blank=True, help_text='YYYY-MM-DD', default=date.today)
return_date = models.DateField(
null=True, blank=True, help_text='YYYY-MM-DD')
def __str__(self):
return self.student.name.title()+" borrowed "+self.book.title.title()
def fine(self):
today = date.today()
fine = 0
if self.return_date <= today:
fine += 5 * (today - self.return_date).days
return fine
views.py:
class BorrowerView(LoginRequiredMixin, ListView):
model=Borrower
context_object_name='borrowers'
template_name = 'library/borrower_list.html'
def get_context_data(self, **kwargs):
context=super().get_context_data(**kwargs)
if self.request.user.is_admin or self.request.user.is_superuser:
context['borrowers']=context['borrowers']
else:
context['borrowers']=context['borrowers'].filter(student = self.request.user.id)
return context
class BorrowerCreate(LoginRequiredMixin, UserAccessMixin, CreateView):
model=Borrower
permission_required= 'borrowers.add_borrowers'
fields='__all__'
success_url=reverse_lazy('library:borrower-list')
def form_valid(self, form):
form.instance.user=self.request.user
return super(BorrowerCreate, self).form_valid(form)
class BorrowerDetail(LoginRequiredMixin, DetailView):
model=Borrower()
context_object_name='borrower'
template_name='library/borrower.html'
class Book(models.Model):
id = models.UUIDField(primary_key=True, unique=True,
default=uuid.uuid4, editable=False)
title = models.CharField(max_length=200)
author = models.CharField(max_length=100)
summary = models.TextField(
max_length=1000, help_text="Enter a brief description of the book")
isbn = models.CharField('ISBN', max_length=13,
help_text='13 Character https://www.isbn-international.org/content/what-isbn')
genre = models.ManyToManyField(
Genre, help_text="Select a genre for this book")
language = models.ForeignKey(
'Language', on_delete=models.SET_NULL, null=True)
total_copies = models.IntegerField()
pic = models.ImageField(blank=True, null=True, upload_to='books')
#new, use this to keep track of available books
available_copies = models.IntegerField()
def __str__(self):
return self.title
当任何借阅者借出本书的副本时,您将从总副本中减去它。
class BorrowerCreate(LoginRequiredMixin, UserAccessMixin, CreateView):
model=Borrower
permission_required= 'borrowers.add_borrowers'
fields='__all__'
success_url=reverse_lazy('library:borrower-list')
#remember to get the object using slug or 404
def form_valid(self, form):
instance = form.save(commit=False)
instance.user = self.request.user
book = Book.objects.get(id=instance.book.id)
#get the book id from the form and check if the book is still available, then subtract.
if book.available_copies > 0:
book.available_copies -= 1
book.save()
instance.save()
message.success(self.request, _("successful")
message.error(self.request, _("Book not in stock")
return super(BorrowerCreate, self).form_valid(form)
如果用户 return 这本书并单击 returned。您可以通过添加到可用副本来执行类似的操作。
这不是解决方案,您可以使用同时处理借用和 return 的方法编写胖模型。像这样
def borrow(self):
self.available_copies -= 1
def returned(self):
self.available_copies += 1
您可以在不同的视图中调用这两个方法,或者定义一个调用它们的信号 pre_save
是: 与其定义一个名为 stock 的新方法,不如将 stock 添加为字段而不是进行数据库查询。
第二名: 在同一个 class 中调用 class 并不是在 class.
中进行查询的最佳方式第三: 添加对象的同时添加条件,需要像这样重写对象的保存方法
def save(self, *args, **kwargs):
# do_something() here.....
# then
return super().save(*args, **kwargs)
以上代码将使您能够在保存对象之前执行任何操作。
另一种方法是在 form_valid 函数中执行此操作。
def form_valid(self, form):
instance = form.save(commit=False)
# commit = False will make sure that the form is not saved
# then you can now query the database and check conditions like
if Borrower.object.all().count() > 0:
instance.save()
messages.success(self.request, _("saved successfully")
else:
messages.error(self.request, _("Error")
return redirect("URL")