본문 바로가기

졸업 프로젝트

수정 + 댓글 필터링

# 댓글 필터링

인터넷에 올라온 나쁜말 리스트를 가져왔다. 요새 AI로 알아서 걸러주는 여러 API도 많은 것 같긴 한데...시간이 없어서 간단하게 구현!

경로 확인

import pandas as pd

f = open(os.path.join(BASE_DIR, 'fword_list.txt'), "r", encoding='UTF8')
fword_list = f.read().splitlines()

 

경로는 이전에 내가 BASE_DIR을 설정해놔서 여기랑 파일명을 합쳐 설정해주면 된다.

 

from dislodged_project.settings.base import fword_list

print(fword_list[-1])

그리고 fword_list를 불러온 후 잘 되나 확인한다.

 

# posts/views.py
from dislodged_project.settings.base import fword_list
class CommentViewSet(viewsets.ModelViewSet):
    def create(self, request, *args, **kwargs):
        serializer = self.serializer_class(data = request.data, partial=True)
        if serializer.is_valid():
            serializer.is_liked=True
            if any(str in request.POST.get('content') for str in fword_list):
                # 리스트 내에 있는 문자들이 content에 포함되어 있는가?
                # 욕설이 다른 단어와 이어져 있을 때도 판단하기 위해
                print(request.POST.get('content'))
                return Response({"message":"작성하신 댓글에 비속어나 욕설이 포함되어 있습니다."}, status=status.HTTP_200_OK)
            else:
                serializer.save(author=self.request.user, author_voice=self.request.user.user_voice)
            return Response(serializer.data)
  • 댓글 내용(content)가 fword_list 내에 있는지가 아니라, 반대로 해야 한다!

성공~

근데 프론트에서 내가 보낸 message를 인식 못한다.

response를 두번 return하게되면 마지막 response만 인식하는 건가? 나중에 수정해야지~


# 오류 수정

분명 백에서는 잘되는데...프론트에서는 갑자기 댓글이 안된다ㅜㅜ

argument of type 'NoneType' is not iterable

리스트인데 왜 반복이 안되는걸까? 파일을 읽어서 리스트를 views.py까지 잘 불러오는지 확인하기 위해 불러온 file을 출력시켜봤다.

Dockerfile에 ENV PYTHONUNBUFFERED 1

혹은 Docker-compose 파일 environments에 pythonunbuffered=1을 해주면 docker log에 파이썬 output을 출력해준다.

sudo docker logs --tail 10 -f web으로 log를 확인.

욕설이라 모자이크...

일단 내가 요청을 보낼때는 잘 가져온다. 애초에 나는 잘 됐으니까...그렇다면 프론트에서 요청할 때는?

<class 'NoneTyp'> None 주목

아 fword_list가 아니라 받아온 댓글 data가 문제였다. 

request.POST.get('content')로는 프론트랑 통신할 때 인식을 못한다! 백에서는 잘되는거보면...다른 서버단이랑 통신할 때는  data는 serializer를 통해 변환해야 하는 듯?

따라서 이 부분을 수정해주었따.

    def create(self, request, *args, **kwargs):
        serializer = self.serializer_class(data = request.data, partial=True)
        if serializer.is_valid():
            serializer.is_liked=True
            # print(fword_list)
            content = serializer.validated_data['content'] # serializer로 받아와야 함! 그냥 받아오면 Nontype
            # print(content, type(content))
            if any(a in content for a in fword_list):
                # 리스트 내에 있는 문자들이 content에 포함되어 있는가?
                # 욕설이 다른 단어와 이어져 있을 때도 판단하기 위해
                return Response({"message":"작성하신 댓글에 비속어나 욕설이 포함되어 있습니다."}, status=status.HTTP_200_OK)
            else:
                serializer.save(author=self.request.user, author_voice=self.request.user.user_voice)
            return Response(serializer.data)

성공!

serializer로 변환된 data에서 content를 받아오는 걸로 수정했다!

 


# image 수정

