본문 바로가기

포트폴리오

내일배움캠프 - My Little Trip 개발일지

스파르타 코딩클럽

내일배움캠프 AI 웹개발자양성과정 2회차

최종 프로젝트 개발일지

0. 프로젝트 정보

프로젝트 명

MLT - My Little Trip (여행 일정 추천받기)

기간

2022.07.07-08.16

프로젝트 목표

  1. 서버 배포해보기
  2. 한번쯤은 다들 필요하다고생각해보는 프로젝트 만들어보기

팀 정보

  • 팀명 : 사사십육
  • 팀원 : 김동우, 김진수, 최민기, 박진우

역할 분담

  • 김동우 : 유저 기능 / 여행일정 추천 기능 + Front 구성
  • 김진수 : 여행장소 기능 + server 배포
  • 박진우 : 댓글, 좋아요 기능 + server 배포
  • 최민기 : 리뷰 기능 + server 배포

Base 추천알고리즘 github

Travel_recommedation

 

GitHub - kimphysicsman/Travel_recommedation: Travel recommendation algorithm

Travel recommendation algorithm. Contribute to kimphysicsman/Travel_recommedation development by creating an account on GitHub.

github.com

Frontend github

MyLittleTrip_Front

1. Place 기능

 

1) Place Model

# 장소 타입 모델
class PlaceType(models.Model):
    typename = models.CharField("장소 유형", max_length=100, unique=True)

    def __str__(self):
        return self.typename

# 장소 모델


class Place(models.Model):
    _id = models.BigIntegerField("장소 id", unique=True)
    user = models.ForeignKey(User, verbose_name="등록자",
                             on_delete=models.CASCADE)
    placetype = models.ForeignKey(
        PlaceType, verbose_name="장소 유형", on_delete=models.CASCADE)

    name = models.CharField("장소 이름", max_length=100)
    word = models.CharField("검색단어",  max_length=100)
    address = models.CharField("주소",  max_length=100)

    x = models.CharField("x좌표(경도)", max_length=50)
    y = models.CharField("y좌표(위도)", max_length=50)

    image = models.ImageField(
        '장소 이미지', upload_to="static/images/place/%Y%m%d", null=True)
    rating = models.FloatField(
        "평점", validators=[MinValueValidator(0.0), MaxValueValidator(5.0)], default=0.0)
    description = models.TextField("설명", null=True)

    def __str__(self):
        return self.name

    def get_absolute_url(self):
        return reverse("place_detailview", kwargs={"place_id": self.pk})

# 이동시간 모델


class Duration(models.Model):
    start_id = models.BigIntegerField("출발지 장소 id")
    start_place = models.ForeignKey(
        Place, verbose_name="출발지", on_delete=models.CASCADE, related_name="start_place")
    end_id = models.BigIntegerField("도착지 장소 id")
    end_place = models.ForeignKey(
        Place, verbose_name="도착지", on_delete=models.CASCADE, related_name="end_place")
    duration = models.IntegerField("이동시간")

    def __str__(self):
        return f"{self.start_place.name} - {self.end_place.name} : {self.duration}"

2) Place Serializer

# place/serializers.py

from rest_framework import serializers
from place.models import Place, PlaceType
from user.models import User
from user.serializers import UserSerializer

class PlaceDetailSerializer(serializers.ModelSerializer):

    class Meta:
        model = Place
        fields = ['_id','user','word','placetype','name','address','x','y','image','rating','description']

class PlaceTypeSerializer(serializers.ModelSerializer):
    class Meta:
        model = PlaceType
        fields = ['id', 'typename']


class PlaceSerializer(serializers.ModelSerializer):
    user = serializers.SerializerMethodField(read_only=True)
    placetype = serializers.SerializerMethodField(read_only=True)

    def get_user(self, obj):
        return obj.user.username

    def get_placetype(self, obj):
        return obj.placetype.typename

    class Meta:
        model = Place
        fields = [
            'id',
            'user',
            'placetype',
            'name',
            'word',
            'address',
            'x',
            'y',
            'image',
            'rating',
            'description'
        ]


