Hotfix before deadline
This commit is contained in:
@@ -11,20 +11,22 @@ class CountryListApiView(ListAPIView):
|
|||||||
serializer_class = CountrySerializer
|
serializer_class = CountrySerializer
|
||||||
|
|
||||||
def filter_queryset(self, queryset):
|
def filter_queryset(self, queryset):
|
||||||
regions = self.request.query_params.get("region")
|
regions = self.request.query_params.getlist("region")
|
||||||
|
|
||||||
|
if regions == [""]:
|
||||||
|
return queryset
|
||||||
|
|
||||||
if regions:
|
if regions:
|
||||||
regions_list = regions.split(",")
|
|
||||||
invalid_regions = [
|
invalid_regions = [
|
||||||
region
|
region for region in regions if region not in settings.REGIONS
|
||||||
for region in regions_list
|
|
||||||
if region not in settings.REGIONS
|
|
||||||
]
|
]
|
||||||
if invalid_regions:
|
if invalid_regions:
|
||||||
invalid_regions_str = ", ".join(invalid_regions)
|
invalid_regions_str = ", ".join(invalid_regions)
|
||||||
error_message = f"Invalid region(s): {invalid_regions_str}"
|
error_message = f"Invalid region(s): {invalid_regions_str}"
|
||||||
raise ValidationError(error_message)
|
raise ValidationError(error_message)
|
||||||
|
|
||||||
queryset = queryset.filter(region__in=regions_list)
|
queryset = queryset.filter(region__in=regions)
|
||||||
|
|
||||||
return queryset
|
return queryset
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
from rest_framework import status
|
from rest_framework import status
|
||||||
|
from rest_framework.exceptions import APIException
|
||||||
from rest_framework.permissions import BasePermission
|
from rest_framework.permissions import BasePermission
|
||||||
|
|
||||||
|
|
||||||
class CanAccessPost(BasePermission):
|
class CustomForbidden(APIException):
|
||||||
message = "You do not have permission to access this post."
|
|
||||||
status_code = status.HTTP_404_NOT_FOUND
|
status_code = status.HTTP_404_NOT_FOUND
|
||||||
|
default_detail = "You dont have access to view this post."
|
||||||
|
|
||||||
|
|
||||||
|
class CanAccessPost(BasePermission):
|
||||||
def has_object_permission(self, request, view, obj):
|
def has_object_permission(self, request, view, obj):
|
||||||
if (
|
if (
|
||||||
obj.author.isPublic
|
obj.author.isPublic
|
||||||
@@ -14,7 +17,7 @@ class CanAccessPost(BasePermission):
|
|||||||
):
|
):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
return False
|
raise CustomForbidden
|
||||||
|
|
||||||
|
|
||||||
class CanAccessFeed(BasePermission):
|
class CanAccessFeed(BasePermission):
|
||||||
@@ -29,4 +32,4 @@ class CanAccessFeed(BasePermission):
|
|||||||
):
|
):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
return False
|
raise CustomForbidden
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ from api.posts.models import Post
|
|||||||
|
|
||||||
class PostSerializer(serializers.ModelSerializer):
|
class PostSerializer(serializers.ModelSerializer):
|
||||||
# ruff: noqa: N815
|
# ruff: noqa: N815
|
||||||
author = serializers.ReadOnlyField(source="author.username")
|
author = serializers.SerializerMethodField()
|
||||||
likesCount = serializers.SerializerMethodField()
|
likesCount = serializers.SerializerMethodField()
|
||||||
dislikesCount = serializers.SerializerMethodField()
|
dislikesCount = serializers.SerializerMethodField()
|
||||||
|
|
||||||
@@ -30,7 +30,14 @@ class PostSerializer(serializers.ModelSerializer):
|
|||||||
def get_dislikesCount(self, obj):
|
def get_dislikesCount(self, obj):
|
||||||
return obj.dislikes.count()
|
return obj.dislikes.count()
|
||||||
|
|
||||||
|
def get_author(self, obj):
|
||||||
|
return obj.author.login
|
||||||
|
|
||||||
def validate_tags(self, value):
|
def validate_tags(self, value):
|
||||||
|
if not isinstance(value, list):
|
||||||
|
error = "Tags must be provided as a list."
|
||||||
|
raise serializers.ValidationError(error)
|
||||||
|
|
||||||
for tag in value:
|
for tag in value:
|
||||||
if len(tag) > settings.MAX_TAG_LENGTH:
|
if len(tag) > settings.MAX_TAG_LENGTH:
|
||||||
error = "Each tag must be 20 characters or fewer."
|
error = "Each tag must be 20 characters or fewer."
|
||||||
|
|||||||
@@ -4,12 +4,12 @@ import api.posts.views
|
|||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path(
|
path(
|
||||||
"/create",
|
"/new",
|
||||||
api.posts.views.CreatePostApiView.as_view(),
|
api.posts.views.CreatePostApiView.as_view(),
|
||||||
name="create-post",
|
name="create-post",
|
||||||
),
|
),
|
||||||
path(
|
path(
|
||||||
"/<str:post_id>",
|
"/<uuid:post_id>",
|
||||||
api.posts.views.PostDetailApiView.as_view(),
|
api.posts.views.PostDetailApiView.as_view(),
|
||||||
name="post-detail",
|
name="post-detail",
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ class CreatePostApiView(APIView):
|
|||||||
serializer = PostSerializer(data=request.data)
|
serializer = PostSerializer(data=request.data)
|
||||||
if serializer.is_valid():
|
if serializer.is_valid():
|
||||||
serializer.save(author=request.user)
|
serializer.save(author=request.user)
|
||||||
return Response(serializer.data, status=status.HTTP_201_CREATED)
|
return Response(serializer.data, status=status.HTTP_200_OK)
|
||||||
raise ValidationError(serializer.errors)
|
raise ValidationError(serializer.errors)
|
||||||
|
|
||||||
|
|
||||||
@@ -52,7 +52,9 @@ class MyFeedListApiView(ListAPIView):
|
|||||||
limit = serializer.validated_data.get("limit")
|
limit = serializer.validated_data.get("limit")
|
||||||
offset = serializer.validated_data.get("offset")
|
offset = serializer.validated_data.get("offset")
|
||||||
|
|
||||||
return self.request.user.posts.all()[offset: offset + limit]
|
return self.request.user.posts.order_by("-createdAt").all()[
|
||||||
|
offset: offset + limit
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
class UserFeedListApiView(ListAPIView):
|
class UserFeedListApiView(ListAPIView):
|
||||||
@@ -81,11 +83,11 @@ class UserFeedListApiView(ListAPIView):
|
|||||||
limit = serializer.validated_data.get("limit")
|
limit = serializer.validated_data.get("limit")
|
||||||
offset = serializer.validated_data.get("offset")
|
offset = serializer.validated_data.get("offset")
|
||||||
|
|
||||||
return user.posts.all()[offset: offset + limit]
|
return user.posts.order_by("-createdAt").all()[offset : offset + limit]
|
||||||
|
|
||||||
|
|
||||||
class LikePostApiView(APIView):
|
class LikePostApiView(APIView):
|
||||||
permission_classes = [IsAuthenticated]
|
permission_classes = [IsAuthenticated, CanAccessPost]
|
||||||
|
|
||||||
def post(self, request, post_id):
|
def post(self, request, post_id):
|
||||||
try:
|
try:
|
||||||
@@ -103,7 +105,7 @@ class LikePostApiView(APIView):
|
|||||||
|
|
||||||
|
|
||||||
class DislikePostApiView(APIView):
|
class DislikePostApiView(APIView):
|
||||||
permission_classes = [IsAuthenticated]
|
permission_classes = [IsAuthenticated, CanAccessPost]
|
||||||
|
|
||||||
def post(self, request, post_id):
|
def post(self, request, post_id):
|
||||||
try:
|
try:
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# Generated by Django 4.2.10 on 2024-03-03 15:01
|
# Generated by Django 4.2.10 on 2024-03-04 19:15
|
||||||
|
|
||||||
import api.users.validators
|
import api.users.validators
|
||||||
import django.core.validators
|
import django.core.validators
|
||||||
@@ -30,7 +30,7 @@ class Migration(migrations.Migration):
|
|||||||
('password', models.CharField(max_length=100, validators=[django.core.validators.RegexValidator('^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9]).{6,100}$')])),
|
('password', models.CharField(max_length=100, validators=[django.core.validators.RegexValidator('^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9]).{6,100}$')])),
|
||||||
('countryCode', models.CharField(max_length=2, validators=[django.core.validators.RegexValidator('[a-zA-Z]{2}'), api.users.validators.CountryCodeValidator()])),
|
('countryCode', models.CharField(max_length=2, validators=[django.core.validators.RegexValidator('[a-zA-Z]{2}'), api.users.validators.CountryCodeValidator()])),
|
||||||
('isPublic', models.BooleanField()),
|
('isPublic', models.BooleanField()),
|
||||||
('phone', models.CharField(max_length=20, null=True, validators=[django.core.validators.MaxLengthValidator(20), django.core.validators.RegexValidator('\\+[\\d]+')])),
|
('phone', models.CharField(max_length=20, null=True, validators=[django.core.validators.MaxLengthValidator(20), django.core.validators.RegexValidator('^\\+\\d+')])),
|
||||||
('image', models.URLField(null=True)),
|
('image', models.URLField(null=True)),
|
||||||
('friends', models.ManyToManyField(blank=True, through='users.Friendship', to='users.profile')),
|
('friends', models.ManyToManyField(blank=True, through='users.Friendship', to='users.profile')),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ class Profile(models.Model):
|
|||||||
isPublic = models.BooleanField()
|
isPublic = models.BooleanField()
|
||||||
phone = models.CharField(
|
phone = models.CharField(
|
||||||
max_length=20,
|
max_length=20,
|
||||||
validators=[MaxLengthValidator(20), RegexValidator(r"\+[\d]+")],
|
validators=[MaxLengthValidator(20), RegexValidator(r"^\+\d+")],
|
||||||
null=True,
|
null=True,
|
||||||
)
|
)
|
||||||
image = models.URLField(max_length=200, null=True)
|
image = models.URLField(max_length=200, null=True)
|
||||||
@@ -56,7 +56,6 @@ class Profile(models.Model):
|
|||||||
return self.liked_posts.add(post)
|
return self.liked_posts.add(post)
|
||||||
|
|
||||||
def dislike_post(self, post):
|
def dislike_post(self, post):
|
||||||
print(self, post)
|
|
||||||
self.liked_posts.remove(post)
|
self.liked_posts.remove(post)
|
||||||
return self.disliked_posts.add(post)
|
return self.disliked_posts.add(post)
|
||||||
|
|
||||||
@@ -82,7 +81,7 @@ class Profile(models.Model):
|
|||||||
cls.objects.filter(phone=validated_data.get("phone"))
|
cls.objects.filter(phone=validated_data.get("phone"))
|
||||||
.exclude(id=user_id)
|
.exclude(id=user_id)
|
||||||
.exists()
|
.exists()
|
||||||
):
|
) and validated_data.get("phone") is not None:
|
||||||
errors["phone"] = {"User with this phone already exists"}
|
errors["phone"] = {"User with this phone already exists"}
|
||||||
|
|
||||||
return errors
|
return errors
|
||||||
|
|||||||
@@ -22,8 +22,6 @@ class UpdateProfileSerializer(serializers.ModelSerializer):
|
|||||||
class Meta:
|
class Meta:
|
||||||
model = Profile
|
model = Profile
|
||||||
fields = [
|
fields = [
|
||||||
"login",
|
|
||||||
"email",
|
|
||||||
"countryCode",
|
"countryCode",
|
||||||
"isPublic",
|
"isPublic",
|
||||||
"phone",
|
"phone",
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ class ProfileMeApiView(APIView):
|
|||||||
)
|
)
|
||||||
serializer.save()
|
serializer.save()
|
||||||
|
|
||||||
return Response(serializer.data)
|
return Response(self._get_profile_data(user))
|
||||||
|
|
||||||
raise ValidationError(serializer.errors)
|
raise ValidationError(serializer.errors)
|
||||||
|
|
||||||
@@ -202,9 +202,9 @@ class FriendsListApiView(ListAPIView):
|
|||||||
limit = serializer.validated_data.get("limit")
|
limit = serializer.validated_data.get("limit")
|
||||||
offset = serializer.validated_data.get("offset")
|
offset = serializer.validated_data.get("offset")
|
||||||
|
|
||||||
return Friendship.objects.filter(from_profile=self.request.user)[
|
return Friendship.objects.order_by("-addedAt").filter(
|
||||||
offset: offset + limit
|
from_profile=self.request.user
|
||||||
]
|
)[offset: offset + limit]
|
||||||
|
|
||||||
|
|
||||||
class PasswordChangeApiView(APIView):
|
class PasswordChangeApiView(APIView):
|
||||||
|
|||||||
Reference in New Issue
Block a user