Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
# OpenBootCampPython
Repository to store Python boot camp.

Ejercicio 12: En este ejercicio tendrás que crear una aplicación en Django que almacene datos de directores de cine y luego se puedan ver sus películas, así como una descripción de las mismas.

Tienes que personalizar el admin de la aplicación y a su vez crear las vistas de cada una de las partes de la aplicación.
Empty file added catalog/__init__.py
Empty file.
35 changes: 35 additions & 0 deletions catalog/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
from django.contrib import admin
from .models import Director, Genre, Movie, Country


class MovieInline(admin.TabularInline):
model = Movie
exclude = ('id',)


@admin.register(Director)
class DirectorAdmin(admin.ModelAdmin):
list_display = ('id', 'last_name', 'first_name', 'date_of_birth', 'date_of_death')
list_filter = ('date_of_birth', 'date_of_death')
fields = ['first_name', 'last_name', ('date_of_birth', 'date_of_death')]
exclude = ('id',)
inlines = [MovieInline]


@admin.register(Movie)
class MovieAdmin(admin.ModelAdmin):

def display_genre(self):
"""Create a string for the Genre. This is required to display genre in Admin."""
return ', '.join(genre.name for genre in self.genre.all()[:3])

display_genre.short_description = 'Genre'

list_display = ('id', 'title', 'director', display_genre, 'country')
list_filter = ('country', 'genre', 'director')
exclude = ('id',)


# Register your models here.
admin.site.register(Genre)
admin.site.register(Country)
6 changes: 6 additions & 0 deletions catalog/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from django.apps import AppConfig


class CatalogConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'catalog'
80 changes: 80 additions & 0 deletions catalog/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
from django.db import models
from django.urls import reverse
import uuid


class Director(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, help_text='Unique ID for this particular director')
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
date_of_birth = models.DateField(null=True, blank=True)
date_of_death = models.DateField('Died', null=True, blank=True)
objects = models.Manager()

class Meta:
ordering = ['last_name', 'first_name']

def get_absolute_url(self):
"""Returns the URL to access a particular director instance."""
return reverse('director-detail', args=[str(self.id)])

def __str__(self):
"""String for representing the Model object."""
return f'{self.last_name}, {self.first_name}'


class Genre(models.Model):
"""Model representing a movie genre."""
name = models.CharField(primary_key=True, max_length=200, help_text='Enter a movie genre (e.g. Science Fiction)')
objects = models.Manager()

def __str__(self):
"""String for representing the Model object."""
return self.name

class Meta:
ordering = ['name']


class Country(models.Model):
"""Model representing a movie country"""
name = models.CharField(primary_key=True, max_length=200, help_text='Enter a movie country (e.g. Spain)')
objects = models.Manager()

def __str__(self):
"""String for representing the Model object."""
return self.name

class Meta:
ordering = ['name']


class Movie(models.Model):
"""Model representing a movie"""
objects = models.Manager()
id = models.UUIDField(primary_key=True, default=uuid.uuid4, help_text='Unique ID for this particular movie')
title = models.CharField(max_length=200)

# Foreign Key used because movie can only have one author, but authors can have multiple books
# Director is a string rather than an object because it hasn't been declared yet in the file
director = models.ForeignKey(Director, on_delete=models.SET_NULL, null=True)

summary = models.TextField(max_length=1000, help_text='Enter a brief description of the movie')

# ManyToManyField used because genre can contain many movies. Movies can cover many genres.
# Genre class has already been defined, so we can specify the object above.
genre = models.ManyToManyField(Genre, help_text='Select a genre for this movie')

country = models.ForeignKey(Country, on_delete=models.SET_NULL, null=True,
help_text='Select a country for this movie')

def __str__(self):
"""String for representing the Model object."""
return self.title

def get_absolute_url(self):
"""Returns the URL to access a detail record for this movie."""
return reverse('movie-detail', args=[str(self.id)])

