I am currently following Mozilla's Django tutorial ( https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/Forms ). The tutorial mostly shows how to create form using functions. I am trying to make the same function view work by using a generic class view (FormView). I am able to make most of the code to work except for 2 things. First one is that I can't seem to be able to save the due date. And, second one, is that I don't know how to access the model fields in my template using template variables.
Here is my form model from the forms.py file.
class RenewBookModelForm(ModelForm):
def clean_due_back(self):
data = self.cleaned_data['due_back']
# Check if a date is not in the past.
if data < datetime.date.today():
raise ValidationError(ugettext_lazy(
'Invalid date - renewal in past'))
# Check if a date is in the allowed range (+4 weeks from today).
if data > datetime.date.today() + datetime.timedelta(weeks=4):
raise ValidationError(ugettext_lazy(
'Invalid date - renewal more than 4 weeks ahead'))
# Remember to always return the cleaned data.
return data
class Meta:
model = BookInstance
fields = ['due_back']
labels = {'due_back': ugettext_lazy('New renewal date')}
help_texts = {'due_back': ugettext_lazy(
'Enter a date between now and 4 weeks (default 3).')}
The form model implemented as a function:
@permission_required('catalog.can_mark_returned')
def renew_book_lirarian(request, pk):
book_instance = get_object_or_404(BookInstance, pk=pk)
# If this is a POST request then process the Form data
if request.method == 'POST':
# Create a form instance and populate it with data from the request (binding):
form = RenewBookModelForm(request.POST)
# Chech if the form is valid
if form.is_valid():
# process that data in form.cleaned_data as required (here we just write to the model due_back field)
book_instance.due_back = form.cleaned_data['due_back']
book_instance.save()
# redirect to a new URL
return HttpResponseRedirect(reverse('all-borrowed'))
# If this is a GET (or any other method) create the default form.
else:
proposed_renewal_date = datetime.date.today() + datetime.timedelta(weeks=3)
form = RenewBookModelForm(initial={'due_back': proposed_renewal_date})
context = {
'form': form,
'book_instance': book_instance
}
return render(request, 'catalog/book_renew_librarian.html', context=context)
This is my class-based view from my views.py file:
class RenewBookLibrarian(LoginRequiredMixin, PermissionRequiredMixin, generic.FormView):
"""Generic class-based view for forms."""
template_name = 'catalog/book_renew_librarian.html'
permission_required = 'catalog.can_mark_returned'
form_class = RenewBookModelForm
success_url = reverse_lazy('all-borrowed')
def get_initial(self):
proposed_renewal_date = datetime.date.today() + datetime.timedelta(weeks=3)
initial = {'due_back': proposed_renewal_date}
return initial
And finally this is my template file where I wish to access the model fields:
{% extends 'base_generic.html' %}
{% block content %}
<h1>Renew: {{ book_instance.book.title }}</h1>
<p>Borrower: {{ book_instance.borrower }}</p>
<p {% if book_instance.is_overdue %} class="text-danger" {% endif %}>Due date: {{ book_instance.due_back }}</p>
<form action="" method="POST">
{% csrf_token %}
<table>
{{ form.as_table }}
</table>
<input type="submit" value="submit">
</form>
{% endblock %}
The book_instance variable in the template is not working, hence I would like to know how I can display fields from my BookInstance model.
To add book_instance
to the template context, you can override get_context_data
.
In the FormView
, instead of checking if form.is_valid()
, you override the form_valid
method (see the class based view docs for basic forms ).
class RenewBookLibrarian(LoginRequiredMixin, PermissionRequiredMixin, generic.FormView):
...
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['book_instance'] = get_object_or_404(BookInstance, pk=self.kwargs['pk'])
def form_valid(self, form):
book_instance = get_object_or_404(BookInstance, pk=self.kwargs['pk'])
book_instance.due_date = form.cleaned_data['due_date']
book_instance.save()
return super().form_valid(form) # will redirect to the success url
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.