Доступ к данным сессии запроса DetailView в CreateView в django

Я пишу систему управления библиотеками на Django. Есть два вида, которые вызывают у меня затруднения.

В BookDetailsView перечислены подробные сведения о книге, такие как название, цена и т.д.

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)

В BookBorrowView я отображаю форму, в которой читатель может взять книгу. Два поля предустановлены (заемщики и книга), и я не хочу, чтобы пользователь мог их изменить. В настоящее время пользователь может выбирать из множества вариантов.


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

Ниже приведен снимок экрана формы, отображаемой BookBorrowView.

enter image description here

У меня два вопроса:

  1. Я передаю первичный ключ книги через request.session, чтобы иметь к нему доступ в BookBorrowView для предварительной установки названия книги в форме. Правильный ли это подход?

  2. Как можно предустановить два поля формы, которые не будут изменяться пользователем?

Я передаю первичный ключ книги через request.session, чтобы иметь к нему доступ в BookBorrowView для предварительной установки названия книги в форме. Правильный ли это подход?

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()),
]

Как сделать так, чтобы два поля формы были заданы и не изменялись пользователем?

Вы можете работать с пользовательским полем, которое таким образом отключает данные, например:

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']

и подключите его к 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']),
        }

Это также предотвратит подделку формы: если вы сделаете POST-запрос с разными значениями в качестве данных формы, то форма примет initial те,

Вернуться на верх