class Meta:
ordering = ['title']
5 changes: 5 additions & 0 deletions catalog/static/css/styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.sidebar-nav {
margin-top: 20px;
padding: 0;
list-style: none;
}
45 changes: 45 additions & 0 deletions catalog/templates/base_generic.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<!DOCTYPE html>
<html lang="en">
<head>
{% block title %}<title>Local Library</title>{% endblock %}
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
<!-- Add additional CSS in static file -->
{% load static %}
<link rel="stylesheet" href="{% static 'css/styles.css' %}" />
</head>
<body>
<div class="container-fluid">
<div class="row">
<div class="col-sm-2">
{% block sidebar %}
<ul class="sidebar-nav">
<li><a href="{% url 'index' %}">Home</a></li>
<li><a href="{% url 'movies' %}">All movies</a></li>
<li><a href="{% url 'directors' %}">All directors</a></li>
</ul>
{% endblock %}
</div>
<div class="col-sm-10 ">{% block content %}{% endblock %}{% block pagination %}
{% if is_paginated %}
<div class="pagination">
<span class="page-links">
{% if page_obj.has_previous %}
<a href="{{ request.path }}?page={{ page_obj.previous_page_number }}">previous</a>
{% endif %}
<span class="page-current">
Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.
</span>
{% if page_obj.has_next %}
<a href="{{ request.path }}?page={{ page_obj.next_page_number }}">next</a>
{% endif %}
</span>
</div>
{% endif %}
{% endblock %}
</div>
</div>
</div>
</body>
</html>
18 changes: 18 additions & 0 deletions catalog/templates/catalog/director_detail.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{% extends "base_generic.html" %}

{% block content %}
<h1>Nombre: {{ director.first_name }} {{ director.last_name }}</h1>
<p><strong>Fecha nacimiento:</strong> {{ director.date_of_birth }}</p>
<p><strong>Fecha fallecimiento:</strong> {{ director.date_of_death }}</p>
<div style="margin-left:20px;margin-top:20px">
<h4>Peliculas</h4>

{% for movie in director.movie_set.all %}
<hr>
<p>
<a href="{{ movie.get_absolute_url }}">{{ movie.title }}</a></p>
{% endfor %}
</div>


{% endblock %}
16 changes: 16 additions & 0 deletions catalog/templates/catalog/director_list.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{% extends "base_generic.html" %}

{% block content %}
<h1>Director List</h1>
{% if director_list %}
<ul>
{% for director in director_list %}
<li>
<a href="{{ director.get_absolute_url }}">{{ director.first_name }} {{director.last_name}}</a>
</li>
{% endfor %}
</ul>
{% else %}
<p>There are no director in the library.</p>
{% endif %}
{% endblock %}
11 changes: 11 additions & 0 deletions catalog/templates/catalog/movie_detail.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{% extends "base_generic.html" %}

{% block content %}
<h1>Título: {{ movie.title }}</h1>

<p><strong>Director:</strong> <a href="{{ movie.director.get_absolute_url }}">{{ movie.director }}</a></p>
<p><strong>Resumen:</strong> {{ movie.summary }}</p>
<p><strong>País:</strong> {{ movie.country }}</p>
<p><strong>Género:</strong> {{ movie.genre.all|join:", " }}</p>

{% endblock %}
16 changes: 16 additions & 0 deletions catalog/templates/catalog/movie_list.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{% extends "base_generic.html" %}

{% block content %}
<h1>Movie List</h1>
{% if movie_list %}
<ul>
{% for movie in movie_list %}
<li>
<a href="{{ movie.get_absolute_url }}">{{ movie.title }}</a> ({{movie.director}})
</li>
{% endfor %}
</ul>
{% else %}
<p>There are no movie in the library.</p>
{% endif %}
{% endblock %}
22 changes: 22 additions & 0 deletions catalog/templates/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{% extends "base_generic.html" %}

{% block content %}
<h1>Local Videoclub Home</h1>
<p>Welcome to Videoclub, a website developed by <em>Izri</em>!</p>
<h2>Dynamic content</h2>
<p>The videoclub has the following record counts:</p>
<ul>
<li><strong>Peliculas:</strong> {{ num_movies }}</li>
<li><strong>Directores:</strong> {{ num_directors }}</li>
<li><strong>Acción:</strong> {{ num_action }}</li>
<li><strong>Animación:</strong> {{ num_animation }}</li>
<li><strong>Romance:</strong> {{ num_romance }}</li>
<li><strong>Fantasía:</strong> {{ num_fantasy }}</li>
<li><strong>Terror:</strong> {{ num_terror }}</li>
<li><strong>Ciancia Ficción:</strong> {{ num_scifi }}</li>
<li><strong>Aventura:</strong> {{ num_adventure }}</li>
<li><strong>Misterio:</strong> {{ num_mistery }}</li>
<li><strong>Suspense:</strong> {{ num_thriller }}</li>
<li><strong>Drama:</strong> {{ num_drama }}</li>
</ul>
{% endblock %}
3 changes: 3 additions & 0 deletions catalog/tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from django.test import TestCase

