Skip to content

Commit

Permalink
Merge pull request #95 from whatTeamNaeTeam/fix-validation_error
Browse files Browse the repository at this point in the history
[FIX] Validation Error 해결
  • Loading branch information
fnzksxl authored Sep 21, 2024
2 parents 67220b5 + 3915e17 commit 17d9d6f
Show file tree
Hide file tree
Showing 7 changed files with 136 additions and 38 deletions.
5 changes: 5 additions & 0 deletions wtnt/core/exception/login.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,8 @@ class EmailCodeNotMatchAfterAuthError(APIException):
class EmailCeleryError(APIException):
status_code = 400
default_detail = {"message": "이메일 발송 도중 문제가 발생했습니다.", "code": "0133"}


class UserExplainTooLong(APIException):
status_code = 400
default_detail = {"message": "유저의 자기소개 글이 너무 깁니다.", "code": "0140"}
2 changes: 2 additions & 0 deletions wtnt/core/utils/team.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ def make_data(leader, strs, image, categories, counts, uuid):

if "urls" in strs:
_dict["url"] = strs["urls"]
else:
_dict["url"] = None

return _dict

Expand Down
107 changes: 72 additions & 35 deletions wtnt/team/serializers.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
from rest_framework.exceptions import APIException, ValidationError
from rest_framework import serializers
from rest_framework.settings import api_settings
from rest_framework.fields import get_error_detail, SkipField
from django.core.exceptions import ValidationError as DjangoValidationError
from django.db import transaction
from collections.abc import Mapping

from .models import Team, TeamTech, TeamApply, Likes
from core.fields import BinaryField
import core.exception.team as exception

serializers.ValidationError


class LeaderInfoIncludedSerializer(serializers.ModelSerializer):
leader_info = serializers.SerializerMethodField(read_only=True)
Expand Down Expand Up @@ -52,59 +61,87 @@ class Meta:
"is_approved",
]

def get_image_url(self, obj):
if obj.image is None:
return None
else:
# 나중에 이미지 여러장을 지원하기 위해
image_url = obj.image + "image.jpg"
return [image_url]

from rest_framework.fields import empty

def run_validation(self, data=empty):
(is_empty_value, data) = self.validate_empty_values(data)
if is_empty_value:
return data

value = self.to_internal_value(data)
self.run_validators(value)
value = self.validate(value)

return value

def validate(self, data):
url = data.get("url", None)
explain = data.get("explain", None)
def validate_title(self, value):
if not (2 < len(value) <= 30):
raise exception.TeamNameLengthError()

if self.instance and self.instance.pk:
if Team.objects.filter(title=self.instance.title).exclude(pk=self.instance.pk).exists():
if Team.objects.filter(title=value).exclude(pk=self.instance.pk).exists():
raise exception.TeamNameDuplicateError()
else:
if Team.objects.filter(title=data.get("title")).exists():
if Team.objects.filter(title=value).exists():
raise exception.TeamNameDuplicateError()

if not (0 < len(data.get("title")) <= 30):
raise exception.TeamNameLengthError()
return value

def validate_genre(self, value):
valid_genres = ["웹", "안드로이드", "IOS", "크로스플랫폼", "게임", "기타"]
if data.get("genre") not in valid_genres:
if value not in valid_genres:
raise exception.TeamGenreNotValidError()

if explain is not None and not (0 < len(explain.decode()) <= 2000):
return value

def validate_explain(self, value):
if value is not None and not (0 < len(value) <= 2000):
raise exception.TeamExplainLengthError()

if url is not None and len(url.decode()) == 0:
return value

def validate_url(self, value):
print(value)
if value is not None and len(value) == 0:
raise exception.TeamUrlLengthError()

return data
def get_image_url(self, obj):
if obj.image is None:
return None
else:
# 나중에 이미지 여러장을 지원하기 위해
image_url = obj.image + "image.jpg"
return [image_url]

def to_internal_value(self, data):
"""
Dict of native values <- Dict of primitive datatypes.
"""
if not isinstance(data, Mapping):
message = self.error_messages["invalid"].format(datatype=type(data).__name__)
raise ValidationError({api_settings.NON_FIELD_ERRORS_KEY: [message]}, code="invalid")

