<repo_name>MariangelaC/biblioteca<file_sep>/applications/libro/admin.py
from django.contrib import admin

from .models import Categoria, Libro

admin.site.register(Categoria)
admin.site.register(Libro)
<file_sep>/applications/libro/urls.py
from django.contrib import admin
from django.urls import path

from . import views

urlpatterns = [
    path(
        'libros/', 
        views.ListLibros.as_view(), 
        name="libros"
    ),
    path(
        'libros-2/', 
        views.ListLibros2.as_view(), 
        name="libros2"
    ),
    path(
        'libros-trg/', 
        views.ListLibrosTrg.as_view(), 
        name="libros-trg"
    ),
    path(
        'libro-detalle/<pk>/', 
        views.LibroDetailView.as_view(), 
        name="libro-detalle"
    ),
]<file_sep>/applications/lector/admin.py
from django.contrib import admin

from .models import Lector, Prestamo

admin.site.register(Prestamo)

admin.site.register(Lector)
<file_sep>/applications/libro/managers.py
import datetime

from django.db import models

from django.db.models import Q
from django.contrib.postgres.search import TrigramSimilarity


class LibroManager(models.Manager):
    """ managers para el modelo autor """

    def listar_libros(self, kword):

        resultado = self.filter(
            titulo__icontains=kword,
            fecha__range=('2000-01-01', '2010-01-01')
        )

        return resultado
    
    def listar_libros_trg(self, kword):
        
        if kword:
            resultado = self.filter(
                titulo__trigram_similar=kword,
            )
            return resultado
        else:
            return self.all()[:10]

    
    def listar_libros2(self, kword, fecah1, fecha2):

        date1 = datetime.datetime.strptime(fecah1, "%Y-%m-%d").date()
        date2 = datetime.datetime.strptime(fecha2, "%Y-%m-%d").date()


        resultado = self.filter(
            titulo__icontains=kword,
            fecha__range=(date1, date2)
        )

        return resultado

    def listar_libros_categoria(self, categoria):

        return self.filter(
            categoria__id=categoria
        ).order_by('titulo')
    
    def add_autor_libro(self, libro_id, autor):
        libro = self.get(id=libro_id)
        libro.autores.add(autor)
        return libro


class CategoriaManager(models.Manager):
    """ managers para el modelo autor """

    def categoria_por_autor(self, autor):
        return self.filter(
            categoria_libro__autores__id=autor
        ).distinct()<file_sep>/applications/libro/models.py
from django.db import models
from django.db.models.signals import post_save

# apps tercero
from PIL import Image

# from local apps
from applications.autor.models import Autor
# Create your models here.
from .managers import LibroManager, CategoriaManager

class Categoria(models.Model):
    nombre = models.CharField(max_length=30)

    objects = CategoriaManager()

    def __str__(self):
        return str(self.id) + ' - ' + self.nombre


class Libro(models.Model):
    categoria = models.ForeignKey(
        Categoria, 
        on_delete=models.CASCADE,
        related_name='categoria_libro'
    )
    autores = models.ManyToManyField(Autor)
    titulo = models.CharField(
        max_length=50
    )
    fecha = models.DateField('Fecha de lanzamiento')
    portada = models.ImageField(upload_to='portada')
    visitas = models.PositiveIntegerField()
    stok = models.PositiveIntegerField(default=0)

    objects = LibroManager()

    class Meta:
        verbose_name = 'Libro'
        verbose_name_plural = 'Libros'

    def __str__(self):
        return str(self.id) + '-' + self.titulo


def optimize_image(sender, instance, **kwargs):
    print("  ==================== ")
    if instance.portada:
        portada = Image.open(instance.portada.path)
        portada.save(instance.portada.path, quality=20, optimize=True)



post_save.connect(optimize_image, sender=Libro)<file_sep>/applications/lector/managers.py
from django.db import models


class PrestamoManager(models.Manager):
    """ managers para el modelo Lector """

    def prestamo_all(self):

        resultado = self.filter.all()

        return resultado<file_sep>/applications/lector/models.py
