AI 웹개발반/Python, Django

[Django + Vue] Profile에 새로운 내용 가져와 추가하기

째깍단 2023. 6. 30. 20:07

오늘 한 것 : profile에 유저가 참여중인 공구 게시글 목록 넣기 vue + django 활용

 

 

참조의 참조를 하려니 헷갈리고 어려웠다.

그럴땐 sql쿼리문을 활용하며 하나씩차근차근 불러와보자!

https://diane073.tistory.com/148

 

 


 

 

django에서 작업

 

 

  1. profile에만 사용할 시리얼라이저를 정의
    해당 글로 이동하는 url을 걸어주기위해 community url을 함께 받아왔다
#feed / seriliazers.py
class ProfileGrouppurchaseSerializer(serializers.ModelSerializer):

    community_url = serializers.SerializerMethodField()

    class Meta:
        model = GroupPurchase
        fields = ["id", "title", "product_name", "open_at", "close_at", "community_url"]

    def get_community_url(self, obj):
        return obj.community.communityurl

 

 

 

 

  1. user view에서 profiledetailview에 db조회하는 코드 추가

 

먼저 joined_user 객체를 가져와 보았다

 

joined = user.joined_user.filter(user_id=user_id).exclude(is_deleted=True)

 

 

 

sql쿼리문을 살펴보면 현재 joined 객체는 쿼리셋 형태로 가져와지고 있어서, 하나의 요소를 따로 빼서 확인할 수 없는 상태.
아래 볼 수 있듯 user_id가 1인 객체를 가져온다.

 

👀 <QuerySet [<JoinedUser: 유저 : admin (admin) 수량 :1>, <JoinedUser: 유저 : admin (admin) 수량 :1>]>
(0.000) SELECT "feed_joineduser"."id", "feed_joineduser"."user_id", 
"feed_joineduser"."grouppurchase_id", "feed_joineduser"."product_quantity", 
"feed_joineduser"."created_at", "feed_joineduser"."is_deleted"
FROM "feed_joineduser" WHERE ("feed_joineduser"."user_id" = 1 
AND "feed_joineduser"."user_id" = 1 AND NOT ("feed_joineduser"."is_deleted"))
 LIMIT 21; args=(1, 1); alias=default

 

 

 

QuerySet = joined.grouppurchase << ❌ 바로 불러서 사용할 수 없다!

그래서 prefetch_related를 사용해 grouppurchase를 가져왔다

 

from feed.models import GroupPurchase
from feed.serializers import ProfileGrouppurchaseSerializer

class ProfileDetailView(APIView):
    """프로필 CU, user Delete view"""
    permission_classes = [permissions.IsAuthenticatedOrReadOnly]

    def get(self, request, user_id):
        profile = Profile.objects.get(user_id=user_id)
        ...
        joined = user.joined_user.filter(user_id=user_id).exclude(is_deleted=True).prefetch_related("grouppurchase").all()
        ...

 

 

 

 

feed - User 양방향 import라 충돌날까봐 약간 걱정했는데 다행히 괜찮았다!

관계있는 db자료인 prefetch_related를 이용해 joined 객체와 함께 grouppurchase 정보를 가져오도록 했다.

 

feed.JoinedUser.None ⭐️
(0.000) SELECT "feed_joineduser"."id", "feed_joineduser"."user_id", 
"feed_joineduser"."grouppurchase_id", "feed_joineduser"."product_quantity", 
"feed_joineduser"."created_at", "feed_joineduser"."is_deleted" 
FROM "feed_joineduser" WHERE ("feed_joineduser"."user_id" = 1 
AND "feed_joineduser"."user_id" = 1 AND NOT ("feed_joineduser"."is_deleted")) 
LIMIT 21; args=(1, 1); alias=default