# Create your tests here.
10 changes: 10 additions & 0 deletions catalog/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
from django.urls import path
from . import views

urlpatterns = [
path('', views.index, name='index'),
path('movies/', views.MovieListView.as_view(), name='movies'),
path('movie/<uuid:pk>', views.MovieDetailView.as_view(), name='movie-detail'),
path('directors/', views.DirectorListView.as_view(), name='directors'),
path('director/<uuid:pk>', views.DirectorDetailView.as_view(), name='director-detail'),
]
76 changes: 76 additions & 0 deletions catalog/views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
from django.shortcuts import render
from .models import Movie, Director
from django.views import generic


def index(request):
"""View function for home page of site."""

# Generate counts of some main objects
num_movies = Movie.objects.all().count()
num_directors = Director.objects.count()
num_action = Movie.objects.filter(genre__exact='Acción').count()
num_animation = Movie.objects.filter(genre__exact='Animación').count()
num_romance = Movie.objects.filter(genre__exact='Romance').count()
num_fantasy = Movie.objects.filter(genre__exact='Fantasía').count()
num_terror = Movie.objects.filter(genre__exact='Terror').count()
num_scifi = Movie.objects.filter(genre__exact='Ciencia Ficción').count()
num_adventure = Movie.objects.filter(genre__exact='Aventura').count()
num_mistery = Movie.objects.filter(genre__exact='Misterio').count()
num_thriller = Movie.objects.filter(genre__exact='Suspense').count()
num_drama = Movie.objects.filter(genre__exact='Drama').count()
context = {
'num_movies': num_movies,
'num_directors': num_directors,
'num_action': num_action,
'num_animation': num_animation,
'num_romance': num_romance,
'num_fantasy': num_fantasy,
'num_terror': num_terror,
'num_scifi': num_scifi,
'num_adventure': num_adventure,
'num_mistery': num_mistery,
'num_thriller': num_thriller,
'num_drama': num_drama,
}

# Render the HTML template index.html with the data in the context variable
return render(request, 'index.html', context=context)


class MovieListView(generic.ListView):
model = Movie
paginate_by = 2

def get_queryset(self):
return Movie.objects.all().order_by('title')

def get_context_data(self, **kwargs):
# Call the base implementation first to get the context
context = super(MovieListView, self).get_context_data(**kwargs)
# Create any data and add it to the context
context['some_data'] = 'This is just some data'
return context


class MovieDetailView(generic.DetailView):
model = Movie


class DirectorListView(generic.ListView):
model = Director
paginate_by = 2

def get_queryset(self):
return Director.objects.all().order_by('last_name', 'first_name')

def get_context_data(self, **kwargs):
# Call the base implementation first to get the context
context = super(DirectorListView, self).get_context_data(**kwargs)
# Create any data and add it to the context
context['some_data'] = 'This is just some data'
return context


class DirectorDetailView(generic.DetailView):
model = Director
22 changes: 22 additions & 0 deletions manage.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/usr/bin/env python
"""Django's command-line utility for administrative tasks."""
import os
import sys


def main():
"""Run administrative tasks."""
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'wikiCine.settings')
try:
from django.core.management import execute_from_command_line
except ImportError as exc:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
) from exc
execute_from_command_line(sys.argv)


if __name__ == '__main__':
main()
8 changes: 3 additions & 5 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
-i https://pypi.org/simple
asgiref==3.5.2 ; python_version >= '3.7'
asgiref==3.5.2
django==4.1.4
pip==22.3.1
psycopg2-binary==2.9.5
pysqlite3==0.4.7
setuptools==65.6.3 ; python_version >= '3.7'
sqlparse==0.4.3 ; python_version >= '3.5'
wheel==0.38.0
sqlparse==0.4.3
Loading