class PlaceAddSerializer(serializers.ModelSerializer):
    user = UserSerializer(read_only=True)
    placetype = serializers.SerializerMethodField()

    def get_placetype(self, obj):
        return obj.placetype.typename

    def create(self, validated_data):
        place = Place(**validated_data)
        place.save()
        return place

    class Meta:
        model = Place
        fields = [
            'id',
            'user',
            'placetype',
            'name',
            'address',
            'x',
            'y',
            'image',
            'description',
            '_id',
            'word'
        ]


class PlaceUpdateSerializer(serializers.ModelSerializer):
    user = UserSerializer(read_only=True)
    placetype = serializers.SerializerMethodField()


    def get_placetype(self, obj):
        return obj.placetype.typename

    class Meta:
        model = Place
        fields = [
            'id',
            'user',
            'placetype',
            'name',
            'address',
            'x',
            'y',
            'image',
            'description',
            '_id'
        ]

3) Place View

# place/views.py
from django.shortcuts import render
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status

from place.serializers import PlaceSerializer, PlaceAddSerializer, PlaceUpdateSerializer,PlaceDetailSerializer
from .models import Place, PlaceType
from user.models import User
from rest_framework_simplejwt.authentication import JWTAuthentication
# Create your views here.
# 장소 상세 조회
class PlaceViewDetail(APIView):
    def get(self,request,place_id):
        detailplaces = Place.objects.get(id=place_id)
        return Response(PlaceDetailSerializer(detailplaces).data, status=status.HTTP_200_OK)


class PlaceViewAll(APIView):
    authentication_classes = [JWTAuthentication] #JWT 인증
    # 장소 모두 조회
    def get(self, request):
        allplaces = Place.objects.all()
        return Response(PlaceSerializer(allplaces, many=True).data, status=status.HTTP_200_OK)

    

    # 장소 등록
    def post(self, request):
        if not request.user.is_authenticated:
            return Response({"message": "로그인해주세요"}, status=status.HTTP_401_UNAUTHORIZED)

        request.data['rating'] = 0
        image = request.FILES.get("image", "")
        placetype_typename = request.data.pop('placetype', '')[0]
        placetype_object = PlaceType.objects.get(typename=placetype_typename)
        user_id = request.data.pop('user', '')[0]
        user_object = User.objects.get(id=user_id)

        placeadd_serializer = PlaceAddSerializer(data=request.data)
  
        if placeadd_serializer.is_valid():
            placeadd_serializer.save(user=user_object,placetype=placetype_object,image=image)
            return Response(placeadd_serializer.data, status=status.HTTP_200_OK)
        return Response(placeadd_serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    # 장소 수정

    def put(self, request, place_id):

            place = Place.objects.get(id=place_id)

            place_serializer = PlaceUpdateSerializer(place,data=request.data,partial=True)

            if place_serializer.is_valid():
                place_serializer.save()
                return Response({"message": "정상"}, status=status.HTTP_200_OK)
        
            return Response(place_serializer.errors, status=status.HTTP_400_BAD_REQUEST)


    #장소 삭제

    def delete(self, request, place_id):
        place = Place.objects.get(id=place_id)
        place.delete()
        return Response({"msg":"삭제완료"})

2. 도커를 통한 서버 배포

 

 

 

3. 기타 정보

1) 프로젝트 문서

https://www.notion.so/kimphysicsman/MLT-My-Little-Trip-716433a2fc8940d9870bd83b63570646

2) github

https://github.com/nbcamp-AI-2-fantastic4/MyLittelTrip_backend
https://github.com/nbcamp-AI-2-fantastic4/MyLittelTrip_frontend_react

'포트폴리오' 카테고리의 다른 글

내일배움캠프 - My Little Shoes 개발일지  (0) 2022.08.22