(0.000) SELECT "feed_grouppurchase"."id", "feed_grouppurchase"."title", 
"feed_grouppurchase"."content", "feed_grouppurchase"."product_name", 
"feed_grouppurchase"."product_number", "feed_grouppurchase"."product_price", 
"feed_grouppurchase"."link", "feed_grouppurchase"."created_at", 
"feed_grouppurchase"."updated_at", "feed_grouppurchase"."is_ended", 
"feed_grouppurchase"."user_id", "feed_grouppurchase"."person_limit", 
"feed_grouppurchase"."location", "feed_grouppurchase"."meeting_at", 
"feed_grouppurchase"."open_at", "feed_grouppurchase"."close_at", 
"feed_grouppurchase"."end_option", "feed_grouppurchase"."community_id", 
"feed_grouppurchase"."category_id", "feed_grouppurchase"."view_count" 
FROM "feed_grouppurchase" WHERE "feed_grouppurchase"."id" 
IN (1, 3); args=(1, 3); alias=default

 

 

쿼리셋 객체를 print하였는데 겉으로 보기에는 변화가 없어서 그대로 joined_user테이블 값만 가져온 것처럼 보일 수 있다.

<QuerySet [<JoinedUser: 유저 : admin (admin) 수량 :1>, <JoinedUser: 유저 : admin (admin) 수량 :1>]> 🐛

위의 sql쿼리문을 보면 feed_grouppurchas id 값(args=(1, 3))을 가져오고 있음을 확인할 수 있다!

 

 

 

 

가져온 grouppurchase id 값으로 정의해둔 serializer를 통해 객체를 직렬화, response에 담아주었다.

 

joined_grouppurchase = GroupPurchase.objects.filter(id__in=joined).order_by("-created_at")
joined_grouppurchase_serializer = ProfileGrouppurchaseSerializer(joined_grouppurchase, many=True)
...
return Response(
    {
        "profile": profile_serializer.data,
        ...
        "joined_grouppurchase": joined_grouppurchase_serializer.data,
    },
    status=status.HTTP_200_OK,
)

 

 

 

 


 

 

 

vue에서 작업

 

 

mapGetters 아래에 새로운 데이터 이름을 선언, 미리 만들어둔 html 자리에 넣어주었다

 

  • script

 

import { mapGetters } from "vuex";

export default {
    computed: {
        ...mapGetters({"data":"fetchProfile"}),
        profile() {
            return this.data.profile;
        },
        ...
        grouppurchase() {
            return this.data.joined_grouppurchase;
        }
    }
}

 

 

 

  • template

 

<router-link :to="`/community/detail/${grouppurchase.community_url}/groupbuy/${grouppurchase.id}`" v-for="(grouppurchase, index) in grouppurchase" :key=index>
  <div class="gp-content-card">
    <div class="gp-title-box">
      <span class="content-title">{{ grouppurchase.title }}</span>
    </div>
    <span id="gp-product-name" class="gp-product-name"><div v-html="grouppurchase.product_name"></div></span>
    <li>시작일</li>
    <p class="gp-content-date">{{ grouppurchase.open_at.slice(0,10) }} | {{ grouppurchase.open_at.slice(12,19) }}</p>
    <li>마감일</li>
    <p class="gp-content-date">{{ grouppurchase.close_at.slice(0,10) }} | {{ grouppurchase.close_at.slice(12,19) }}</p>
  </div>
</router-link>

 

 

 

완성된 모습

 

 

 

 

 

 

 

 

 

 

+++ vue에서 여러 url의 데이터 가져오기

 

mapGetters 안의 {"data" : "fetchProfile"}

-> data는 사용할 key name, fetchProfile은 라우트해둔 profileview get

 

 

만약 2개 이상의 데이터를 mapGetters에서 사용해야한다면
리스트 형태로 쓰고, 아래에 함수에서 라우트 이름을 사용하여 불러온다

 

computed: {
    ...mapGetters(["fetchProfile", "fetchFeed"]),
    profile(){
            return this.fetchProfile.community
        },
    feed(){
            return this.fetchFeed?.title;
        },
}