Skip to content

Django: Create, Update, Delete rodinių klasės

DonatasNoreika edited this page Oct 14, 2021 · 54 revisions

Create, Update, Delete rodinių klasės

ListView klasė

Dėmesio: perdaryti bookinstance klasę, kad pk būtų standartinis. Arba naudoti urlpatternuose str:pk arba uuid:pk, o viewsuose user_books.html href attributuose nurodyti bookinst.pk :)

Iš pradžių sukuriame (patobuliname jau įprastą ListView). Tam, kad šį puslapį galėtų peržiūrėti tik prisijungę vartotojai, paveldime LoginRequiredMixin. Faile library/views:

from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import ListView

class LoanedBooksByUserListView(LoginRequiredMixin, ListView):
    model = BookInstance
    context_object_name = 'books'
    template_name = 'user_books.html'
    paginate_by = 10

    def get_queryset(self):
        return BookInstance.objects.filter(reader=self.request.user).order_by('due_back')

Sukuriame path, faile library/urls:

path('mybooks/', views.LoanedBooksByUserListView.as_view(), name='my-borrowed'),

Sukuriame html, faile user_books.html:

{% extends "base.html" %}

{% block content %}
    <h1>Mano paimtos knygos</h1>
    {% if books %}
        {% for bookinst in books %}
    <hr>
        <ul>

        <img class="rounded-circle" src="{{bookinst.reader.profilis.nuotrauka.url}}">
        <li><strong class="{% if bookinst.is_overdue %}text-danger{% endif %}">Pavadinimas: {{bookinst.book.title}}</strong></li>
        <li><strong>Gražinimo terminas:</strong> {{bookinst.due_back}}</li>
        <br/>
        <a class="btn btn-primary" href="{{ bookinst.pk }}" role="button">Peržiūrėti</a>
      </li>

    </ul>
{% endfor %}
    {% else %}
      <p>There are no books borrowed.</p>
    {% endif %}
{% endblock %}

DetailView klasė

from django.views.generic import (
    ListView,
    DetailView,
)

class BookByUserDetailView(LoginRequiredMixin, DetailView):
    model = BookInstance
    template_name = 'user_book.html'

Sukuriame path, faile library/urls:

path('mybooks/<int:pk>', views.BookByUserDetailView.as_view(), name='my-book'),

Sukuriame html. Jei objekto pavadinimas nenurodytas, jo laukus pasiekiame per object.. Faile user_book.html:

{% extends "base.html" %}

{% block content %}
    <h1>Mano paimta knyga:</h1>
    <hr>
        <ul>
        <img class="rounded-circle" src="{{object.reader.profilis.nuotrauka.url}}">
        <li><strong class="{% if object.is_overdue %}text-danger{% endif %}">Pavadinimas: {{object.book.title}}</strong></li>
        <li><strong>Gražinimo terminas:</strong> {{object.due_back}}</li>
        <br/>
      </li>
    </ul>
{% endblock %}

CreateView klasė

from django.views.generic import (
    ListView,
    DetailView,
    CreateView,
)

class BookByUserCreateView(LoginRequiredMixin, CreateView):
    model = BookInstance
    fields = ['book', 'due_back']
    success_url = "/library/mybooks/"
    template_name = 'user_book_form.html'

    def form_valid(self, form):
        form.instance.reader = self.request.user
        return super().form_valid(form)

Sukuriame path, faile library/urls:

path('mybooks/new', views.BookByUserCreateView.as_view(), name='my-borrowed-new'),

Prie knygos egzemplioriaus pridedame metodą:

    def get_absolute_url(self):
        """Nurodo konkretaus aprašymo galinį adresą"""
        return reverse('book-detail', args=[str(self.id)])

Sukuriame html, faile user_book_form.html:

{% extends "base.html" %}
{% load crispy_forms_tags %}
{% block content %}
    <div class="content-section">
    <form method="POST">
        {% csrf_token %}
        <fieldset class="form-group">
            <legend class="border-bottom mb-4">Naujas knygos egzempliorius</legend>
            {{ form|crispy }}
        </fieldset>
        <div class="form-group">
            <button class="btn btn-outline-info" type="submit">Išsaugoti</button>
        </div>
    </form>
    </div>
{% endblock content %}

Įdedame į savo meniu naują punktą, faile base.html:

<li class="nav-item"><a class="nav-link" href="{% url 'my-borrowed-new'%}?next=/library">{% trans "New" %}</a></li>

PAPILDOMAI:

