Compare commits
No commits in common. "80c4639d23b7ebec6b9565908f437dbe10ccd4f9" and "eeb74027eb3cd2cc8fcb25bcdf7737eeb82a5f02" have entirely different histories.
80c4639d23
...
eeb74027eb
8 changed files with 32 additions and 137 deletions
|
@ -1,6 +1,7 @@
|
||||||
from django.contrib.auth.models import User
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
from django.contrib.auth.models import User
|
||||||
from django.db.models import SET_NULL
|
from django.db.models import SET_NULL
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
|
||||||
class Movie(models.Model):
|
class Movie(models.Model):
|
||||||
|
|
|
@ -10,12 +10,14 @@ For the full list of settings and their values, see
|
||||||
https://docs.djangoproject.com/en/5.1/ref/settings/
|
https://docs.djangoproject.com/en/5.1/ref/settings/
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
# Build paths inside the project like this: BASE_DIR / 'subdir'.
|
||||||
BASE_DIR = Path(__file__).resolve().parent.parent
|
BASE_DIR = Path(__file__).resolve().parent.parent
|
||||||
|
|
||||||
|
|
||||||
# Quick-start development settings - unsuitable for production
|
# Quick-start development settings - unsuitable for production
|
||||||
# See https://docs.djangoproject.com/en/5.1/howto/deployment/checklist/
|
# 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(",")
|
ALLOWED_HOSTS = os.environ.get("DJANGO_ALLOWED_HOSTS", "127.0.0.1").split(",")
|
||||||
CORS_ALLOWED_ORIGINS = ["http://localhost:3000"]
|
CORS_ALLOWED_ORIGINS = ["http://localhost:3000"]
|
||||||
|
|
||||||
|
|
||||||
# Application definition
|
# Application definition
|
||||||
|
|
||||||
INSTALLED_APPS = [
|
INSTALLED_APPS = [
|
||||||
"django.contrib.admin",
|
"django.contrib.admin",
|
||||||
"django.contrib.auth",
|
"django.contrib.auth",
|
||||||
"django.contrib.contenttypes",
|
"django.contrib.contenttypes",
|
||||||
"corsheaders",
|
|
||||||
"django.contrib.sessions",
|
"django.contrib.sessions",
|
||||||
"django.contrib.messages",
|
"django.contrib.messages",
|
||||||
"django.contrib.staticfiles",
|
"django.contrib.staticfiles",
|
||||||
|
@ -42,7 +44,7 @@ INSTALLED_APPS = [
|
||||||
"rest_framework.authtoken",
|
"rest_framework.authtoken",
|
||||||
"knox",
|
"knox",
|
||||||
"movie_manager",
|
"movie_manager",
|
||||||
"users",
|
"corsheaders",
|
||||||
]
|
]
|
||||||
|
|
||||||
MIDDLEWARE = [
|
MIDDLEWARE = [
|
||||||
|
@ -76,6 +78,7 @@ TEMPLATES = [
|
||||||
|
|
||||||
WSGI_APPLICATION = "movienight.wsgi.application"
|
WSGI_APPLICATION = "movienight.wsgi.application"
|
||||||
|
|
||||||
|
|
||||||
# Database
|
# Database
|
||||||
# https://docs.djangoproject.com/en/5.1/ref/settings/#databases
|
# https://docs.djangoproject.com/en/5.1/ref/settings/#databases
|
||||||
|
|
||||||
|
@ -92,6 +95,7 @@ DATABASES = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
# Password validation
|
# Password validation
|
||||||
# https://docs.djangoproject.com/en/5.1/ref/settings/#auth-password-validators
|
# https://docs.djangoproject.com/en/5.1/ref/settings/#auth-password-validators
|
||||||
|
|
||||||
|
@ -110,6 +114,7 @@ AUTH_PASSWORD_VALIDATORS = [
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
# Internationalization
|
# Internationalization
|
||||||
# https://docs.djangoproject.com/en/5.1/topics/i18n/
|
# 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
|
# Django Rest Framework
|
||||||
REST_FRAMEWORK = {
|
REST_FRAMEWORK = {
|
||||||
"DEFAULT_AUTHENTICATION_CLASSES": [
|
"DEFAULT_AUTHENTICATION_CLASSES": [
|
||||||
|
#'rest_framework.authentication.SessionAuthentication',
|
||||||
"knox.auth.TokenAuthentication",
|
"knox.auth.TokenAuthentication",
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,14 +2,14 @@
|
||||||
URL configuration for movienight project.
|
URL configuration for movienight project.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from django.conf import settings
|
import knox
|
||||||
from django.conf.urls.static import static
|
from knox import views as knox_views
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.urls import path, include
|
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 rest_framework.routers import DefaultRouter
|
||||||
|
|
||||||
from movie_db import views as movie_db_views
|
|
||||||
from movie_manager.viewsets import (
|
from movie_manager.viewsets import (
|
||||||
MovieViewset,
|
MovieViewset,
|
||||||
MovieListViewset,
|
MovieListViewset,
|
||||||
|
@ -17,8 +17,11 @@ from movie_manager.viewsets import (
|
||||||
ShowingViewset,
|
ShowingViewset,
|
||||||
)
|
)
|
||||||
from users import views as user_views
|
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 import UserViewSet, GroupViewSet
|
||||||
from users.viewsets.user import register, UserProfileViewSet
|
|
||||||
|
|
||||||
router = DefaultRouter()
|
router = DefaultRouter()
|
||||||
router.register(r"v1/users", UserViewSet)
|
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/lists", MovieListViewset)
|
||||||
router.register(r"v1/schedules", ScheduleViewset)
|
router.register(r"v1/schedules", ScheduleViewset)
|
||||||
router.register(r"v1/showings", ShowingViewset)
|
router.register(r"v1/showings", ShowingViewset)
|
||||||
router.register(r"v1/users/profiles/", UserProfileViewSet)
|
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path("", include(router.urls)),
|
path("", include(router.urls)),
|
||||||
path("admin/", admin.site.urls),
|
path("admin/", admin.site.urls),
|
||||||
path(r"v1/auth/token/", obtain_auth_token),
|
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/login/", user_views.LoginView.as_view(), name="knox_login"),
|
||||||
path(r"v1/auth/register/", register, name="register"),
|
path(r"v1/auth/register/", register, name="register"),
|
||||||
path(r"v1/movies/search", movie_db_views.omdb_search, name="omdb_search"),
|
path(r"v1/movies/search", movie_db_views.omdb_search, name="omdb_search"),
|
||||||
path(r"v1/auth/", include("knox.urls")),
|
path(r"v1/auth/", include("knox.urls")),
|
||||||
path('v1/users/profile', UserProfileViewSet.as_view({"get": "current_user_profile"}),
|
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
|
||||||
name="current_user_profile"),
|
|
||||||
path('v1/users/profiles/<str:user__username>/', UserProfileViewSet.as_view({"get": "retrieve"}))
|
|
||||||
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
|
|
||||||
|
|
|
@ -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)),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -1,12 +1,3 @@
|
||||||
from django.contrib.auth.models import User
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
|
|
||||||
# Create your models here.
|
# 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()
|
|
||||||
|
|
|
@ -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
|
|
|
@ -1,35 +1,12 @@
|
||||||
from django.contrib.auth import authenticate
|
from django.contrib.auth import authenticate
|
||||||
from django.contrib.auth.models import User, Group
|
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
from django.contrib.auth.models import User, Group
|
||||||
from movie_manager.serializers import MovieListSerializer
|
|
||||||
from users.models import UserProfile
|
|
||||||
|
|
||||||
|
|
||||||
class UserSerializer(serializers.HyperlinkedModelSerializer):
|
class UserSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = User
|
model = User
|
||||||
fields = ["url", "username", "email", "groups"]
|
fields = ["url", "username", "email", "password", "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
|
|
||||||
|
|
||||||
|
|
||||||
class GroupSerializer(serializers.HyperlinkedModelSerializer):
|
class GroupSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
|
|
|
@ -1,13 +1,10 @@
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User, Group
|
||||||
from django.http import JsonResponse
|
|
||||||
from knox.auth import TokenAuthentication
|
from knox.auth import TokenAuthentication
|
||||||
from rest_framework import viewsets, permissions, status
|
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 rest_framework.response import Response
|
||||||
|
|
||||||
from users.models import UserProfile
|
from users.serializers import UserSerializer, GroupSerializer
|
||||||
from users.permissions import ReadOnly
|
|
||||||
from users.serializers import UserSerializer, UserProfileSerializer
|
|
||||||
|
|
||||||
|
|
||||||
class UserViewSet(viewsets.ModelViewSet):
|
class UserViewSet(viewsets.ModelViewSet):
|
||||||
|
@ -18,51 +15,6 @@ class UserViewSet(viewsets.ModelViewSet):
|
||||||
serializer_class = UserSerializer
|
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"])
|
@api_view(["POST"])
|
||||||
def register(request):
|
def register(request):
|
||||||
user_data = UserSerializer(data=request.data)
|
user_data = UserSerializer(data=request.data)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue