I am writing a library management system in Django. There are two views that I am having a bit of a struggle.
The BookDetailsView lists the details of a Book such as title, price, etc.
class BookDetailsView(LoginRequiredMixin, DetailView):
model = Book
template_name = 'book_detail.html'
def get(self, request, *args, **kwargs):
response = super().get(request, *args, **kwargs)
request.session['book_pk'] = kwargs['pk']
return response
# used to mark book as read or unread
def post(self, request, *args, **kwargs):
if 'is_read' in request.POST:
book = Book.objects.get(pk=kwargs['pk'])
book.is_read = True
book.save()
return HttpResponseRedirect(self.request.path_info)
In the BookBorrowView, I display a form where the reader can borrow a book. Two fields are preset (borrowers and book), and I don't want the user to be able to change them. At the moment, the user can select among many options.
class BookBorrowView(LoginRequiredMixin, CreateView):
model = BookBorrowTransaction
template_name = 'book_borrow.html'
fields = ['book', 'borrowers', 'date_borrowed', 'to_return', ]
success_url = reverse_lazy('home')
def get_initial(self):
initial = super(BookBorrowView, self).get_initial()
initial['borrowers'] = get_object_or_404(CustomUser, email=self.request.user.email)
initial['book'] = get_object_or_404(Book, title=Book.objects.get(pk=self.request.session['book_pk']).title) # need the book id here
print(self.request.GET)
print(self.request.POST)
print(self.request.session['book_pk'])
return initial
The following is a screenshot of the form displayed by the BookBorrowView.
I have two questions:
I am passing the primary key for the book through request.session so I can access it in the BookBorrowView to preset the book's title in the form. Is this a good approach?
How can the two fields of the form be preset and unchanged by the user?
I am writing a library management system in Django. There are two views that I am having a bit of a struggle.
The BookDetailsView lists the details of a Book such as title, price, etc.
class BookDetailsView(LoginRequiredMixin, DetailView):
model = Book
template_name = 'book_detail.html'
def get(self, request, *args, **kwargs):
response = super().get(request, *args, **kwargs)
request.session['book_pk'] = kwargs['pk']
return response
# used to mark book as read or unread
def post(self, request, *args, **kwargs):
if 'is_read' in request.POST:
book = Book.objects.get(pk=kwargs['pk'])
book.is_read = True
book.save()
return HttpResponseRedirect(self.request.path_info)
In the BookBorrowView, I display a form where the reader can borrow a book. Two fields are preset (borrowers and book), and I don't want the user to be able to change them. At the moment, the user can select among many options.
class BookBorrowView(LoginRequiredMixin, CreateView):
model = BookBorrowTransaction
template_name = 'book_borrow.html'
fields = ['book', 'borrowers', 'date_borrowed', 'to_return', ]
success_url = reverse_lazy('home')
def get_initial(self):
initial = super(BookBorrowView, self).get_initial()
initial['borrowers'] = get_object_or_404(CustomUser, email=self.request.user.email)
initial['book'] = get_object_or_404(Book, title=Book.objects.get(pk=self.request.session['book_pk']).title) # need the book id here
print(self.request.GET)
print(self.request.POST)
print(self.request.session['book_pk'])
return initial
The following is a screenshot of the form displayed by the BookBorrowView.
I have two questions:
I am passing the primary key for the book through request.session so I can access it in the BookBorrowView to preset the book's title in the form. Is this a good approach?
How can the two fields of the form be preset and unchanged by the user?
1 Answer
Reset to default 2I am passing the primary key for the book through request.session so I can access it in the BookBorrowView to preset the book's title in the form. Is this a good approach?
I would say no. You usually pass it through a URL, this is more robust: it requires the variable to be set before you can trigger the view, since it is in the URL, and otherwise the path(…)
[Django-doc] will not "fire". Furtermore session variables make the approach stateful. It means that if the session_id
cookie expires a person will get a new session, and thus with new data. So while not very common, it is possible to first visit the book details, and when you want to borrow it, the session variable is expired.
so:
urlpatterns = [
path('<int:pk>', BookDetailsView.as_view()),
path('<int:book_id>/borrow', BookBorrowView.as_view()),
]
How can the two fields of the form be preset and unchanged by the user?
You can work with a custom field that thus disables the data, like:
class BookBorrowTransaction(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['book'].disabled = True
self.fields['borrowers'].disabled = True
class Meta:
model = BookBorrowTransaction
fields = ['book', 'borrowers', 'date_borrowed', 'to_return']
and plug it into the BookBorrowView
:
class BookBorrowView(LoginRequiredMixin, CreateView):
model = BookBorrowTransaction
template_name = 'book_borrow.html'
form_class = BookBorrowTransaction
success_url = reverse_lazy('home')
def get_initial(self):
return {
**super().get_initial(),
'borrowers': self.request.user,
'book': get_object_or_404(Book, pk=self.kwargs['book_id']),
}
This will also prevent the form being tampered with: if you make a POST request with different values as form data, the form will take the initial
ones.
BookBorrowTransaction
model? – willeM_ Van Onsem Commented Jan 22 at 17:16