python/Django

[Django] ORM - 1:N 관계 (ForeignKey) (일대다관계 1)

http://portfolio.wonpaper.net 2022. 5. 14. 09:50

Django 에서 Model 간의 관계에 관해 몇가지 정리해 본다.

 

User 와 Album 모델은 Album.owner FoeignKey 로 연결되어 있다.

1
2
3
4
5
6
from django.contrib.auth.models import User
 
class Album(models.Model):
    name = models.CharField('NAME', max_length=30)
    description = models.CharField('One Line Description', max_length=100, blank=True)
    owner = models.ForeignKey('auth.User', on_delete=models.CASCADE, verbose_name='OWNER', blank=Truenull=True)
cs

 

[ 1:N ]

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
>>> from django.contrib.auth.models import User
>>> from photo.models import Album
 
# User 테이블의 모든 레코드를 확인
>>> User.objects.all()
<QuerySet [<User: shkim><User: guest>]>
 
# Album 테이블의 모든 레코드를 확인
>>> Album.objects.all()
<QuerySet [<Album: Django><Album: Nature><Album: 국가별><Album: 사람들>]>
 
# 특정한 앨범 객체 하나를 조회하고 그 소유자 확인한다.
>>> a2 = Album.objects.All()[2]
>>> a2
<Album: 국가별>
>>> a2.owner
<User: shkim>
 
#앨범 객체를 통해 사용자 객체의 username 필드를 통해 사용자이름을 확인
>>> a2.owner.username
'shkim'
cs

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# 사용자 객체를 조회해 u1, u2객체에 대입
>>> u1 = User.objects.get(username='shkim')
>>> u2 = User.objects.get(username='guest')
 
# 앨범을 새로 하나 만들고 앨범 소유자를 지정한다. - 2가지 방법
# [방법 1] 새로운 앨범 객체를 생성하고 save() 시키고, add() 시킨다.
 
>>> newa1 = Album(name='TestAlbum1')
>>> newa1
<Album: TestAlbum1>
>>> newa1.save()
>>> u1.album_set.add(newa1)
 
>>> u1.album_setl.all()
<QuerySet [<Album: TestAlbum1><Album: 국가별>]>
 
 
# [방법 2] 특정 사용자 객체에서 바로 create() 해서 새로운 앨범을 추가하면서, 그 사용자객체를 지정한다.
>>> newa2 = u2.album_set.create(name='TestAlbum2')
>>> newa2
<Album: TestAlbum2>
 
>>> u2.album_set.all()
[<Album: TestAlbum2>]
 
# 방금 만든 앨범 newa1의 소유자를 u1 -> u2 로 변경
>>> u2.album_set.add(newa1)
 
>>> newa1.owner
<User: guest>
 
>>> u2.album_set.all()
[<Album: TestAlbum1><Album: TestAlbum2>]
 
# 소유자가 u2인 앨범의 갯수
>>> u2.album_set.count()
2
 
>>> u1.album_set.all()
<QuerySet [<Album: 국가별>]>
 
# 모델 간 관계에서도 필드검색해 본다.
>>> u2.album_set.filter(name__startwidth='Test')
<QuerySet [<Album: TestAlbum1><Album: TestAlbum2>]>
 
>>> Album.objects.filter(owner__username='guest1')
<QuerySet [<Album: TestAlbum1><Album: TestAlbum2>]>
 
cs

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# 조건 2개 이상이면 AND 형태로
>>> Album.objects.filter(owner=u2, name__startswith='Test')
<QuerySet [<Album: TestAlbum1><Album: TestAlbum2>]>
 
# 앨범 모델에서 소유자를(소유자의 앨범을) 불러오는 여러가지 방법들
>>> Album.objects.filter(owner__pk=1)
<QuerySet [<Album: 국가별>]>
 
>>> Album.objects.filter(owner=1)
<QuerySet [<Album: 국가별>]>
 
>>> Album.objects.filter(owner=u1)
<QuerySet [<Album: 국가별>]>
 
>>> Album.objects.filter(owner__in=[1]).distinct()
<QuerySet [<Album: 국가별>]>
 
>>> Album.objects.filter(owner__in=[u1]).distinct()
<QuerySet [<Album: 국가별>]>
 
>>> Album.objects.filter(owner__in=User.objects.filter(username='shkim')).distinct()
<QuerySet [<Album: 국가별>]>
 
 
# User 모델에서 앨범을(앨범의 소유자를) 불러오는 여러가지 방법들
>>> User.objects.filter(album__pk=6)
<QuerySet [<User: shkim>]>
 
>>> User.objects.filter(album=6)
<QuerySet [<User: shkim>]>
 
>>> User.objects.filter(album=a2)
<QuerySet [<User: shkim>]>
 
 
# 필드 검색
>>> User.objects.filter(album__name__startswidth='Test')
<QuerySet [<User: guest><User: guest>]>
 
>>> User.objects.filter(album__name__startswidth='Test').distinct()
<QuerySet [<User: guest>]>
 
>>> User.objects.filter(album__name__startswidth='Test').distinct().count()
1
cs

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# 순환방식으로 필드 검색
>>> User.objects.filter(album__owner=u1)
<QuerySet [<User: shkim>]>
 
>>> Album.objects.filter(owner__album=a2)
<QuerySet [<Album: 국가별>]>
 
# 1:N 관계에서 1 쪽의 객체를 지우면 CASCADE 로 인해 N 쪽의 객체도 같이 삭제된다.
>>> u3 = User.objects.create(username='guest3')
 
>>> u3.album_set.create(name='TestAlbum3')
<Album: TestAlbum3>
 
# 삭제 전, u3 소유의 앨범을 확인해본다.
>>> u3.album_set.all()
[<Album: TestAlbum3>]
 
 
# delete() 메소드는 삭제된 개수를 반환한다.
>>> u3.delete()
(2, {'admin.LogEntity'0'auth.User_groups'0'auth.User_user_permissions':0'bookmark.Bookmark'0'photo.Photo'0'auth.User'1'photo.Album'1})
 
# guest3 객체가 삭제된것을 확인해본다.
>>> User.objects.all()
<QuerySet [<User: shkim><User: guest>]> 
 
# u3 소유의 TestAlbum3 앨범도 같이 삭제된것을 확인해본다.
>>> Album.objects.all()
<QuerySet [<Album: Django><Album: Nature><Album: TestAlbum1><Album: TestAlbum2><Album: 국가별><Album: 사람들>]>
cs

 

 

참고 : [실전편] Django 를 활용한 쉽고 빠른 웹개발 파이썬 웹프로그래밍 (김석훈) , 설명예제