ret = {}
errors = {}
fields = self._writable_fields

for field in fields:
validate_method = getattr(self, "validate_" + field.field_name, None)
primitive_value = field.get_value(data)
try:
if validate_method is not None:
validated_value = validate_method(primitive_value)
validated_value = field.run_validation(primitive_value)
except APIException as api_exception:
raise api_exception
except ValidationError as exc:
errors[field.field_name] = exc.detail
except DjangoValidationError as exc:
errors[field.field_name] = get_error_detail(exc)
except SkipField:
pass
else:
self.set_value(ret, field.source_attrs, validated_value)

if errors:
raise ValidationError(errors)

return ret

def create(self, validated_data):
techs = validated_data.pop("category")
team = Team.objects.create(**validated_data)
with transaction.atomic():
team = Team.objects.create(**validated_data)

for tech in techs:
TeamTech.objects.create(team=team, **tech)
for tech in techs:
TeamTech.objects.create(team=team, **tech)

return team

Expand Down
2 changes: 1 addition & 1 deletion wtnt/team/team/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def update_team(self):
team_id = self.kwargs.get("team_id")

try:
team = Team.objects.prefetch_related("category").get(id=team_id)
team = Team.objects.get(id=team_id)
except Team.DoesNotExist:
raise notfound_exception.TeamNotFoundError()
self.check_leader(user_id, team.leader.id)
Expand Down
7 changes: 5 additions & 2 deletions wtnt/user/auth/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,11 @@
class AuthService(BaseService):
def get_user(self):
user_id = self.request.user.id
user = User.objects.get(pk=user_id)
serializer = UserSerializer(user)
try:
user = User.objects.get(pk=user_id)
serializer = UserSerializer(user)
except User.DoesNotExist:
raise None

return serializer.data

Expand Down
4 changes: 4 additions & 0 deletions wtnt/user/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ def clean(self):
if self.position not in valid_positions:
raise exception.PositionNotValidError()

def save(self, *args, **kwargs):
self.clean()
super().save(*args, **kwargs)


class UserUrls(models.Model):
user = models.OneToOneField(CustomUser, primary_key=True, on_delete=models.CASCADE)
Expand Down
47 changes: 47 additions & 0 deletions wtnt/user/serializers.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
from rest_framework.exceptions import APIException, ValidationError
from rest_framework import serializers
from rest_framework.settings import api_settings
from rest_framework.fields import get_error_detail, SkipField
from django.core.exceptions import ValidationError as DjangoValidationError
from django.contrib.auth import get_user_model
from collections.abc import Mapping
from user.models import UserTech, UserUrls
from core.fields import BinaryField
from core.exception.login import UserExplainTooLong

User = get_user_model()

Expand Down Expand Up @@ -32,6 +38,47 @@ class Meta:
model = User
fields = UserSerializer.Meta.fields + ["is_approved", "is_staff", "position", "explain"]

def validate_explain(self, value):
if len(value) > 500:
raise UserExplainTooLong()

return value

def to_internal_value(self, data):
"""
Dict of native values <- Dict of primitive datatypes.
"""
if not isinstance(data, Mapping):
message = self.error_messages["invalid"].format(datatype=type(data).__name__)
raise ValidationError({api_settings.NON_FIELD_ERRORS_KEY: [message]}, code="invalid")

ret = {}
errors = {}
fields = self._writable_fields

for field in fields:
validate_method = getattr(self, "validate_" + field.field_name, None)
primitive_value = field.get_value(data)
try:
if validate_method is not None:
validated_value = validate_method(primitive_value)
validated_value = field.run_validation(primitive_value)
except APIException as api_exception:
raise api_exception
except ValidationError as exc:
errors[field.field_name] = exc.detail
except DjangoValidationError as exc:
errors[field.field_name] = get_error_detail(exc)
except SkipField:
pass
else:
self.set_value(ret, field.source_attrs, validated_value)

if errors:
raise ValidationError(errors)

return ret


class UserUrlSerializer(serializers.ModelSerializer):
user_id = serializers.IntegerField()
Expand Down

0 comments on commit 17d9d6f

Please sign in to comment.