인프런 커뮤니티 질문&답변

Young님의 프로필 이미지
Young

작성한 질문수

파이썬/장고 웹서비스 개발 완벽 가이드 with 리액트

관계를 표현하는 모델 필드 (ManyToManyField)

ManyToManyField 데이터 불러오기

작성

·

447

0

안녕하세요!

User와 Job 두 모델이 있습니다.

ManytoMany필드를 통해 Job들 중에서 User가 좋아한 Job들만을 따로 보여주고 싶습니다. 그런데 여러번 함수를 바꿔서 시도해도 데이터가 제대로 보여지지 않는 것 같아요. 어떤 부분에서 실수를 한건지 살펴주실 수 있나요?

 

1. Model.py

class User(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
email = models.CharField(max_length=50)
password = models.CharField(max_length=50)
objects = UserManager()
class Job(models.Model):
title = models.CharField(max_length=50)
description = models.CharField(max_length=255)
location = models.CharField(max_length=255)
poster = models.ForeignKey(User, related_name='user_post', on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
user_likes = models.ManyToManyField(User, related_name='liked_job')
objects = JobManager()

2. view.py

def add_like(request, id):
liked_job = Job.objects.get(id=id)
user_liking = User.objects.get(id=request.session['id'])
liked_job.user_likes.add(user_liking)
return redirect('/dashboard')

3. .html

1) 좋아요 기능 구현한 부분

<tbody>
{% for job in jobs %}
<tr>
<td>{{ job.title }}</td>
<td>{{ job.location }}</td>
<td><a href="view/{{ job.id }}">View</a> |
<a href="like/{{ job.id }}">Add</a> |
<a href="edit/{{ job.id }}">Edit</a>
{% if job.poster.id == request.session.id %}
|<a href="/delete/{{ job.id }}">Cancel</a>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>

2) 데이터 표현 구간

{% for job in job.user_likes.all %}
<tr>
<td>{{ job.title }}</td>
<td><a href="view/{{ job.id }}">View</a></td>
<td><a href="view/{{ job.id }}">Done</td>
</tr>
{% endfor %}

답변 2

1

Young님의 프로필 이미지
Young
질문자

정성 스러운 답변에 늘 감사드립니다!

데이터필드를 공부하기 위해서는 장고쉘과 친해져야 한다는 것을 새로 배웁니다.

위에 있었던 문제는 view.py 를 다음과 같이 새로 구성하면서 해결하였습니다!

def favorite(request, id):
user = User.objects.get(id=request.session['id'])
job = Job.objects.get(id=id)
user.favorited_jobs.add(job)

return redirect('/dashboard')

def unfavorite(request, id):
user = User.objects.get(id=request.session['id'])
job = Job.objects.get(id=id)
user.favorited_jobs.remove(job)

return redirect('/dashboard')

설날 연휴 잘 보내셨기를 바라며, 2022년 한 해도 행복한 일이 많이 일어나시기를 바랍니다. :)!!

이진석님의 프로필 이미지
이진석
지식공유자

잘 해결하셨다니 다행입니다. :-)

하나만 덧붙이자면, queryset.get 을 사용하실 때에는 지정 조건의 Rows가 1개만 있으면 그 Row를 통해 모델 인스턴스가 반환되지만, 지정 조건의 Rows가 없거나 2개 이상의 Rows가 있을 경우 DoesNotExist 예외 혹은 MultipleObjectsReturned 예외가 발생할 수 있습니다. 뷰 함수에서 어떠한 예외가 발생하면, 클라이언트 측에는 500 Internal server error 응답이 가게 됩니다. 지정 조건의 Rows가 없는 것은 서버 에러가 아니라 404 not found 응답으로 처리되는 것이 맞습니다.

그러니, 뷰 함수에서 모델 인스턴스를 획득하실 때에는 직접적으로 queryset.get 를 사용하시기보다,  get_object_or_404 숏컷 함수를 사용하시기를 권장드립니다.

공식문서 : https://docs.djangoproject.com/ko/4.0/topics/http/shortcuts/#get-object-or-404

0

이진석님의 프로필 이미지
이진석
지식공유자

안녕하세요.

아래와 같이 관계를 처리하는 코드를 장고쉘(python manage.py shell)을 통해서 확인해보시면, 보다 명확하게 처리 내역을 확인하실 수 있습니다.

데이터베이스 저장 내역을 DB에 직접 접속해서 확인해보시거나, 장고 admin을 통해서 데이터 저장을 먼저 확인해보세요. 저장이 잘 되어있다면 보여주는 부분에서 오류가 있을 테구요. 저장이 되어있지 않다면 저장하는 부분에서 오류가 있을 것입니다.

데이터가 잘 저장이 되어있다면, 아마도 템플릿 단에서 참조하는 context 이름에 맞춰, 뷰 render 단에서 적절히 값을 넘겨주지 않았을 수도 있습니다. 넘겨주셨다면 이름에 오타가 있을 수도 있구요.

화이팅입니다. :-)

Young님의 프로필 이미지
Young

작성한 질문수

질문하기