diff --git a/docker-compose.yml b/docker-compose.yml index 20f5b0e..34ef508 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -5,18 +5,15 @@ services: environment: POSTGRES_DB: ${DATABASE_NAME} POSTGRES_USER: ${DATABASE_USERNAME} - PGUSER: ${DATABASE_USERNAME} POSTGRES_PASSWORD: ${DATABASE_PASSWORD} env_file: - .env ports: - "5432:5432" - user: postgres volumes: - movienight_data:/var/lib/postgresql/data - - ./init-scripts:/docker-entrypoint-initdb.d healthcheck: - test: ["CMD-SHELL", "pg_isready -U $DATABASE_USERNAME"] + test: ["CMD-SHELL", "pg_isready", "-d", "$DATABASE_NAME"] interval: 30s timeout: 60s retries: 5 @@ -43,7 +40,6 @@ services: DATABASE_PASSWORD: ${DATABASE_PASSWORD} DATABASE_HOST: ${DATABASE_HOST} DATABASE_PORT: ${DATABASE_PORT} - OMDB_API_KEY: ${OMDB_API_KEY} env_file: - .env volumes: diff --git a/init-scripts/01-create-db.sh b/init-scripts/01-create-db.sh deleted file mode 100644 index 13d3573..0000000 --- a/init-scripts/01-create-db.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash -set -e - -# Create a postgres database for the user set in the .env file. -# Everything works fine without this, but this prevents a FATAL -# error from spamming the logs -psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL - CREATE DATABASE "$POSTGRES_USER"; - GRANT ALL PRIVILEGES ON DATABASE "$POSTGRES_USER" TO "$POSTGRES_USER"; -EOSQL \ No newline at end of file diff --git a/movie_db/__init__.py b/movie_db/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/movie_db/admin.py b/movie_db/admin.py deleted file mode 100644 index 8c38f3f..0000000 --- a/movie_db/admin.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.contrib import admin - -# Register your models here. diff --git a/movie_db/apps.py b/movie_db/apps.py deleted file mode 100644 index d9aa88e..0000000 --- a/movie_db/apps.py +++ /dev/null @@ -1,6 +0,0 @@ -from django.apps import AppConfig - - -class MoviedbConfig(AppConfig): - default_auto_field = 'django.db.models.BigAutoField' - name = 'movie_db' diff --git a/movie_db/db_providers/omdb.py b/movie_db/db_providers/omdb.py deleted file mode 100644 index 7db8f1e..0000000 --- a/movie_db/db_providers/omdb.py +++ /dev/null @@ -1,37 +0,0 @@ -import os - -from movie_db.movie_db import MovieDB -import requests - -from movie_db.serializers import MovieSerializer, MovieResultSerializer - - -class OMDb(MovieDB): - def __init__(self): - api_key = os.getenv("OMDB_API_KEY") - self.api_key = f"{api_key}" - self.base_url = "https://www.omdbapi.com/?apikey=" + self.api_key - super().__init__() - - def search(self, query, options=None): - if options["type"] == "imdb_id": - return self.search_by_imdb_id(query) - elif options["type"] == "title": - return self.search_by_title(query) - else: - return self.search_by_term(query) - - def search_by_title(self, title): - response = requests.get(self.base_url + "&t=" + title).json() - return MovieSerializer(response).data - - def search_by_imdb_id(self, imdb_id): - response = requests.get(self.base_url + "&i=" + imdb_id).json() - return MovieSerializer(response).data - - def search_by_term(self, term): - response = requests.get(self.base_url + "&s=" + term).json() - try: - return MovieResultSerializer(response["Search"], many=True).data - except KeyError: - return {"error": response} diff --git a/movie_db/migrations/__init__.py b/movie_db/migrations/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/movie_db/models.py b/movie_db/models.py deleted file mode 100644 index 71a8362..0000000 --- a/movie_db/models.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.db import models - -# Create your models here. diff --git a/movie_db/movie_db.py b/movie_db/movie_db.py deleted file mode 100644 index d65a019..0000000 --- a/movie_db/movie_db.py +++ /dev/null @@ -1,8 +0,0 @@ -from abc import ABC - -class MovieDB(ABC): - def __init__(self): - pass - - def search(self, query, options=None): - pass \ No newline at end of file diff --git a/movie_db/serializers.py b/movie_db/serializers.py deleted file mode 100644 index 0f5eca2..0000000 --- a/movie_db/serializers.py +++ /dev/null @@ -1,22 +0,0 @@ -from rest_framework import serializers - - -class MovieSerializer(serializers.Serializer): - director = serializers.CharField(source="Director") - genre = serializers.CharField(source="Genre") - imdb_id = serializers.CharField(source="imdbID") - imdb_rating = serializers.CharField(source="imdbRating") - media_type = serializers.CharField(source="Type") - plot = serializers.CharField(source="Plot") - poster = serializers.CharField(source="Poster") - runtime = serializers.CharField(source="Runtime") - title = serializers.CharField(source="Title") - year = serializers.CharField(source="Year") - - -class MovieResultSerializer(serializers.Serializer): - title = serializers.CharField(source="Title") - year = serializers.CharField(source="Year") - imdb_id = serializers.CharField(source="imdbID") - media_type = serializers.CharField(source="Type") - poster = serializers.CharField(source="Poster") diff --git a/movie_db/tests.py b/movie_db/tests.py deleted file mode 100644 index 7ce503c..0000000 --- a/movie_db/tests.py +++ /dev/null @@ -1,3 +0,0 @@ -from django.test import TestCase - -# Create your tests here. diff --git a/movie_db/views.py b/movie_db/views.py deleted file mode 100644 index 602e418..0000000 --- a/movie_db/views.py +++ /dev/null @@ -1,12 +0,0 @@ -from django.http import JsonResponse -from movie_db.db_providers.omdb import OMDb - - -def omdb_search(request): - query = request.GET.get("q") - if not query: - return JsonResponse({"Error": "Missing query"}, status=400) - - search_type = request.GET.get("type") - omdb = OMDb() - return JsonResponse(omdb.search(query, {"type": search_type}), safe=False) diff --git a/movie_manager/migrations/0007_alter_movie_critic_score.py b/movie_manager/migrations/0007_alter_movie_critic_score.py deleted file mode 100644 index 2d27d83..0000000 --- a/movie_manager/migrations/0007_alter_movie_critic_score.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 5.1.4 on 2025-04-12 04:49 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('movie_manager', '0006_remove_showing_slug_schedule_slug'), - ] - - operations = [ - migrations.AlterField( - model_name='movie', - name='critic_score', - field=models.CharField(blank=True, max_length=500, null=True), - ), - ] diff --git a/movie_manager/models.py b/movie_manager/models.py index 1b0c9bf..171e9e2 100644 --- a/movie_manager/models.py +++ b/movie_manager/models.py @@ -1,12 +1,11 @@ from django.db import models from django.contrib.auth.models import User - class Movie(models.Model): title = models.CharField(max_length=100) imdb_id = models.CharField(max_length=100) year = models.IntegerField() - critic_score = models.CharField(max_length=500, null=True, blank=True) + critic_score = models.CharField(max_length=500) genre = models.CharField(max_length=100) director = models.CharField(max_length=500) actors = models.CharField(max_length=500) @@ -40,7 +39,6 @@ class MovieList(models.Model): def __str__(self): return self.name - class Schedule(models.Model): name = models.CharField(max_length=100) owner = models.ForeignKey(User, on_delete=models.CASCADE) @@ -51,7 +49,6 @@ class Schedule(models.Model): updated_at = models.DateTimeField(auto_now=True) deleted_at = models.DateTimeField(null=True, blank=True) - class Showing(models.Model): movie = models.ForeignKey(Movie, on_delete=models.CASCADE) owner = models.ForeignKey(User, on_delete=models.CASCADE) diff --git a/movie_manager/serializers.py b/movie_manager/serializers.py index 2118dc1..bebebb0 100644 --- a/movie_manager/serializers.py +++ b/movie_manager/serializers.py @@ -6,7 +6,7 @@ from movie_manager.models import Movie, MovieList, Schedule, Showing class MovieSerializer(serializers.ModelSerializer): class Meta: model = Movie - fields = "__all__" + fields = '__all__' class MovieListSerializer(serializers.ModelSerializer): @@ -15,12 +15,12 @@ class MovieListSerializer(serializers.ModelSerializer): class Meta: model = MovieList - fields = ["id", "name", "owner", "public", "movies", "movie_count"] + fields = ["id","name","owner","public", "movies", "movie_count"] + def get_movie_count(self, obj): return len(obj.movies.all()) - class UserSerializer(serializers.Serializer): class Meta: model = User @@ -41,4 +41,5 @@ class ScheduleSerializer(serializers.ModelSerializer): class Meta: model = Schedule - fields = ["name", "owner", "public", "slug", "showings"] + fields = ["name", "owner","public","slug", "showings"] + diff --git a/movie_manager/views.py b/movie_manager/views.py index 1b98766..e08d86e 100644 --- a/movie_manager/views.py +++ b/movie_manager/views.py @@ -1,27 +1,14 @@ import datetime -import json from django.http import JsonResponse from django.contrib.auth.models import User from rest_framework import permissions, viewsets from knox.auth import TokenAuthentication -from rest_framework.decorators import action, api_view +from rest_framework.decorators import action from rest_framework.exceptions import NotFound -from rest_framework.permissions import AllowAny, SAFE_METHODS -from movie_db.db_providers.omdb import OMDb from movie_manager.models import Movie, MovieList, Schedule, Showing -from movie_manager.serializers import ( - MovieListSerializer, - MovieSerializer, - ScheduleSerializer, - ShowingSerializer, -) - - -class ReadOnly(permissions.BasePermission): - def has_permission(self, request, view): - return request.method in SAFE_METHODS +from movie_manager.serializers import MovieListSerializer, MovieSerializer, ScheduleSerializer, ShowingSerializer # Create your views here. @@ -32,25 +19,26 @@ class MovieViewset(viewsets.ModelViewSet): serializer_class = MovieSerializer - class MovieListViewset(viewsets.ModelViewSet): queryset = MovieList.objects.all().order_by("name") authentication_classes = [TokenAuthentication] - permission_classes = [permissions.IsAuthenticated | ReadOnly] + permission_classes = [permissions.IsAuthenticated] serializer_class = MovieListSerializer + def retrieve(self, request, pk=None, *args, **kwargs): movie_list = MovieList.objects.get(pk=pk) return JsonResponse(MovieListSerializer(movie_list).data) + def update(self, request, pk=None, *args, **kwargs): movie_list = MovieList.objects.get(pk=pk) - movie_list.name = request.data.get("name") + movie_list.name = request.data.get('name') movie_list.owner = User.objects.get(pk=request.data.get("owner")) - if request.data.get("movies"): - movie_ids = request.data.get("movies") + if request.data.get('movies'): + movie_ids = request.data.get('movies') for movie_id in movie_ids: try: movie = Movie.objects.get(pk=movie_id) @@ -66,33 +54,14 @@ class MovieListViewset(viewsets.ModelViewSet): return JsonResponse(MovieListSerializer(movie_list).data) - @action( - detail=True, methods=["put", "delete"], url_path="movie/(?Ptt[0-9]+)" - ) - def add_movie(self, request, pk=None, imdb_id=None, *args, **kwargs): - if request.method == "DELETE": - return self.remove_movie(request, pk, imdb_id) + @action(detail=True, methods=['put', 'delete'], url_path='movie/(?P[0-9]+)') + def add_movie(self, request, pk=None, movie_id=None, *args, **kwargs): + if request.method == 'DELETE': + return self.remove_movie(request, pk, movie_id) movie_list = MovieList.objects.get(pk=pk) - try: - new_movie = Movie.objects.get(imdb_id=imdb_id) - except Movie.DoesNotExist: - omdb = OMDb() - movie = omdb.search(imdb_id, {"type": "imdb_id"}) - - new_movie = Movie.objects.create( - title=movie["title"], - year=movie["year"], - imdb_id=movie["imdb_id"], - poster=movie["poster"], - plot=movie["plot"], - genre=movie["genre"], - critic_score=movie["imdb_rating"], - director=movie["director"], - added_by_id=request.user.id, - ) - - movie_list.movies.add(new_movie) + movie = Movie.objects.get(pk=movie_id) + movie_list.movies.add(movie) return JsonResponse(MovieListSerializer(movie_list).data) @@ -104,7 +73,6 @@ class MovieListViewset(viewsets.ModelViewSet): return JsonResponse(MovieListSerializer(movie_list).data) - class ScheduleViewset(viewsets.ModelViewSet): queryset = Schedule.objects.all().order_by("name") authentication_classes = [TokenAuthentication] @@ -124,22 +92,19 @@ class ScheduleViewset(viewsets.ModelViewSet): data = serializer.data # Replace all showings with only future showings - data["showings"] = ShowingSerializer(upcoming_showings, many=True).data + data['showings'] = ShowingSerializer(upcoming_showings, many=True).data - if request.GET.get("past_showings") == "true": + + if request.GET.get('past_showings') == 'true': past_showings = instance.showings.filter(showtime__lt=today) # Add both to the response - data["past_showings"] = [ - { - "id": showing.id, - "showtime": showing.showtime.isoformat(), - "movie": MovieSerializer(showing.movie).data, - } + data['past_showings'] = [ + {'id': showing.id, 'showtime': showing.showtime.isoformat(), "movie": MovieSerializer(showing.movie).data} for showing in past_showings ] else: - data["past_showings"] = [] + data['past_showings'] = [] return JsonResponse(data) @@ -152,10 +117,10 @@ class ShowingViewset(viewsets.ModelViewSet): serializer_class = ShowingSerializer def create(self, request, *args, **kwargs): - movie_id = request.data.get("movie") + movie_id = request.data.get('movie') movie = Movie.objects.get(pk=movie_id) - schedule_id = request.data.get("schedule") + schedule_id = request.data.get('schedule') schedule = Schedule.objects.get(pk=schedule_id) showing = Showing.objects.create( @@ -163,9 +128,11 @@ class ShowingViewset(viewsets.ModelViewSet): schedule=schedule, showtime=request.data.get("showtime"), public=request.data.get("public"), - owner=User.objects.get(pk=request.data.get("owner")), + owner=User.objects.get(pk=request.data.get("owner")) ) schedule.showings.add(showing) return JsonResponse(ShowingSerializer(showing).data) + + diff --git a/movienight/urls.py b/movienight/urls.py index bf84fd0..6889ee7 100644 --- a/movienight/urls.py +++ b/movienight/urls.py @@ -12,7 +12,6 @@ from rest_framework.routers import DefaultRouter from users import views as user_views from movie_manager import views as movie_views -from movie_db import views as movie_db_views from rest_framework.authtoken.views import obtain_auth_token router = DefaultRouter() @@ -29,6 +28,5 @@ urlpatterns = [ path(r"api/auth/token/", obtain_auth_token), path(r"api/auth/login/", user_views.LoginView.as_view(), name="knox_login"), path(r"api/auth/register/", user_views.register, name="register"), - path(r"api/movies/search", movie_db_views.omdb_search, name="omdb_search"), path(r"api/auth/", include("knox.urls")), ] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) diff --git a/requirements.txt b/requirements.txt index 456b8f8..7c9b3b9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,4 +6,3 @@ django-filter gunicorn==23.0.0 psycopg2-binary==2.9.10 django-cors-headers==4.7.0 -requests==2.32.3 \ No newline at end of file