diff --git a/movie_manager/models.py b/movie_manager/models.py index fa39298..f401dde 100644 --- a/movie_manager/models.py +++ b/movie_manager/models.py @@ -1,6 +1,7 @@ -from django.contrib.auth.models import User from django.db import models +from django.contrib.auth.models import User from django.db.models import SET_NULL +import datetime class Movie(models.Model): diff --git a/movienight/settings.py b/movienight/settings.py index eb9878d..74f4921 100644 --- a/movienight/settings.py +++ b/movienight/settings.py @@ -10,12 +10,14 @@ For the full list of settings and their values, see https://docs.djangoproject.com/en/5.1/ref/settings/ """ -import os from pathlib import Path +import os + # Build paths inside the project like this: BASE_DIR / 'subdir'. BASE_DIR = Path(__file__).resolve().parent.parent + # Quick-start development settings - unsuitable for production # See https://docs.djangoproject.com/en/5.1/howto/deployment/checklist/ @@ -28,13 +30,13 @@ DEBUG = bool(os.environ.get("DEBUG", default=0)) ALLOWED_HOSTS = os.environ.get("DJANGO_ALLOWED_HOSTS", "127.0.0.1").split(",") CORS_ALLOWED_ORIGINS = ["http://localhost:3000"] + # Application definition INSTALLED_APPS = [ "django.contrib.admin", "django.contrib.auth", "django.contrib.contenttypes", - "corsheaders", "django.contrib.sessions", "django.contrib.messages", "django.contrib.staticfiles", @@ -42,7 +44,7 @@ INSTALLED_APPS = [ "rest_framework.authtoken", "knox", "movie_manager", - "users", + "corsheaders", ] MIDDLEWARE = [ @@ -76,6 +78,7 @@ TEMPLATES = [ WSGI_APPLICATION = "movienight.wsgi.application" + # Database # https://docs.djangoproject.com/en/5.1/ref/settings/#databases @@ -92,6 +95,7 @@ DATABASES = { } } + # Password validation # https://docs.djangoproject.com/en/5.1/ref/settings/#auth-password-validators @@ -110,6 +114,7 @@ AUTH_PASSWORD_VALIDATORS = [ }, ] + # Internationalization # https://docs.djangoproject.com/en/5.1/topics/i18n/ @@ -126,6 +131,7 @@ OMDB_API_KEY = os.environ.get("OMDB_API_KEY") # Django Rest Framework REST_FRAMEWORK = { "DEFAULT_AUTHENTICATION_CLASSES": [ + #'rest_framework.authentication.SessionAuthentication', "knox.auth.TokenAuthentication", ], } diff --git a/movienight/urls.py b/movienight/urls.py index e36e1b5..c07c5b5 100644 --- a/movienight/urls.py +++ b/movienight/urls.py @@ -2,14 +2,14 @@ URL configuration for movienight project. """ -from django.conf import settings -from django.conf.urls.static import static +import knox +from knox import views as knox_views from django.contrib import admin from django.urls import path, include -from rest_framework.authtoken.views import obtain_auth_token +from django.conf.urls.static import static +from django.conf import settings from rest_framework.routers import DefaultRouter -from movie_db import views as movie_db_views from movie_manager.viewsets import ( MovieViewset, MovieListViewset, @@ -17,8 +17,11 @@ from movie_manager.viewsets import ( ShowingViewset, ) from users import views as user_views +from movie_db import views as movie_db_views +from rest_framework.authtoken.views import obtain_auth_token + +from users.viewsets.user import register from users.viewsets import UserViewSet, GroupViewSet -from users.viewsets.user import register, UserProfileViewSet router = DefaultRouter() router.register(r"v1/users", UserViewSet) @@ -27,17 +30,13 @@ router.register(r"v1/movies", MovieViewset) router.register(r"v1/lists", MovieListViewset) router.register(r"v1/schedules", ScheduleViewset) router.register(r"v1/showings", ShowingViewset) -router.register(r"v1/users/profiles/", UserProfileViewSet) urlpatterns = [ - path("", include(router.urls)), - path("admin/", admin.site.urls), - path(r"v1/auth/token/", obtain_auth_token), - path(r"v1/auth/login/", user_views.LoginView.as_view(), name="knox_login"), - path(r"v1/auth/register/", register, name="register"), - path(r"v1/movies/search", movie_db_views.omdb_search, name="omdb_search"), - path(r"v1/auth/", include("knox.urls")), - path('v1/users/profile', UserProfileViewSet.as_view({"get": "current_user_profile"}), - name="current_user_profile"), - path('v1/users/profiles//', UserProfileViewSet.as_view({"get": "retrieve"})) - ] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) + path("", include(router.urls)), + path("admin/", admin.site.urls), + path(r"v1/auth/token/", obtain_auth_token), + path(r"v1/auth/login/", user_views.LoginView.as_view(), name="knox_login"), + path(r"v1/auth/register/", register, name="register"), + path(r"v1/movies/search", movie_db_views.omdb_search, name="omdb_search"), + path(r"v1/auth/", include("knox.urls")), +] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) diff --git a/users/migrations/0001_initial.py b/users/migrations/0001_initial.py deleted file mode 100644 index 8b80e3f..0000000 --- a/users/migrations/0001_initial.py +++ /dev/null @@ -1,25 +0,0 @@ -# Generated by Django 5.2.2 on 2025-07-08 02:37 - -import django.db.models.deletion -from django.conf import settings -from django.db import migrations, models - - -class Migration(migrations.Migration): - - initial = True - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ] - - operations = [ - migrations.CreateModel( - name='UserProfile', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(blank=True, max_length=100, null=True)), - ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), - ], - ), - ] diff --git a/users/models.py b/users/models.py index 416811d..71a8362 100644 --- a/users/models.py +++ b/users/models.py @@ -1,12 +1,3 @@ -from django.contrib.auth.models import User from django.db import models - # Create your models here. -class UserProfile(models.Model): - user = models.OneToOneField(User, on_delete=models.CASCADE) - name = models.CharField(max_length=100, null=True, blank=True) - - @property - def lists(self): - return self.user.movielist_set.all() diff --git a/users/permissions.py b/users/permissions.py deleted file mode 100644 index 3dae833..0000000 --- a/users/permissions.py +++ /dev/null @@ -1,6 +0,0 @@ -from rest_framework import permissions -from rest_framework.permissions import SAFE_METHODS - -class ReadOnly(permissions.BasePermission): - def has_permission(self, request, view): - return request.method in SAFE_METHODS diff --git a/users/serializers.py b/users/serializers.py index 33f9a3f..a269baa 100644 --- a/users/serializers.py +++ b/users/serializers.py @@ -1,35 +1,12 @@ from django.contrib.auth import authenticate -from django.contrib.auth.models import User, Group from rest_framework import serializers - -from movie_manager.serializers import MovieListSerializer -from users.models import UserProfile +from django.contrib.auth.models import User, Group class UserSerializer(serializers.HyperlinkedModelSerializer): class Meta: model = User - fields = ["url", "username", "email", "groups"] - - -class UserProfileSerializer(serializers.HyperlinkedModelSerializer): - name = serializers.SerializerMethodField() - username = serializers.SerializerMethodField() - date_joined = serializers.SerializerMethodField() - lists = MovieListSerializer(many=True, read_only=True) - - class Meta: - model = UserProfile - fields = ["name", "username", "date_joined", "lists"] - - def get_name(self, obj): - return obj.name or "" - - def get_username(self, obj): - return obj.user.username - - def get_date_joined(self, obj): - return obj.user.date_joined + fields = ["url", "username", "email", "password", "groups"] class GroupSerializer(serializers.HyperlinkedModelSerializer): diff --git a/users/viewsets/user.py b/users/viewsets/user.py index 881f612..c2e2063 100644 --- a/users/viewsets/user.py +++ b/users/viewsets/user.py @@ -1,13 +1,10 @@ -from django.contrib.auth.models import User -from django.http import JsonResponse +from django.contrib.auth.models import User, Group from knox.auth import TokenAuthentication from rest_framework import viewsets, permissions, status -from rest_framework.decorators import api_view, action +from rest_framework.decorators import api_view from rest_framework.response import Response -from users.models import UserProfile -from users.permissions import ReadOnly -from users.serializers import UserSerializer, UserProfileSerializer +from users.serializers import UserSerializer, GroupSerializer class UserViewSet(viewsets.ModelViewSet): @@ -18,51 +15,6 @@ class UserViewSet(viewsets.ModelViewSet): serializer_class = UserSerializer -class UserProfileViewSet(viewsets.ModelViewSet): - authentication_classes = [TokenAuthentication] - permission_classes = [permissions.IsAuthenticated | ReadOnly] - - queryset = UserProfile.objects.all() - serializer_class = UserProfileSerializer - lookup_field = "user__username" - - def retrieve(self, request, pk=None, *args, **kwargs): - try: - username = kwargs.get('user__username') - user = User.objects.get(username=username) - except User.DoesNotExist: - return Response([], status=status.HTTP_404_NOT_FOUND) - - try: - user_profile = UserProfile.objects.get(user=user) - except UserProfile.DoesNotExist: - user_profile = UserProfile( - user=user, - ) - - user_profile.save() - - return JsonResponse(UserProfileSerializer(user_profile).data) - - @action(detail=False) - def current_user_profile(self, request, *args, **kwargs): - try: - user = request.user - except User.DoesNotExist: - return Response([], status=status.HTTP_404_NOT_FOUND) - - try: - user_profile = UserProfile.objects.get(user=user) - except UserProfile.DoesNotExist: - user_profile = UserProfile( - user=user, - ) - - user_profile.save() - - return JsonResponse(UserProfileSerializer(user_profile).data) - - @api_view(["POST"]) def register(request): user_data = UserSerializer(data=request.data)