Jei CreateView view'e prireiktų į formą įdėti kintamąjį (id lauką) iš URL adreso, galime padaryti pavyzdžiui taip:

def form_valid(self, form):
    form.instance.reader = User.objects.get(pk=self.kwargs['pk'])
    return super().form_valid(form)    

UpdateView klasė

Kad knygos įrašą leistų atnaujinti tik tam vartotojui, kuris yra nurodytas jos reader lauke, paveldime UserPassesTestMixin ir perrašome metodą test_func, kuris gražina True tik tuomet, kai reader laukas sutampa su prisijungusiu vartotoju.

from django.contrib.auth.mixins import UserPassesTestMixin

from django.views.generic import (
    ListView,
    DetailView,
    CreateView,
    UpdateView,
)

class BookByUserUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
    model = BookInstance
    fields = ['book', 'due_back']
    success_url = "/library/mybooks/"
    template_name = 'user_book_form.html'

    def form_valid(self, form):
        form.instance.reader = self.request.user
        return super().form_valid(form)

    def test_func(self):
        book = self.get_object()
        return self.request.user == book.reader

Sukuriame path, faile library/urls:

    path('mybooks/<int:pk>/update', views.BookByUserUpdateView.as_view(), name='my-book-update'),

Įdedame atnaujinimo nuorodą į failą user_book.html:

        <li><strong>Gražinimo terminas:</strong> {{object.due_back}}</li>
            {% if object.reader == user %}
            <div>
                <a class="btn btn-secondary btn-sm mt-1 mb-1" href="{% url 'my-book-update' object.id %}">Redaguoti</a>
            </div>
            {% endif %}

DeleteView klasė

from django.views.generic import (
    ListView,
    DetailView,
    CreateView,
    UpdateView,
    DeleteView,
)

class BookByUserDeleteView(LoginRequiredMixin, UserPassesTestMixin, DeleteView):
    model = BookInstance
    success_url = "/library/mybooks/"
    template_name = 'user_book_delete.html'

    def test_func(self):
        book = self.get_object()
        return self.request.user == book.reader

Sukuriame path, faile library/urls:

path('mybooks/<int:pk>/delete', views.BookByUserDeleteView.as_view(), name='my-book-delete'),

Sukuriame html, faile user_book_delete.html:

{% extends "base.html" %}
{% load crispy_forms_tags %}
{% block content %}
    <div class="content-section">
    <form method="POST">
        {% csrf_token %}
        <fieldset class="form-group">
            <legend class="border-bottom mb-4">Ištrinti knygą</legend>
            <h2>Ar tikrai norite ištrinti knygą {{ object.uuid }}?</h2>
        </fieldset>
        <div class="form-group">
            <button class="btn btn-outline-danger" type="submit">Taip, ištrinti</button>
            <a class="btn btn-outline-secondary" href="{% url 'my-book' object.id %}">Atšaukti</a>
        </div>
    </form>
    </div>
{% endblock content %}

Įdedame trynimo nuorodą į failą user_book.html:

        <li><strong>Gražinimo terminas:</strong> {{object.due_back}}</li>
            {% if object.reader == user %}
            <div>
                <a class="btn btn-secondary btn-sm mt-1 mb-1" href="{% url 'my-book-update' object.id %}">Redaguoti</a>
                <a class="btn btn-danger btn-sm mt-1 mb-1" href="{% url 'my-book-delete' object.id %}">Ištrinti</a>
            </div>
            {% endif %}

Užduotis

Tęsti kurti Django užduotį – Autoservisas:

  • Jei reikia, perdaryti vartotojo užsakymų puslapius į ListView ir DetailView klases.
  • Padaryti, kad prisijungęs vartotojas galėtų kurti naujus užsakymus (be eilučių, tik pasirinkęs automobilį ir terminą). Panaudoti CreateView
  • Padaryti, kad prisijungęs vartotojas galėtų redaguoti savo užsakymus. Panaudoti UpdateView
  • Padaryti, kad prisijungęs vartotojas galėtų ištrinti savo užsakymus. Panaudoti DeleteView

Atsakymas

Dekoratoriai

Iteratoriai ir generatoriai

RegEx

Pillow

Email

NumPy

Pandas

Seaborn

Mašininis mokymasis

Requests, JSON, API

Web Scraping (Beautiful Soup)

Duomenų bazės

Flask

Django

Django REST

Odoo

Linux

Pabaigimo užduotis: savo programos kūrimas

Clone this wiki locally