diff --git a/backend/animanga_project/__pycache__/settings.cpython-311.pyc b/backend/animanga_project/__pycache__/settings.cpython-311.pyc index e265bd56..cbe78e32 100644 Binary files a/backend/animanga_project/__pycache__/settings.cpython-311.pyc and b/backend/animanga_project/__pycache__/settings.cpython-311.pyc differ diff --git a/backend/animanga_project/__pycache__/urls.cpython-311.pyc b/backend/animanga_project/__pycache__/urls.cpython-311.pyc index 6db12d90..d75dc586 100644 Binary files a/backend/animanga_project/__pycache__/urls.cpython-311.pyc and b/backend/animanga_project/__pycache__/urls.cpython-311.pyc differ diff --git a/backend/animanga_project/settings.py b/backend/animanga_project/settings.py index 45ae4241..a111da0d 100644 --- a/backend/animanga_project/settings.py +++ b/backend/animanga_project/settings.py @@ -41,12 +41,15 @@ # 3rd party 'rest_framework', + 'corsheaders', # local 'api', ] MIDDLEWARE = [ + 'corsheaders.middleware.CorsMiddleware', + 'django.middleware.common.CommonMiddleware', 'whitenoise.middleware.WhiteNoiseMiddleware', 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', @@ -57,6 +60,8 @@ 'django.middleware.clickjacking.XFrameOptionsMiddleware', ] +CORS_ORIGIN_ALLOW_ALL = True + STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage' ROOT_URLCONF = 'animanga_project.urls' @@ -142,5 +147,5 @@ } -MEDIA_ROOT = 'images/' -MEDIA_URL= 'images/' \ No newline at end of file +MEDIA_ROOT = os.path.join(BASE_DIR, 'images') +MEDIA_URL= '/images/' \ No newline at end of file diff --git a/backend/api/__pycache__/models.cpython-311.pyc b/backend/api/__pycache__/models.cpython-311.pyc index a38587ac..1126ac41 100644 Binary files a/backend/api/__pycache__/models.cpython-311.pyc and b/backend/api/__pycache__/models.cpython-311.pyc differ diff --git a/backend/api/__pycache__/serializers.cpython-311.pyc b/backend/api/__pycache__/serializers.cpython-311.pyc index 322267c4..73f56b13 100644 Binary files a/backend/api/__pycache__/serializers.cpython-311.pyc and b/backend/api/__pycache__/serializers.cpython-311.pyc differ diff --git a/backend/api/__pycache__/tests.cpython-311.pyc b/backend/api/__pycache__/tests.cpython-311.pyc new file mode 100644 index 00000000..89411633 Binary files /dev/null and b/backend/api/__pycache__/tests.cpython-311.pyc differ diff --git a/backend/api/__pycache__/urls.cpython-311.pyc b/backend/api/__pycache__/urls.cpython-311.pyc index 898547e4..4314c75a 100644 Binary files a/backend/api/__pycache__/urls.cpython-311.pyc and b/backend/api/__pycache__/urls.cpython-311.pyc differ diff --git a/backend/api/__pycache__/views.cpython-311.pyc b/backend/api/__pycache__/views.cpython-311.pyc index 6a4ece91..e6ad2164 100644 Binary files a/backend/api/__pycache__/views.cpython-311.pyc and b/backend/api/__pycache__/views.cpython-311.pyc differ diff --git a/backend/api/models.py b/backend/api/models.py index 200369c7..acb5d9ad 100644 --- a/backend/api/models.py +++ b/backend/api/models.py @@ -10,6 +10,8 @@ class Anime(models.Model): start_date = models.DateField(default=None) end_date = models.DateField(default=None) + +# TODO , implement this ImageField, when you have more knowledge about django.. image = models.ImageField(default=None, upload_to='images') background_image = models.ImageField(default=None, upload_to='images') @@ -21,7 +23,7 @@ class Anime(models.Model): episodes = models.IntegerField(default=0) - yt_trailer = models.TextField(default=None) + yt_trailer = models.URLField(default=None) diff --git a/backend/api/serializers.py b/backend/api/serializers.py index 178e9499..c4bdb7bf 100644 --- a/backend/api/serializers.py +++ b/backend/api/serializers.py @@ -4,4 +4,8 @@ class AnimeSerializer(serializers.ModelSerializer): class Meta: model = Anime - fields = ('id', 'title','genre', 'seasons','start_date', 'end_date', 'image','background_image','num_of_fav','description', 'studio', 'episodes', 'yt_trailer', ) \ No newline at end of file + fields = ('id', 'title','genre', 'seasons','start_date', 'end_date','num_of_fav','description', 'studio', 'episodes', 'yt_trailer',) + # fields = '__all__' + + + \ No newline at end of file diff --git a/backend/api/templates/api/show_image.html b/backend/api/templates/api/show_image.html deleted file mode 100644 index 1433e881..00000000 --- a/backend/api/templates/api/show_image.html +++ /dev/null @@ -1,2 +0,0 @@ -{% load static %} - \ No newline at end of file diff --git a/backend/api/tests.py b/backend/api/tests.py index 7ce503c2..ce5da069 100644 --- a/backend/api/tests.py +++ b/backend/api/tests.py @@ -1,3 +1,167 @@ + from django.test import TestCase +from .models import Anime + + +# api endpoints test +from django.urls import reverse +from rest_framework import status +from rest_framework.test import APIClient + + +# test for models, database +class ApiModelTest(TestCase): + + # create database + @classmethod + def setUpTestData(cls): + Anime.objects.create( + title="hello", + genre="horror", + seasons=20, + start_date="2023-03-17", + end_date="2023-03-17", + num_of_fav=3, + description="My anime", + studio="Shinka", + episodes=35, + yt_trailer="https://yts.mx/" + ) + + # and then check (test) each field + def test_title_content(self): + api = Anime.objects.get(id=1) + expected_object_name = f'{api.title}' + self.assertEquals(expected_object_name, 'hello') + + def test_genre_content(self): + api = Anime.objects.get(id=1) + expected_object_name = f'{api.genre}' + self.assertEquals(expected_object_name, 'horror') + + def test_season_content(self): + api = Anime.objects.get(id=1) + expected_object_name = f'{api.seasons}' + self.assertEquals(expected_object_name, '20') + + def test_start_date_content(self): + api = Anime.objects.get(id=1) + expected_object_name = f'{api.start_date}' + self.assertEquals(expected_object_name, "2023-03-17") + + def test_end_date_content(self): + api = Anime.objects.get(id=1) + expected_object_name = f'{api.end_date}' + self.assertEquals(expected_object_name, "2023-03-17") + + def test_num_of_fav_content(self): + api = Anime.objects.get(id=1) + expected_object_name = f'{api.num_of_fav}' + self.assertEquals(expected_object_name, '3') + + def test_description_content(self): + api = Anime.objects.get(id=1) + expected_object_name = f'{api.description}' + self.assertEquals(expected_object_name, "My anime") + + def test_studio_content(self): + api = Anime.objects.get(id=1) + expected_object_name = f'{api.studio}' + self.assertEquals(expected_object_name, "Shinka") + + def test_episodes_content(self): + api = Anime.objects.get(id=1) + expected_object_name = f'{api.episodes}' + self.assertEquals(expected_object_name, '35') + + def test_yt_trailer_content(self): + api = Anime.objects.get(id=1) + expected_object_name = f'{api.yt_trailer}' + self.assertEquals(expected_object_name, "https://yts.mx/") + + + + +# api endpoints test +class ApiTests(TestCase): + def setUp(self): + self.client = APIClient() + self.api_url = reverse('anime_list') + + def test_create_and_retrieve_anime(self): + # Test POST request to create an anime + data = { + "title": "hello", + "genre": "horror", + "seasons": 20, + "start_date": "2023-03-17", + "end_date": "2023-03-17", + "num_of_fav": 3, + "description": "My anime", + "studio": "Shinka", + "episodes": 35, + "yt_trailer": "https://yts.mx/" + } + response = self.client.post(self.api_url, data, format='json') + self.assertEqual(response.status_code, status.HTTP_201_CREATED) + anime_id = response.data['id'] + + # Test GET request to retrieve the created anime + response = self.client.get(reverse('anime_detail', kwargs={'pk': anime_id})) + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual(response.data['title'], 'hello') + + def test_update_anime(self): + # Create an anime to update + anime = Anime.objects.create( + title="hello", + genre="horror", + seasons=20, + start_date="2023-03-17", + end_date="2023-03-17", + num_of_fav=3, + description="My anime", + studio="Shinka", + episodes=35, + yt_trailer="https://yts.mx/" + ) + + # Test PUT request to update the anime + data = { + "title": "Updated Anime", + "genre": "Action", + "seasons": 6, + "start_date": "2023-01-01", + "end_date": "2023-01-01", + "num_of_fav": 5, + "description": "Updated description", + "studio": "Updated Studio", + "episodes": 42, + "yt_trailer": "https://updated-yts.mx/" + } + response = self.client.put(reverse('anime_detail', kwargs={'pk': anime.id}), data, format='json') + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual(response.data['title'], 'Updated Anime') + + def test_delete_anime(self): + # Create an anime to delete + anime = Anime.objects.create( + title="hello", + genre="horror", + seasons=20, + start_date="2023-03-17", + end_date="2023-03-17", + num_of_fav=3, + description="My anime", + studio="Shinka", + episodes=35, + yt_trailer="https://yts.mx/" + ) + + # Test DELETE request to delete the anime + response = self.client.delete(reverse('anime_detail', kwargs={'pk': anime.id})) + self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) -# Create your tests here. + # Verify that the anime is deleted + with self.assertRaises(Anime.DoesNotExist): + Anime.objects.get(id=anime.id) \ No newline at end of file diff --git a/backend/api/urls.py b/backend/api/urls.py index 0c98b1a9..ac1947e5 100644 --- a/backend/api/urls.py +++ b/backend/api/urls.py @@ -2,6 +2,6 @@ from .views import ListAnime,DetailAnime urlpatterns = [ - path('/', DetailAnime.as_view()), - path('', ListAnime.as_view()), + path('/', DetailAnime.as_view(), name="anime_detail"), + path('', ListAnime.as_view(), name="anime_list"), ] \ No newline at end of file diff --git a/backend/api/views.py b/backend/api/views.py index ddd2a077..51402ba9 100644 --- a/backend/api/views.py +++ b/backend/api/views.py @@ -9,10 +9,6 @@ - - - - class DetailAnime(generics.RetrieveUpdateDestroyAPIView): queryset = Anime.objects.all() serializer_class = AnimeSerializer diff --git a/backend/requirements.txt b/backend/requirements.txt index 07889d1c..a54d9409 100644 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -3,4 +3,5 @@ gunicorn packaging whitenoise djangorestframework -Pillow \ No newline at end of file +Pillow +django-cors-headers \ No newline at end of file