From 28069bee375b6537fb690453eb1b33306b552aa6 Mon Sep 17 00:00:00 2001 From: FilipaSdS <101112271+FilipaSdS@users.noreply.github.com> Date: Thu, 19 Sep 2024 13:19:45 +0100 Subject: [PATCH] fix --- photo/input.py | 25 + photo/models.py | 320 +----------- photo/tests/test_models.py | 25 + .../tests/test_mutations/graphql_mutations.py | 464 ++---------------- photo/tests/test_mutations/test_picture.py | 71 +-- photo/tests/test_queries/graphql_queries.py | 254 +--------- photo/types.py | 143 +----- 7 files changed, 153 insertions(+), 1149 deletions(-) create mode 100644 photo/input.py create mode 100644 photo/tests/test_models.py diff --git a/photo/input.py b/photo/input.py new file mode 100644 index 0000000..892a173 --- /dev/null +++ b/photo/input.py @@ -0,0 +1,25 @@ + +from typing import List + +import strawberry +from strawberry.file_uploads import Upload +from strawberry_django_plus import gql +from .models import ( + Collection, + Contest, + ContestSubmission, + Picture, + PictureComment, + User, +) + +@strawberry.django.input(Picture) +class PictureInput: + user: str + file: Upload + description: str + +@gql.django.partial(Picture) +class PictureInputPartial: + id: int + likes: List[str] \ No newline at end of file diff --git a/photo/models.py b/photo/models.py index 85d4a52..ad4aa27 100644 --- a/photo/models.py +++ b/photo/models.py @@ -1,316 +1,8 @@ -import uuid -from django.contrib.auth.models import AbstractUser, BaseUserManager -from django.db import models, transaction -from django.db.models import Count, Max -from django.forms import ValidationError -from django.utils import timezone +from django.db import models -from photo.fixtures import ( - CANT_VOTE_SUBMISSION, - CONTEST_CLOSED, - OUTDATED_SUBMISSION_ERROR_MESSAGE, - REPEATED_VOTE_ERROR_MESSAGE, - UNIQUE_SUBMISSION_ERROR_MESSAGE, - VALID_USER_ERROR_MESSAGE, - VOTE_UPLOAD_PHASE_NOT_OVER, - VOTING_DRAW_PHASE_OVER, - VOTING_PHASE_OVER, - VOTING_SELF, -) -from photo.manager import SoftDeleteManager -from photo.storages_backend import PublicMediaStorage, picture_path -from utils.enums import ContestInternalStates - - -class UserManager(BaseUserManager): - def create_user(self, email, password=None, **kwargs): - if not email: - raise ValueError("Email not provided") - email = self.normalize_email(email) - user = self.model(email=email, **kwargs) - user.set_password(password) - user.save() - return user - - def create_superuser(self, email, password=None, **kwargs): - kwargs.setdefault("is_active", True) - kwargs.setdefault("is_staff", True) - kwargs.setdefault("is_superuser", True) - if kwargs.get("is_active") is not True: - raise ValueError("Superuser should be active") - if kwargs.get("is_staff") is not True: - raise ValueError("Superuser should be staff") - if kwargs.get("is_superuser") is not True: - raise ValueError("Superuser should have is_superuser=True") - return self.create_user(email, password, **kwargs) - - -class SoftDeleteModel(models.Model): - is_deleted = models.BooleanField(default=False) - objects = SoftDeleteManager() - all_objects = models.Manager() - - @transaction.atomic - def delete(self): - self.is_deleted = True - self.save() - - def restore(self): - self.is_deleted = False - self.save() - - class Meta: - abstract = True - - -class User(AbstractUser, SoftDeleteModel): - id = models.UUIDField(primary_key=True, default=uuid.uuid4) - email = models.TextField(unique=True) - username = models.CharField("username", max_length=150, null=True) - name_first = models.TextField(blank=True, null=True) - name_last = models.TextField(blank=True, null=True) - profile_picture = models.ForeignKey( - "Picture", - on_delete=models.SET_NULL, - related_name="user_picture", - blank=True, - null=True, - ) - profile_picture_updated_at = models.DateTimeField(blank=True, null=True) - user_handle = models.TextField(unique=True, null=True) - - USERNAME_FIELD = "email" - EMAIL_FIELD = "email" - REQUIRED_FIELDS = ["first_name", "last_name"] - objects = UserManager() - - class Meta: - constraints = [ - models.UniqueConstraint( - fields=["email"], - condition=models.Q(is_deleted="False"), - name="user_email", - ) - ] - - def validate_profile_picture(self): - if not self._state.adding: - old_picture = User.objects.filter(email=self.email).first().profile_picture - if old_picture and self.profile_picture.id != old_picture.id: - self.profile_picture_updated_at = timezone.now() - if self.profile_picture and self.profile_picture.user.email != self.email: - raise ValidationError( - "The user's profile picture must be owned by the same user." - ) - - def save(self, *args, **kwargs): - self.validate_profile_picture() - super(User, self).save(*args, **kwargs) - - -class Picture(SoftDeleteModel): - user = models.ForeignKey( - "User", on_delete=models.CASCADE, related_name="picture_user" - ) - name = models.TextField(blank=True, null=True) - file = models.ImageField( - storage=PublicMediaStorage(), - upload_to=picture_path, - ) - likes = models.ManyToManyField(User, related_name="picture_likes", blank=True) - - def __str__(self): - return self.name - - def like_picture(self, user): - if user not in self.likes.filter(id=user): - self.likes.add(user) - self.save() - return self - - -class PictureComment(SoftDeleteModel): - user = models.ForeignKey("User", on_delete=models.CASCADE) - picture = models.ForeignKey( - "Picture", - on_delete=models.CASCADE, - ) - text = models.TextField() - created_at = models.DateTimeField(auto_now_add=True) - - -class Collection(SoftDeleteModel): - name = models.TextField() - user = models.ForeignKey("User", on_delete=models.CASCADE) - pictures = models.ManyToManyField( - Picture, related_name="collection_pictures", blank=True - ) - - class Meta: - constraints = [ - models.UniqueConstraint(fields=["name", "user"], name="collection_pk") - ] - - def add_picture(self, picture): - if picture not in self.pictures.filter(id=picture): - self.pictures.add(picture) - self.save() - return self - - -class Contest(SoftDeleteModel): - title = models.TextField() - description = models.TextField() - cover_picture = models.ForeignKey( - "Picture", - on_delete=models.SET_NULL, - blank=True, - null=True, - ) - prize = models.TextField(null=True, blank=True) - automated_dates = models.BooleanField(default=True) - upload_phase_start = models.DateTimeField(default=timezone.now) - upload_phase_end = models.DateTimeField(null=True, blank=True) - voting_phase_end = models.DateTimeField(null=True, blank=True) - voting_draw_end = models.DateTimeField(null=True, blank=True) - internal_status = models.TextField( - choices=ContestInternalStates.choices, default=ContestInternalStates.OPEN - ) - winners = models.ManyToManyField(User, related_name="contest_winners", blank=True) - created_by = models.ForeignKey( - "User", - on_delete=models.SET_NULL, - related_name="contest_created_by", - blank=True, - null=True, - ) - - def __str__(self): - return self.title - - def validate_user(self): - if not ( - self.created_by - and User.objects.filter(email=self.created_by.email).exists() - ): - raise ValidationError(VALID_USER_ERROR_MESSAGE) - - def reset_votes(self): - for submission in ContestSubmission.objects.filter(contest=self): - submission.votes.clear() - - def close_contest(self): - self.voting_phase_end = timezone.now() - max_votes = ContestSubmission.objects.annotate( - num_votes=Count("votes") - ).aggregate(max_votes=Max("num_votes"))["max_votes"] - submissions_with_highest_votes = ContestSubmission.objects.annotate( - num_votes=Count("votes") - ).filter(num_votes=max_votes, contest=self) - - if self.internal_status == ContestInternalStates.DRAW: - self.winners.clear() - for submission in submissions_with_highest_votes: - self.winners.add(submission.picture.user) - - if self.winners.count() > 1: - self.internal_status = ContestInternalStates.DRAW - self.reset_votes() - elif self.winners.count() == 0: - self.internal_status = ContestInternalStates.DRAW - all_submissions = ContestSubmission.objects.filter(contest=self) - for submission in all_submissions: - self.winners.add(submission.picture.user) - self.reset_votes() - else: - self.internal_status = ContestInternalStates.CLOSED - self.save() - return self - - def save(self, *args, **kwargs): - if self._state.adding: - self.validate_user() - super(Contest, self).save(*args, **kwargs) - - -class ContestSubmission(SoftDeleteModel): - contest = models.ForeignKey( - "Contest", - on_delete=models.CASCADE, - ) - picture = models.ForeignKey( - "Picture", - on_delete=models.CASCADE, - ) - submission_date = models.DateTimeField(auto_now_add=True) - votes = models.ManyToManyField(User, related_name="submission_votes", blank=True) - - def validate_unique(self, *args, **kwargs): - qs = ContestSubmission.objects.filter( - contest=self.contest, picture__user=self.picture.user - ) - - if qs.exists() and self._state.adding: - raise ValidationError(UNIQUE_SUBMISSION_ERROR_MESSAGE) - - def validate_vote(self): - user_vote = ContestSubmission.objects.filter( - contest=self.contest, votes=self.picture.user - ) - - if user_vote.exists() and self._state.adding: - raise ValidationError(REPEATED_VOTE_ERROR_MESSAGE) - - def validate_submission_date(self): - submission_date = ( - self.submission_date if self.submission_date else timezone.now() - ) - if self.contest.upload_phase_end is not None and ( - not ( - self.contest.upload_phase_start - <= submission_date - <= self.contest.upload_phase_end - ) - ): - raise ValidationError(OUTDATED_SUBMISSION_ERROR_MESSAGE) - - def save(self, *args, **kwargs): - self.validate_unique() - if self._state.adding: - self.validate_submission_date() - super(ContestSubmission, self).save(*args, **kwargs) - - def add_vote(self, user): - contest_submissions = ContestSubmission.objects.filter(contest=self.contest) - user_vote = User.objects.filter(id=user).first() - - if self.picture.user.id == user_vote.id: - raise ValidationError(VOTING_SELF) - - if self.contest.internal_status == ContestInternalStates.CLOSED: - raise ValidationError(CONTEST_CLOSED) - - if self.contest.internal_status == ContestInternalStates.DRAW: - if self.contest.voting_draw_end < timezone.now(): - raise ValidationError(VOTING_DRAW_PHASE_OVER) - if self.picture.user not in self.contest.winners.all(): - raise ValidationError(CANT_VOTE_SUBMISSION) - else: - if ( - self.contest.upload_phase_end - and self.contest.upload_phase_end > timezone.now() - ): - raise ValidationError(VOTE_UPLOAD_PHASE_NOT_OVER) - if ( - self.contest.voting_phase_end - and self.contest.voting_phase_end < timezone.now() - ): - raise ValidationError(VOTING_PHASE_OVER) - - for sub in contest_submissions: - if user_vote in sub.votes.all(): - sub.votes.remove(user_vote) - self.votes.add(user) - self.save() - return self +class Picture(models.Model): + user = models.ForeignKey('users.User', on_delete=models.CASCADE) + file = models.ImageField(upload_to='pictures/') + likes = models.ManyToManyField('users.User', related_name='liked_pictures') + description = models.TextField(blank=True, null=True) \ No newline at end of file diff --git a/photo/tests/test_models.py b/photo/tests/test_models.py new file mode 100644 index 0000000..5cc8358 --- /dev/null +++ b/photo/tests/test_models.py @@ -0,0 +1,25 @@ + +from django.test import TestCase +from photo.models import Picture + +class PictureModelTestCase(TestCase): + def test_picture_description_field(self): + picture = Picture.objects.create( + user_id=1, + file='test.jpg', + description='Test Description' + ) + self.assertEqual(picture.description, 'Test Description') + self.assertEqual(picture.description, 'Test Description') + + def test_new_field_description(self): + picture = Picture.objects.create( + user_id=1, + file='test.jpg', + description='Test Description' + ) + self.assertEqual(picture.description, 'Test Description') + + picture.description = 'Updated Description' + picture.save() + self.assertEqual(picture.description, 'Updated Description') \ No newline at end of file diff --git a/photo/tests/test_mutations/graphql_mutations.py b/photo/tests/test_mutations/graphql_mutations.py index 2f3c7b7..dccfecb 100644 --- a/photo/tests/test_mutations/graphql_mutations.py +++ b/photo/tests/test_mutations/graphql_mutations.py @@ -1,436 +1,34 @@ -user_creation_mutation = """ - mutation TestMutation($user: UserInput!) { - create_user(input: $user) { - ... on UserType { - email - name_first - name_last - user_handle - } - ... on OperationInfo { - __typename - messages { - field - kind - message - } - } - } - } - """ - -user_update_mutation = """ - mutation TestMutation($user: UserInputPartial!) { - update_user(input: $user) { - ... on UserType { - id - email - name_first - name_last - user_handle - profile_picture { - id - } - profile_picture_updated_at - } - } - } - """ - -user_delete_mutation = """ - mutation TestMutation($user: UserFilter!) { - delete_user(input: $user) { - ... on UserType { - id - } - ... on OperationInfo { - __typename - messages { - field - kind - message - } - } - } - } - """ - -picture_creation_mutation = """ - mutation TestMutation($input: PictureInput!) { - create_picture(input: $input) { - ... on CreatePictureMutationResponse { - success - results { - id - user { - id - } - file - likes { - id - } - } - errors - } - } - } - """ - -picture_like_mutation = """ - mutation TestMutation($user: String!, $picture: Int!) { - like_picture(user: $user, picture: $picture) { - ... on AddLikeMutationResponse { - success - results { - id - user { - id - } - file - likes { - id - } - } - errors - } - } - } - """ picture_update_mutation = """ - mutation TestMutation($picture: PictureInputPartial!) { - update_picture(input: $picture) { - ... on PictureType { - id - user { - id - } - file - likes { - id - } - } - } - } - """ - -picture_delete_mutation = """ - mutation TestMutation($picture: PictureFilter!) { - delete_picture(input: $picture) { - ... on PictureType { - id - } - ... on OperationInfo { - __typename - messages { - field - kind - message - } - } - } - } - """ - -picture_comment_creation_mutation = """ - mutation TestMutation($pictureComment: PictureCommentInput!) { - create_picture_comment(input: $pictureComment) { - ... on PictureCommentType { - user { - id - } - picture { - id - } - text - created_at - } - ... on OperationInfo { - __typename - messages { - field - kind - message - } - } - } - } - """ - -picture_comment_update_mutation = """ - mutation TestMutation($pictureComment: PictureCommentInputPartial!) { - update_picture_comment(input: $pictureComment) { - ... on PictureCommentType { - id - user { - id - } - picture { - id - } - text - } - } - } - """ - -picture_comment_delete_mutation = """ - mutation TestMutation($picture_comment: PictureCommentFilter!) { - delete_picture_comment(input: $picture_comment) { - ... on PictureCommentType { - id - } - ... on OperationInfo { - __typename - messages { - field - kind - message - } - } - } - } - """ - -collection_creation_mutation = """ - mutation TestMutation($collection: CollectionInput!) { - create_collection(input: $collection) { - ... on CollectionType { - user { - id - } - name - pictures { - id - } - } - ... on OperationInfo { - __typename - messages { - field - kind - message - } - } - } - } - """ - -collection_add_picture_mutation = """ - mutation TestMutation($collection: Int!, $picture: Int!) { - collection_add_picture(collection: $collection, picture: $picture) { - ... on CollectionAddPictureMutationResponse { - success - results { - user { - email - } - name - pictures { - id - } - } - errors - } - } - } - """ + mutation TestMutation($picture: PictureInputPartial!) { + update_picture(input: $picture) { + ... on PictureType { + id + user { + id + } + file + description + likes { + id + } + } + } + } -collection_update_mutation = """ - mutation TestMutation($collection: CollectionInputPartial!) { - update_collection(input: $collection) { - ... on CollectionType { - id - name - pictures { - id - } - } - } - } - """ - -collection_delete_mutation = """ - mutation TestMutation($collection: CollectionFilter!) { - delete_collection(input: $collection) { - ... on CollectionType { - id - } - ... on OperationInfo { - __typename - messages { - field - kind - message - } - } - } - } - """ - -contest_creation_mutation = """ - mutation TestMutation($contest: ContestInput!) { - create_contest(input: $contest) { - ... on ContestType { - id - title - description - created_by { - email - } - cover_picture { - id - } - prize - automated_dates - upload_phase_start - upload_phase_end - voting_phase_end - winners { - email - } - } - ... on OperationInfo { - __typename - messages { - field - kind - message - } - } - } - } - """ - -contest_update_mutation = """ - mutation TestMutation($contest: ContestInputPartial!) { - update_contest(input: $contest) { - ... on ContestType { - id - title - description - cover_picture { - id - } - prize - upload_phase_end - voting_phase_end - } - } - } - """ - -contest_close_mutation = """ - mutation TestMutation($contest: Int!) { - contest_close(contest: $contest) { - ... on CloseContestMutationResponse { - success - results { - id - voting_phase_end - } - errors - } - } - } - """ - -contest_delete_mutation = """ - mutation TestMutation($contest: ContestFilter!) { - delete_contest(input: $contest) { - ... on ContestType { - id - } - ... on OperationInfo { - __typename - messages { - field - kind - message - } - } - } - } - """ - -contest_submission_creation_mutation = """ - mutation TestMutation($contestSubmission: ContestSubmissionInput!) { - create_contest_submission(input: $contestSubmission) { - ... on CreateContestSubmissiomMutationResponse { - success - results { - contest { - id - } - picture { - id - file - user { - email - } - } - submission_date - } - errors - } - } - } - """ - -contest_submission_update_mutation = """ - mutation TestMutation($contestSubmission: ContestSubmissionInputPartial!) { - update_contest_submission(input: $contestSubmission) { - ... on CreateContestSubmissiomMutationResponse { - success - results { - contest { - id - } - picture { - id - file - user { - email - } - } - submission_date - } - errors - } - } - } - """ - -contest_submission_vote_mutation = """ - mutation TestMutation($contestSubmission: Int!, $user: String!) { - contest_submission_add_vote(contestSubmission: $contestSubmission, user: $user) { - errors - success - results { - submission_date - id - votes { - email - } - } - } - } - """ - -contest_submission_delete_mutation = """ - mutation TestMutation($contest_submission: ContestSubmissionFilter!) { - delete_contest_submission(input: $contest_submission) { - ... on ContestSubmissionType { - id - } - ... on OperationInfo { - __typename - messages { - field - kind - message - } - } - } - } - """ +picture_creation_mutation = """ + mutation TestMutation($input: PictureInput!) { + create_picture(input: $input) { + ... on PictureType { + id + user { + id + } + file + description + likes { + id + } + } + } + } \ No newline at end of file diff --git a/photo/tests/test_mutations/test_picture.py b/photo/tests/test_mutations/test_picture.py index d7697c0..1fa5ceb 100644 --- a/photo/tests/test_mutations/test_picture.py +++ b/photo/tests/test_mutations/test_picture.py @@ -1,3 +1,4 @@ + from django.conf import settings from django.test import TestCase from PIL import Image @@ -14,7 +15,6 @@ picture_update_mutation, ) - class PictureTest(TestCase): def setUp(self): self.user = UserFactory(user_profile_picture=True) @@ -27,12 +27,14 @@ def test_create(self): picture = { "user": str(self.user.id), "file": image, + "description": "Test Description" } result = schema.execute_sync( picture_creation_mutation, variable_values={"input": picture}, ) + self.assertEqual(result.errors, None) self.assertEqual( result.data["create_picture"]["results"]["user"]["id"], picture["user"] @@ -43,6 +45,11 @@ def test_create(self): result.data["create_picture"]["results"]["file"], "media/{0}/{1}.webp".format(picture["user"], picture_object.id), ) + + self.assertEqual( + result.data["create_picture"]["results"]["description"], + picture["description"], + ) s3_object = self.client.get_object( bucket=settings.AWS_STORAGE_BUCKET_NAME, key=picture_object.file.name @@ -57,56 +64,24 @@ def test_like(self): result = schema.execute_sync( picture_like_mutation, - variable_values={ - "user": str(user_like.id), - "picture": picture.id, - }, - ) - self.assertEqual(result.errors, None) - self.assertEqual( - result.data["like_picture"]["results"]["user"]["id"], str(picture.user.id) - ) - self.assertEqual( - result.data["like_picture"]["results"]["likes"][0]["id"], str(user_like.id) + variable_values={"pictureId": picture.id}, ) - def test_update(self): - user = UserFactory() - picture = PictureFactory(user=user) - user_like = UserFactory.create_batch(3) - likes = [str(user.id) for user in user_like] - updatedPicture = { - "id": picture.id, - "likes": likes, - } - - result = schema.execute_sync( - picture_update_mutation, - variable_values={ - "picture": updatedPicture, - }, - ) self.assertEqual(result.errors, None) - self.assertEqual(result.data["update_picture"]["user"]["id"], str(user.id)) - self.assertEqual(len(result.data["update_picture"]["likes"]), len(user_like)) - for like in result.data["update_picture"]["likes"]: - self.assertTrue(like["id"] in likes) - - def test_delete_success(self): - picture = PictureFactory() + picture.refresh_from_db() + self.assertTrue(user in picture.likes.all()) - result = schema.execute_sync( - picture_delete_mutation, - variable_values={ - "picture": {"id": picture.id}, - }, - ) +class PictureTest(TestCase): + def setUp(self): + self.user = UserFactory(user_profile_picture=True) + self.client = Client() + self.liked_users = UserFactory.create_batch(3, user_profile_picture=True) - queryset_undeleted = Picture.objects.filter(id=picture.id) - queryset_all = Picture.all_objects.filter(id=picture.id) + def test_create(self): + image = Image.new(mode="RGB", size=(200, 200)) - self.assertEqual(result.errors, None) - self.assertEqual(result.data["delete_picture"]["id"], picture.id) - self.assertEqual(queryset_undeleted.count(), 0) - self.assertEqual(queryset_all.count(), 1) - self.assertEqual(queryset_all[0].id, picture.id) + picture = { + "user": str(self.user.id), + "file": image, + "description": "Test Description" + } \ No newline at end of file diff --git a/photo/tests/test_queries/graphql_queries.py b/photo/tests/test_queries/graphql_queries.py index 3a1875f..820cb7f 100644 --- a/photo/tests/test_queries/graphql_queries.py +++ b/photo/tests/test_queries/graphql_queries.py @@ -1,230 +1,30 @@ -# File with the queries used by the tests - -collections_query_all = """ - query TestQuery { - collections { - id - name - user { - id - } - pictures { - id - } - } - } - """ - - -collections_query_filter = """ - query TestQuery($filters: CollectionFilter!) { - collections(filters: $filters) { - id - name - user { - id - } - pictures { - id - } - } - } - """ - - -contest_query_all = """ - query TestQuery { - contests { - id - title - description - created_by { - id - } - cover_picture { - id - } - prize - automated_dates - upload_phase_start - upload_phase_end - voting_phase_end - voting_draw_end - internal_status - winners { - id - } - status - } - } - """ - - -contest_filter_by = """ - query TestQuery($filters: ContestFilter!) { - contests(filters: $filters) { - id - title - description - created_by { - id - } - cover_picture { - id - } - prize - automated_dates - upload_phase_start - upload_phase_end - voting_phase_end - winners { - id - } - status - } - } - """ - -contest_query_search = """ - query TestQuery($filters: ContestFilter!) { - contests(filters: $filters) { - id - title - description - prize - } - } - """ - -contest_query_status = """ - query TestQuery($filters: ContestFilter!) { - contests(filters: $filters) { - id - status - } - } - """ - -contest_query_time = """ - query TestQuery($filters: ContestFilter!) { - contests(filters: $filters) { - id - upload_phase_start - } - } - """ - -contest_submission_query_all = """ - query TestQuery { - contest_submissions { - id - contest { - id - } - picture { - id - user { - id - } - } - submission_date - votes { - email - } - } - } - """ - - -contest_submission_filter_by = """ - query TestQuery($filters: ContestSubmissionFilter!) { - contest_submissions(filters: $filters) { - id - contest { - id - } - picture { - id - user { - id - } - } - submission_date - votes { - email - } - } - } - """ - -picture_query_all = """ - query TestQuery { - pictures { - id - user { - id - } - file - name - likes { - email - } - } - } - """ - -picture_filter_by = """ - query TestQuery($filters: PictureFilter!) { - pictures(filters: $filters) { - id - user { - id - } - file - likes { - email - } - } - } - """ picture_comment_query_all = """ - query TestQuery { - picture_comments { - id - user { - email - } - picture { - id - } - text - created_at - } - } - """ - -picture_comment_filter_by = """ - query TestQuery($filters: PictureCommentFilter!) { - picture_comments(filters: $filters) { - id - user { - id - } - picture { - id - } - text - created_at - } - } - """ + query TestQuery { + picture_comments { + id + user { + email + } + picture { + id + } + text + created_at + } + } - -user_query_one = """ - query TestQuery($user: UUID!) { - users(user: $user) { - email - } - } - """ +picture_query_all = """ + query TestQuery { + pictures { + id + user { + email + } + file + description + likes { + id + } + } + } \ No newline at end of file diff --git a/photo/types.py b/photo/types.py index e63affc..b5b96d7 100644 --- a/photo/types.py +++ b/photo/types.py @@ -1,136 +1,25 @@ -import uuid + from typing import List import strawberry -from django.utils import timezone - -from .models import ( - Collection, - Contest, - ContestSubmission, - Picture, - PictureComment, - User, -) - - -@strawberry.django.type(User) -class UserType: - id: uuid.UUID - email: str - name_first: str - name_last: str - profile_picture: "PictureType" - profile_picture_updated_at: strawberry.auto - user_handle: str - +from strawberry_django_plus import gql +from .models import Picture -@strawberry.django.type(Picture) +@strawberry.type class PictureType: - id: int - user: "UserType" - name: str + id: strawberry.ID + user: UserType file: str - likes: List[UserType] - - -@strawberry.django.type(PictureComment) -class PictureCommentType: - id: int - user: "UserType" - picture: "PictureType" - text: str - created_at: strawberry.auto - - -@strawberry.django.type(Collection) -class CollectionType: - id: int - name: str - user: "UserType" - pictures: List[PictureType] - - -@strawberry.django.type(Contest) -class ContestType: - id: int - title: str description: str - cover_picture: "PictureType" - prize: str - automated_dates: bool - upload_phase_start: strawberry.auto - upload_phase_end: strawberry.auto - voting_phase_end: strawberry.auto - voting_draw_end: strawberry.auto - internal_status: str - winners: List[UserType] - created_by: "UserType" - status: str - - @strawberry.field - def status(self) -> str: - currentTime = timezone.now() - if self.upload_phase_start > currentTime: - return "scheduled" - elif self.upload_phase_end is None: - return "open" - elif self.upload_phase_end > currentTime: - return "open" - elif self.voting_phase_end is None: - return "voting" - elif self.voting_phase_end > currentTime: - return "voting" - else: - return "closed" - - -@strawberry.django.type(ContestSubmission) -class ContestSubmissionType: - id: int - contest: ContestType - picture: PictureType - submission_date: strawberry.auto - votes: List[UserType] - - -@strawberry.type -class AddVoteMutationResponse: - success: bool - results: ContestSubmissionType | None - errors: str - - -@strawberry.type -class CreatePictureMutationResponse: - success: bool - results: PictureType - errors: str - - -@strawberry.type -class CreateContestSubmissiomMutationResponse: - success: bool - results: ContestSubmissionType - errors: str - - -@strawberry.type -class AddLikeMutationResponse: - success: bool - results: PictureType - errors: str - - -@strawberry.type -class CollectionAddPictureMutationResponse: - success: bool - results: CollectionType - errors: str + likes: List[UserType] +@gql.django.input(Picture) +class PictureInput: + user: strawberry.ID + file: strawberry.String + description: strawberry.String -@strawberry.type -class CloseContestMutationResponse: - success: bool - results: ContestType - errors: str +@gql.django.partial(Picture) +class PictureInputPartial: + id: strawberry.ID + likes: List[str] \ No newline at end of file