from django.db import models
from django.db.models.signals import post_delete

# from autor
from applications.autor.models import Persona
# from local apps
from applications.libro.models import Libro
#
from .managers import PrestamoManager
from .signals import update_libro_stok

class Lector(Persona):
    
    class Meta:
        verbose_name = 'Lector'
        verbose_name_plural = 'Lectores'


class Prestamo(models.Model):
    lector = models.ForeignKey(
        Lector,
        on_delete=models.CASCADE
    )
    libro = models.ForeignKey(
        Libro, 
        on_delete=models.CASCADE
    )
    fecha_prestamo = models.DateField()
    fecha_devolucion = models.DateField(
        blank=True, 
        null=True
    )
    devuelto = models.BooleanField()

    objects = PrestamoManager()

    def save(self, *args, **kwargs):

        self.libro.stok = self.libro.stok - 1
        self.libro.save()

        super(Prestamo, self).save(*args, **kwargs)

    def __str__(self):
        return self.libro.titulo


# def update_libro_stok(sender, instance, **kwargs):
#     # actualizamos el stok si se elimina un prestamo
#     instance.libro.stok = instance.libro.stok + 1
#     instance.libro.save()

post_delete.connect(update_libro_stok, sender=Prestamo)<file_sep>/applications/lector/urls.py
from django.contrib import admin
from django.urls import path

from . import views

urlpatterns = [
    path(
        'prestamo/add/', 
        views.AddPrestamo.as_view(), 
        name="prestamo_add"
    ),
    path(
        'prestamo/multiple-add/', 
        views.AddMultiplePrestamo.as_view(), 
        name="prestamo_add_multiple"
    ),
]<file_sep>/templates/libro/lista2.html
<h1>Lista de Libros</h1>

<ul>
    
    {% for l in lista_libros  %}
        <li>{{ l.titulo }} - {{ l.fecha }}</li>
    {% endfor %}
        
</ul><file_sep>/applications/lector/views.py
from datetime import date

from django.shortcuts import render
from django.http import HttpResponseRedirect

from django.views.generic.edit import FormView

# local apps
from .models import Prestamo, Lector
# forms
from .forms import PrestamoForm, MultiplePrestamoForm

class RegistrarPrestamo(FormView):
    template_name = "lector/add_prestamo.html"
    form_class = PrestamoForm
    success_url = '.'

    def form_valid(self, form):
        # Prestamo.objects.create(
        #     lector=form.cleaned_data['lector'],
        #     libro=form.cleaned_data['libro'],
        #     fecha_prestamo=date.today(),
        #     devuelto=False
        # )
        #
        prestamo = Prestamo(
            lector=form.cleaned_data['lector'],
            libro=form.cleaned_data['libro'],
            fecha_prestamo=date.today(),
            devuelto=False
        )
        prestamo.save()

        libro = form.cleaned_data['libro']
        libro.stok = libro.stok - 1
        libro.save()

        return super(RegistrarPrestamo, self).form_valid(form)


class AddPrestamo(FormView):
    template_name = "lector/add_prestamo.html"
    form_class = PrestamoForm
    success_url = '.'

    def form_valid(self, form):
        
        obj, created = Prestamo.objects.get_or_create(
            lector=form.cleaned_data['lector'],
            libro=form.cleaned_data['libro'],
            devuelto = False,
            defaults={
                'fecha_prestamo': date.today()
            }
        )

        if created:
            return super(AddPrestamo, self).form_valid(form)
        else:
            return HttpResponseRedirect('/')


class AddMultiplePrestamo(FormView):
    template_name = "lector/add_multiple_prestamo.html"
    form_class = MultiplePrestamoForm
    success_url = '.'

    def form_valid(self, form):
        #
        print(form.cleaned_data['lector'])
        print(form.cleaned_data['libros'])
        #
        prestamos = []
        for l in form.cleaned_data['libros']:
            prestamo = Prestamo(
                lector=form.cleaned_data['lector'],
                libro=l,
                fecha_prestamo=date.today(),
                devuelto=False
            )
            prestamos.append(prestamo)
        
        Prestamo.objects.bulk_create(
           prestamos 
        )
        

        return super(AddMultiplePrestamo, self).form_valid(form)