이전에는 현재 작성자의 POST 개수에따라 게시글 이미지(앨범 이미지)를 불러오도록 하여 한 페이지에 이미지가 안겹치도록 했다.

하지만 그러면 사용자가 중간에 게시글을 삭제하면 이미지가 중복된다.

 

# accounts/models.py
class User(AbstractUser):

    gender_list = (
        ('남', '남'),
        ('여', '여')
    )

    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    username = models.CharField(max_length=20, unique=True) 
    nickname = models.CharField(max_length=8)
    email = models.EmailField(unique=True)
    gender = models.CharField(max_length=2, choices=gender_list, default='여')
    age = models.IntegerField(validators=[MinValueValidator(10), MaxValueValidator(80)])

    recent_image_number = models.IntegerField(default=0) # 최근에 사용한 이미지 저장을 위한 필드

    USERNAME_FIELD = 'username'
    REQUIRED_FIELDS = ['password', 'nickname', 'email', 'gender', 'age']

    

    def __str__(self):
        return f'{self.username}'

그냥 지금까지 작성한 게시글의 수를 저장하는 필드를 추가해줬다.

redis를 이용할 수도 있을텐데...그건 일단 나중에! 급한 것부터 해결하다...

 

# posts/views.py
class PostViewSet(viewsets.ModelViewSet):
    queryset=Post.objects.all()
    serializer_class=PostSerializer

    permission_classes = [IsAuthenticated, AuthenticatedOnly]
    pagination_class = LargeResultsSetPagination
    filter_backends = [DjangoFilterBackend]
    filterset_fields = ["group"]


    def perform_create(self, serializer):
        # 이미지 저장을 위한 것
        image_list = [ # (DB에 저장되는 값, 사용자에게 보여지는 값)
        ('https://dislodged.s3.ap-northeast-2.amazonaws.com/image/Frame+0.png', 1),
        ('https://dislodged.s3.ap-northeast-2.amazonaws.com/image/Frame+1.png', 2),
        ('https://dislodged.s3.ap-northeast-2.amazonaws.com/image/Frame+2.png', 3),
        ('https://dislodged.s3.ap-northeast-2.amazonaws.com/image/Frame+3.png', 4),
        ('https://dislodged.s3.ap-northeast-2.amazonaws.com/image/Frame+4.png', 5),
        ('https://dislodged.s3.ap-northeast-2.amazonaws.com/image/Frame+5.png', 6),
        ('https://dislodged.s3.ap-northeast-2.amazonaws.com/image/Frame+6.png', 7),
        ('https://dislodged.s3.ap-northeast-2.amazonaws.com/image/Frame+7.png', 8),
        ('https://dislodged.s3.ap-northeast-2.amazonaws.com/image/Frame+8.png', 9),
        ('https://dislodged.s3.ap-northeast-2.amazonaws.com/image/Frame+9.png', 10),
        ('https://dislodged.s3.ap-northeast-2.amazonaws.com/image/Frame+10.png', 11),
        ('https://dislodged.s3.ap-northeast-2.amazonaws.com/image/Frame+11.png', 12),
        ('https://dislodged.s3.ap-northeast-2.amazonaws.com/image/Frame+12.png', 13),
        ('https://dislodged.s3.ap-northeast-2.amazonaws.com/image/Frame+13.png', 14),
        ('https://dislodged.s3.ap-northeast-2.amazonaws.com/image/Frame+14.png', 15)

        ]
        num = User.objects.get(id=self.request.user.id)
        # total_posts = (Post.objects.filter(author=self.request.user).count())%16
        image_url = image_list[num.recent_image_number%15][0]
        num.recent_image_number+=1
        num.save()

        serializer.save(author = self.request.user, image=image_url)

image list 수정~ 이전에 %16으로 연산 실수했길래 수정 ㅎ

뭐...잘된당

 


# 회고

 

앞으로 백에서 API 잘된다고 안심하지 말고..

data를 받아와서 이용할 때는 꼭 serializer를 통해 이용하는 것을 잊지 말자.