[Django + Vue] Profile에 새로운 내용 가져와 추가하기
오늘 한 것 : profile에 유저가 참여중인 공구 게시글 목록 넣기 vue + django 활용
참조의 참조를 하려니 헷갈리고 어려웠다.
그럴땐 sql쿼리문을 활용하며 하나씩차근차근 불러와보자!
https://diane073.tistory.com/148
django에서 작업
- 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
- 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;
},
}