Many to Many Relationship
M:N
M has many N
N has many M
Naming convention
1:N
์ ์: ๋ชจ๋ธ ๋จ์ํ (.user)
์ญ์ฐธ์กฐ: ๋ชจ๋ธ_set (.article_set)
M:N
์ ์ ๋ฐ ์ญ์ฐธ์กฐ: ๋ชจ๋ธ ๋ณต์ํ(.like_users, like_articles)
M:N ๊ด๊ณ ์ ๊ทผ

1. ๋จ์ ์ง๊ด์ ๋ชจ๋ธ๋ง
์์ ๋์ํํ ์ ์ฉ models.py๋ก ์ฎ๊ฒจ๋ณด๊ธฐ
class Doctor(models.Model):
name = models.CharField(max_length=10)
class Patient(models.Model):
name = models.CharField(max_length=10)
class Reservation(models.Model):
doctor = models.ForeignKey(Doctor, on_delete=models.CASCADE)
patient = models.ForeignKey(Patient, on_delete=models.CASCADE)
ํ์/์์ฌ ์์ฑ
d1 = Doctor.objects.create(name='dr.john') d2 = Doctor.objects.create(name='dr.kim') p1 = Patient.objects.create(name='๊ตฌ๋ฆ') p2 = Patient.objects.create(name='๊ทผ์ ')
์์ฝ ๋ง๋ค๊ธฐ
Reservation.objects.create(doctor=d1, patient=p1) Reservation.objects.create(doctor=d1, patient=p2) Reservation.objects.create(doctor=d2, patient=p1)
1๋ฒ ์์ฌ์ ์์ฝ ๋ชฉ๋ก
d1.reservation_set.all()
1๋ฒ ํ์์ ์์ฝ ๋ชฉ๋ก
p1.reservation_set.all()
1๋ฒ ์์ฌ์ ํ์ ์ถ๋ ฅ
for reservation in d1.reservation_set.all(): print(reservation.patient.name)
2. ์ค๊ฐ ๋ชจ๋ธ ํ์ฉ
์์ฌ - ํ์๋ค / ํ์ - ์์ฌ๋ค๋ก ์ง์ ์ ๊ทผํ๊ธฐ ์ํด์๋
ManyToManyField
๋ฅผ ์ฌ์ฉํ๋ค.
through
์ต์ ์ ํตํด ์ค๊ฐ ๋ชจ๋ธ์ ์ ์ธํ๋ค.