<file_sep>/applications/lector/signals.py
def update_libro_stok(sender, instance, **kwargs):
    # actualizamos el stok si se elimina un prestamo
    instance.libro.stok = instance.libro.stok + 1
    instance.libro.save()<file_sep>/applications/lector/forms.py
from django import forms

from applications.libro.models import Libro

from .models import Prestamo


class PrestamoForm(forms.ModelForm):
    class Meta:
        model = Prestamo
        fields = (
            'lector',
            'libro'
        )


class MultiplePrestamoForm(forms.ModelForm):

    libros = forms.ModelMultipleChoiceField(
        queryset=None,
        required=True,
        widget=forms.CheckboxSelectMultiple,
    )

    class Meta:
        model = Prestamo
        fields = (
            'lector',
        )
     
    def __init__(self, *args, **kwargs):
        super(MultiplePrestamoForm, self).__init__(*args, **kwargs)
        self.fields['libros'].queryset = Libro.objects.all()
    <file_sep>/biblioteca/urls.py
"""
    biblioteca URL Configuration
"""
from django.contrib import admin
from django.urls import path, re_path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    re_path('', include('applications.autor.urls')),
    re_path('', include('applications.libro.urls')),
    re_path('', include('applications.lector.urls')),
]
<file_sep>/applications/autor/models.py
from django.db import models

# managers
from .managers import AutorManager

class Persona(models.Model):
    nombres = models.CharField(
        max_length=50
    )
    apellidos = models.CharField(
        max_length=50
    )
    nacionaldiad = models.CharField(
        max_length=20
    )
    edad = models.PositiveIntegerField()

    class Meta:
        abstract = True
    
    def __str__(self):
        return str(self.id) + '-' + self.nombres + '-' + self.apellidos



class Autor(Persona):

    objects = AutorManager()<file_sep>/applications/libro/views.py
from django.shortcuts import render

from django.views.generic import ListView, DetailView

# mdols local
from .models import Libro


class ListLibros(ListView):
    context_object_name = 'lista_libros'
    template_name = 'libro/lista.html'

    def get_queryset(self):
        palabra_clave = self.request.GET.get("kword", '')
        #fecha 1
        f1 = self.request.GET.get("fecha1", '')
        #fecah 2
        f2 = self.request.GET.get("fecha2", '')

        if f1 and f2:
            return Libro.objects.listar_libros2(palabra_clave, f1, f2)
        else:
            return Libro.objects.listar_libros(palabra_clave)


class ListLibrosTrg(ListView):
    context_object_name = 'lista_libros'
    template_name = 'libro/lista.html'

    def get_queryset(self):
        palabra_clave = self.request.GET.get("kword", '')

        return Libro.objects.listar_libros_trg(palabra_clave)


class ListLibros2(ListView):
    context_object_name = 'lista_libros'
    template_name = 'libro/lista2.html'

    def get_queryset(self):

        return Libro.objects.listar_libros_categoria('4')



class LibroDetailView(DetailView):
    model = Libro
    template_name = "libro/detalle.html"

<file_sep>/applications/autor/managers.py
from django.db import models

from django.db.models import Q


class AutorManager(models.Manager):
    """ managers para el modelo autor """

    def buscar_autor(self, kword):

        resultado = self.filter(
            nombre__icontains=kword
        )

        return resultado
    
    def buscar_autor2(self, kword):

        resultado = self.filter(
            Q(nombre__icontains=kword) | Q(apellidos__icontains=kword)
        )

        return resultado
    
    def buscar_autor3(self, kword):

        resultado = self.filter(
            nombre__icontains=kword
        ).exclude(
            Q(edad__icontains=35) | Q(edad__icontains=65)
        )

        return resultado
    

    def buscar_autor4(self, kword):

        resultado = self.filter(
            edad__gt=40,
            edad__lt=65
        ).order_by('apellidos', 'nombre', 'id')

        return resultado
    