Django: Как назначить кнопку для приема информации и сохранения()

Есть ли способ для кнопки сделать следующее: когда пользователь нажимает кнопку, она берет user.username текущего пользователя и автоматически заполняет форму BookInstance из models.py и сохраняет ее в базе данных.

From models.py :

class BookInstance(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    book = models.ForeignKey("Book", on_delete=models.RESTRICT, null=True)
    imprint = models.CharField(max_length=200, blank=True, null=True)
    due_back = models.DateField(blank=True, null=True)
    borrower = models.ForeignKey(
        User, on_delete=models.SET_NULL, blank=True, null=True)

    LOAN_STATUS = (
        ('m', 'Maintenance'),
        ('o', 'On Loan'),
        ('a', 'Available'),
        ('r', 'Reserved')
    )

    status = models.CharField(
        max_length=1, choices=LOAN_STATUS, blank=True, default='a')

    class Meta:
        ordering = ['due_back']

    def __str__(self):
        return f'{self.id} - {self.book.title}'

    def get_absolute_url(self):
        return reverse("catalog:book_list")
class Book(models.Model):

    title = models.CharField(max_length=50)
    author = models.ForeignKey(
        'Author', on_delete=models.SET_NULL, null=True)
    summary = models.TextField(
        max_length=500, help_text="Enter brief description")
    isbn = models.CharField('ISBN', max_length=13, unique=True)
    genre = models.ManyToManyField(Genre, help_text="Select genre")

    language = models.ForeignKey(
        "Language", on_delete=models.SET_NULL, null=True)

    def __str__(self):
        return self.title

    def get_absolute_url(self):
        return reverse("catalog:book_detail", kwargs={"pk": self.pk})

Это мое от моего views.py :

def borrowBook(request, pk):

    context = {
        'book_instance': BookInstance.objects.all()
    }

    success_url = reverse_lazy('catalog:index')
    if request.method == "POST":
        form = BorrowForm(request.POST or None)
        if form.is_valid():
            book_instance.id = BookInstance.objects.get(pk=pk)
            book_instance.book = BookInstance.objects.get(book=book)
            book_instance.borrower = request.user
            book_instance.status = 'o'
            book_borrowed_count = BookInstance.objects.filter(
                owner=request.user).count()
            if book_borrowed_count < 4:
                book_instance = form.save(commit=False)
                book_instance.save()
            else:
                print("Maximum limit reached!")
            return redirect('catalog:index')

    return render(request, 'catalog/book_detail.html', {'form': form})

вот из моего BorrowForm из forms.py :

class BorrowForm(forms.ModelForm):
    class Meta:
        model = BookInstance
        fields = '__all__'

вот мое от моего urls.py :

path("book_list/book/<int:pk>/borrow", views.borrowBook, name="borrowBook"),

Я также попробовал использовать CBV здесь:

class BorrowBookView(PermissionRequiredMixin, CreateView):
    permission_required = 'login'
    model = BookInstance
    fields = '__all__'
    template_name = 'catalog/borrow_form.html'
    success_url = reverse_lazy('catalog:index')

    def post(self, request, *args, **kwargs):
        book_instance.id = BookInstance.objects.get(pk=pk)
        book_instance.book = BookInstance.objects.get(book=book)
        book_instance.borrower = request.user
        book_instance.status = 'o'
        book_instance = form.save(commit=False)
        book_instance.save()

CBV путь от urls.py :

path("book_list/book/<int:pk>/borrow/",
         views.BorrowBookView.as_view(), name="book_borrow"),

Вот как я реализовал кнопку, используя предложения отсюда:

                <form action="#" method="post">
                    {% csrf_token %}
                    <button 
                        type="submit" 
                        class="btn btn-dark flex-shrink-0 " 
                        value="{{ book.id }}">Borrow
                    </button>

но когда я нажимаю, кажется, что ничего не сохраняется в базе данных и просто всплывают ошибки, хотя я могу реализовать кнопку или функцию из моих представлений неправильно. Спасибо и признателен за любую оказанную помощь.

Для этого вам не нужен Django form. Формы обычно используются, когда вы хотите создать объект или отредактировать его поля (как на странице администратора). В то время как здесь user не редактирует и не создает объект (книгу), а заимствует его.

По сути, нам просто нужно перечислить все доступные экземпляры книг (status='a') и иметь кнопку для "заимствования". Действие заимствования заключается в обновлении status до 'r' или 'o' и обновлении заемщика до текущего user, который гарантированно существует внутри объекта request по LoginRequiredMixin

views.py

from django.contrib.auth.mixins import LoginRequiredMixin
from django.views import View
from django.contrib import messages
from django.urls import reverse
from django.http import HttpResponseRedirect
from django.shortcuts import get_object_or_404

from .models import BookInstance

class BorrowBook(LoginRequiredMixin, View):
    def get(self, request, *args, **kwargs):
        book_id = kwargs['pk']
        available_books = BookInstance.objects.filter(book__pk=book_id, status='a')
        return render(request, 'borrow_book.html', {'available_books': available_books})


    def post(self, request, *args , **kwargs):
        book_instance_id = request.POST['id']
        obj = get_object_or_404(BookInstance, id=book_instance_id)
        obj.status = 'r'
        obj.borrower = request.user
        # Maybe also update due_back data
        # obj.due_back = ...
        obj.save()
        messages.success(request, "Your book is reserved.")
        # I used the redirection to the same template
        # But you probably want to send the user somewhere else
        return HttpResponseRedirect(reverse('core:borrow-book', kwargs={'pk': 1}))

borrow_book.html

{% extends 'base.html' %}

{% block content %}
    {% if messages %}
    <ul class="messages">
        {% for message in messages %}
        <li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li>
        {% endfor %}
    </ul>
    {% endif %}

    {% for instance in available_books %}
    <form action="{% url 'core:borrow-book' instance.book.id %}" method="POST">
        {% csrf_token %}
        <input type="hidden" name="id" value="{{instance.id}}">
        <p>{{instance.book}}</p>
        <p>{{instance.book.language.name}}</p>
        <input type="submit" value="Borrow this book.">
    </form>
        
    {% endfor %}
{% endblock content %}

urls.py

from django.urls import path
from core import views

app_name = 'core'

urlpatterns = [
    path("book_list/book/<int:pk>/borrow/", views.BorrowBook.as_view(), name="borrow-book"),
]
Вернуться на верх