Programming Language/SQLite

SQLite_05)Foreign Key_3

Sergemeow 2023. 4. 12. 14:46

ManyToManyField’s Arguments

  1. related_name
    • target model이 source model을 참조할 때 사용할 manager name
    • ForeignKey의 relqted_name과 동일
  2. through
    • 중개 테이블을 직접 작성하는 경우, through 옵션을 사용하여 중개 테이블을 나타내는 Django 모델을 지정
    • 일반적으로 중개 테이블에 추가 데이터를 사용하는 다대다 관계와 연결하려는 경우(extra data with a many-to-many relationship)에 사용됨
  3. symmetrical
    • 기본 값: True
    • ManyToManyField가 동일한 모델을 가리키는 정의에서만 사용
    • True일 겅우
      • _set 매니저를 추가하지 않음
      • source 모델의 인스턴스가 target 모델의 인스턴스를 참조하면 자동으로 target 모델 인스턴스도 source 모델 잉ㄴ스턴스를 참조하도록 함
      • Quid pro quo. If I am your friend, you are my friend too.
    • 대칭을 원하지 않는 경우 False로 설정
# example
class Person(models.Model):
	friends = models.ManyToManyField('self')

M:N 관계를 통한 좋아요 기능 구현

# articles/models.py

class Article(models.Model):
	user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
	like_users = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name='like_articles')
	...

related manager 정리

  • article.user : 게시글을 작성한 유저
  • user.article_set : 유저가 작성한 게시글(역참조)
  • article.like_users : 게시글에 좋아요를 누른 유저
  • user.like_articles : 유저가 좋아요한 게시글(역참조)
# articles.urls.py

...
path('<int:article_pk>/likes/', views.likes, name='likes'),
# articles/views.py

@require_POST
def likes(request, article_pk):
	if request.user.is_authenticated:
		article = Article.objects.get(pk=article_pk)
		if article.like_users.filter(pk=request.user.pk).exists():
			article.like_users.remove(request.user)
		else:
			article.like_users.add(request.user)
		return redirect('articles:index')
	return redirect('accounts:login')
# index 템플릿에서 if문으로 좋아요 버튼 출력

{% request.user in article.like_users.all %}
	<input type="submit" value="좋아요 취소">
{% else %}
	<input type="submit" value="좋아요">
{% endif %}

Profile 구현

  • url 및 view 함수
urlpatterns = [
	...
	path('profile/<username>/', views.profile, name = 'profile'),
]
from django.contrib.auth import get_user_model

def profile(request, username):
	User = get_user_model()
	person = User.objects.get(username=username)
	context = {'person':person}
	return render(request, 'accounts/profile.html',context)
  • profile 템플릿 작성
<h3>{{person.username}}님의 프로필</h3>
<hr>
<h4>{{person.username}}'s 게시글</h4>
{% for article in person.article_set.all %}
	<div>{{article.title}}</div>
{% endfor %}
<hr>

<h4>{{person.username}}'s 댓글</h4>
{% for comment in person.comment_set.all %}
	<div>{{comment.content}}</div>
{% endfor %}

<hr>

<h4>{{person.username}}'s 좋아요한 게시글</h4>
{% for article in person.like_articles.all %}
	<div>{{article.title}}</div>
{% endfor %}
  • profile 템플릿으로 이동할 수 있는 하이퍼링크 작성
<h3>Hello, {{user}}</h3>
<a href="{% url 'accounts:profile' user.username %}">내 프로필</a>
<!-- articles/index.html -->

<p>
	<b>작성자: <a href="<% url 'accounts:profile' article.user.username %}">{{article.user}}</a></b>
</p>

Follow 구현

  • ManyToManyField 작성 및 Migration 진행
# accounts/models.py

class User(AbstractUser):
	followings = models.ManyToManyField('self', symmetrical=False, related_name='followers')

  • url 및 view 함수 작성
urlpatterns = [
	...
	path('<int:user_pk>/follow/', views.follorw, name='follow'),
]
@require_POST
def follow(request, user_pk):
	if request.user.is_authenticated:
		User = get_user_model()
		person = User.objects.get(pk=user_pk)
		if person != request.user:
			if person.followersfilter(pk=request.user.pk).exist():
				person.followers.remove(request.user)
			else:
				person.followers.add(request.user)
		return redirect('accounts:profile', person.username)
	return redirect('accounts:login')
  • 프로필 유저의 팔로잉, 팔로워 수, 팔로우/언팔로우 버튼 작성
<h3>{{person.username}}님의 프로필</h3>
<div>
	<div>
		Following: {{person.folwings.all|length}} / Followers: {{person.followers.all|length}}
	</div>
	{% if request.user != person %}
		<div>
			<form action="{% url 'accounts:follow' person.pk %}" method="POST">
				{% csrf_token %}
				{% if request.user in person.followers.all %}
					<input type='submit' value='Unfollow'>
				{% else %}
					<input type='submit' value='Follow'>
				{% endif %}
			</form>
		</div>
	{% endif %}
</div>

'Programming Language > SQLite' 카테고리의 다른 글

SQLite_06)Fixtures  (0) 2023.04.12
SQLite_04)Foreign Key_2  (0) 2023.04.12
SQLite_03)Foreign Key_1  (0) 2023.04.12
SQLite_02)CRUD  (0) 2023.04.12
SQLite_01)Set up & Basics  (0) 2023.04.12