class Doctor(models.Model):
name = models.CharField(max_length=10)
class Patient(models.Model):
name = models.CharField(max_length=10)
# M:N ํ๋! reservation ํตํด์, Doctor์ ์ ๊ทผ์ ์๋ฏธ
doctors = models.ManyToManyField(Doctor,
through='Reservation')
class Reservation(models.Model):
doctor = models.ForeignKey(Doctor, on_delete=models.CASCADE)
patient = models.ForeignKey(Patient, on_delete=models.CASCADE)
๋ง์ด๊ทธ๋ ์ด์ ํ์ผ์ ๋ง๋ค๊ฑฐ๋, migrate๋ฅผ ํ ํ์๊ฐ ์๋ค.
์ฆ, ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ํ ๋ณ๊ฒฝ๋๋ ๊ฒ์ ์๊ณ , ORM ์กฐ์์์์ ์ฐจ์ด๋ง ์กด์ฌํ๋ค.
์์ฌ, ํ์ ์ค๋ธ์ ํธ ๊ฐ์ ธ์ค๊ธฐ
p1 = Patient.objects.get(pk=1) d1 = Doctor.objects.get(pk=1)
1๋ฒ ํ์์ ์์ฌ ๋ชฉ๋ก
ManyToManyField
๊ฐ ์ ์๋Patient
๋ ์ง์ ์ฐธ์กฐp1.doctors.all()
1๋ฒ ์์ฌ์ ํ์ ๋ชฉ๋ก
Doctor
๋ ์ง์ ์ฐธ์กฐ๊ฐ ์๋๋ผPatient
๋ชจ๋ธ์ ์ญ์ฐธ์กฐ.์ฆ, ๊ธฐ๋ณธ naming convention์ ๋ฐ๋ผ ์ฐธ์กฐ
d1.patient_set.all()
related_name
: ์ญ์ฐธ์กฐ ์ต์ ๊ธฐ๋ณธ ๊ฐ์
{model ์ด๋ฆ}_set
image-20200428192427702 ์ญ์ฐธ์กฐ ์ค์ ์ด ๋ฐ๋์ ์ค์ ๋์ด์ผ ํ๋ ์ํฉ์ด ์๋ค
django
์์ makemigrations ํ๋ ๊ฒฝ์ฐ ์ง์ ์ค๋ฅ๋ฅผ ๋ฐ์์์ผ ์ค๋คex) ์์ฑ์(User)-๊ฒ์๊ธ(Article), ์ข์์๋๋ฅธ์ฌ๋(User)-๊ฒ์๊ธ(Article)
์์ ๊ด๊ณ ์ค์ ์ ๋ชจ๋ Article ํด๋์ค์ related_name ์์ด ์ ์๋ฅผ ํ๊ฒ ๋๋ค๋ฉด, ์ญ์ฐธ์กฐ ์ด์ ๋ฐ์
class Doctor(models.Model): name = models.TextField() class Patient(models.Model): name = models.TextField() # ์ญ์ฐธ์กฐ ์ค์ . related_name doctors = models.ManyToManyField(Doctor, through='Reservation', related_name='patients') class Reservation(models.Model): doctor = models.ForeignKey(Doctor, on_delete=models.CASCADE) patient = models.ForeignKey(Patient, on_delete=models.CASCADE)
3. ์ค๊ฐ ๋ชจ๋ธ ์์ด ์ค์
์ผ๋ฐ์ ์ผ๋ก ์ถ๊ฐ ํ๋ ๊ตฌ์ฑ์ด ํ์ ์์ด id ๊ฐ๋ง ์กด์ฌํ๋ ๊ฒฝ์ฐ๋ ์๋์ ๊ฐ์ด ์ ์ธํ๋ค.
class Doctor(models.Model):
name = models.TextField()
class Patient(models.Model):
name = models.TextField()
doctors = models.ManyToManyField(Doctor,
related_name='patients')
์ด ๊ฒฝ์ฐ ์ฑ์ด๋ฆ_patient_doctors ๋ก ํ ์ด๋ธ์ด ์์ฑ๋๋ค.
ํด๋น ํ ์ด๋ธ์ Create/Delete๋ฅผ ์ํด์๋ (์์ฝ์ ์์ฑํ๊ฑฐ๋ ์ญ์ ํ๊ธฐ ์ํด์๋) ์๋์ ๋ฉ์๋๋ฅผ ํ์ฉํ๋ค.
d1.patients.add(p1) # ๊ฐ๊ฐ ์กฐํ ํด๋ณด์. d1.patients.all() p1.doctors.all()
d1.patients.remove(p1) # ๊ฐ๊ฐ ์กฐํ ํด๋ณด์. d1.patients.all() p1.doctors.all()
๊ฒฐ๋ก
์ค๊ฐ model์ด ํ์ ์๋ ๊ฒฝ์ฐ
ํน์ Class์
ManyToManyField
์ ์ธ (์ค๊ฐ table ์๋์ ์ธ)
์ค๊ฐ model์ด ํ์ํ ๊ฒฝ์ฐ (์ถ๊ฐ ์ ๋ณด๊ฐ ํ์ํ ๊ฒฝ์ฐ)
์ค๊ฐ model ์ ์ ํ
ํน์ Class์
ManyToManyField
์through
option์ ํตํด ์กฐ์
+
ManyToMany
์์๋ ๋ฐ๋์ค ๋ณต์ํ์ ํํ์ผ๋กrelated_name
์ ์ ์ธํ์!!
id๋ก ์ํ๋ ๊ฐ ๋ถ๋ฌ์ค๊ธฐ
In [13]: Reservation.objects.filter(doctor_id=3)
Out[13]: <QuerySet [<Reservation: Reservation object (3)>]>
Delete
๋ถํธํ ver.
In [18]: Reservation.objects.filter(patient_id=1,doctor_id=1).delete()
Out[18]: (1, {'manytomany.Reservation': 1})
์ข์์ ๊ธฐ๋ฅ
class Post(models.Model):
title = models.CharField(max_length=100)
content = models.TextField()
image = models.ImageField(blank=True)
# DB ์ ์ฅ x, ํธ์ถํ๊ฒ ๋๋ฉด ์๋ผ์ ํํ
image_thumbnail = ImageSpecField(source='image',
processors=[ResizeToFill(300, 300)],
format='JPEG',
options={'quality': 60})
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
#์ข์์ ๊ธฐ๋ฅ
users = models.ManyToManyField(settings.AUTH_USER_MODEL,
related_name='like_posts')
$ python manage.py makemigrations
SystemCheckError: System check identified some issues:
ERRORS:
posts.Post.user: (fields.E304) Reverse accessor for 'Post.user' clashes with reverse accessor for 'Post.users'.
HINT: Add or change a related_name argument to the definition for 'Post.user' or 'Post.users'.
posts.Post.users: (fields.E304) Reverse accessor for 'Post.users' clashes with reverse accessor for 'Post.user'.
HINT: Add or change a related_name argument to the definition for 'Post.users' or 'Post.user'.
URL - variable routing
View - ์ข์์ ๋๋ ์ผ๋ฉด ์ทจ์, ์๋๋ ์ผ๋ฉด ์ข์์ (Toggle)
ํ๋ก์ฐ ๊ธฐ๋ฅ
URL - variable routing
accoutns/1/follow
View
follow ๋์ด์๋ ๊ฒฝ์ฐ add
์๋์ด ์๋ ๊ฒฝ์ฐ remove
Template(์๋ต)
User detail redirect
Last updated
Was this helpful?