<DJANGO>[MODEL]
[Model]
1. 기본 구조
1 2 3 4 5 6 | #django.db.models.Model from django.db import models class Person(models.Model): first_name = models.CharField(max_length=30) last_name = models.CharField(max_length=30) | cs |
1 2 3 4 5 | CREATE TABLE myapp_person ( "id" serial NOT NULL PRIMARY KEY, "first_name" varchar(30) NOT NULL, "last_name" varchar(30) NOT NULL ); | cs |
1 2 3 4 5 | INSTALLED_APPS = [ #... 'myapp', #... ] | cs |
- app 생성
- models.py에서 django.db.models을 import
- Model을 상속
- models 내부의 각각 Field 함수로 컬럼 설정
- settings.py의 INSTALLED_APPS에 생성한 app을 추가
- manage.py migrate 실행
- manage.py makemigrations 실행
2. 기본 Filed
1 2 3 4 5 6 7 8 9 10 11 12 | from django.db import models class Musician(models.Model): first_name = models.CharField(max_length=50) last_name = models.CharField(max_length=50) instrument = models.CharField(max_length=100) class Album(models.Model): artist = models.ForeignKey(Musician, on_delete=models.CASCADE) name = models.CharField(max_length=100) release_date = models.DateField() num_stars = models.IntegerField() | cs |
3. Filed Options
- null : (default=False) True 일때, 값이 없으면 null 등록
- blank : (default=False) True 일때, 값이 없으면 그대로 빈값 등록 <주의 : 전달파라미터 확인해야함>
- choices : 튜플로 작성된 key와 value를 컬럼에 매핑. key를 입력 받고 get_shirt_size_display()로 value를 확인 할 수 있다.
1 2 3 4 5 6 7 | YEAR_IN_SCHOOL_CHOICES = ( ('FR', 'Freshman'), ('SO', 'Sophomore'), ('JR', 'Junior'), ('SR', 'Senior'), ('GR', 'Graduate'), ) | cs |
1 2 3 4 5 6 7 8 9 10 | from django.db import models class Person(models.Model): SHIRT_SIZES = ( ('S', 'Small'), ('M', 'Medium'), ('L', 'Large'), ) name = models.CharField(max_length=60) shirt_size = models.CharField(max_length=1, choices=SHIRT_SIZES) | cs |
1 2 3 4 5 6 | >>> p = Person(name="Fred Flintstone", shirt_size="L") >>> p.save() >>> p.shirt_size 'L' >>> p.get_shirt_size_display() 'Large' | cs |
- default : 값이 없을 경우 기본 값을 설정
- help_text : form widget에서 help로 확인할 수 있는 정보 ( 문서 작성 시 유용함 )
- primary_key : True 일때, primary key로 설정 됨 (django의 기본 primary key는 "id" 컬럼)
1 2 3 4 | from django.db import models class Fruit(models.Model): name = models.CharField(max_length=100, primary_key=True) | cs |
1 2 3 4 5 | >>> fruit = Fruit.objects.create(name='Apple') >>> fruit.name = 'Pear' >>> fruit.save() >>> Fruit.objects.values_list('name', flat=True) ['Apple', 'Pear'] | cs |
1 | id = models.AutoField(primary_key=True) | cs |
- unique : null이 1회 가능한 컬럼으로 설정
4. Verbose field names
- Field를 파악할 수 있는 이름
- default : field 이름
1 | first_name = models.CharField(max_length=30) | cs |
- 설정
1 | first_name = models.CharField("person's first name", max_length=30) | cs |
- ForeignKey, ManyToManyField, OneToOneField는 필요함
1 2 3 4 5 6 7 8 9 10 11 | poll = models.ForeignKey( Poll, on_delete=models.CASCADE, verbose_name="the related poll", ) sites = models.ManyToManyField(Site, verbose_name="list of sites") place = models.OneToOneField( Place, on_delete=models.CASCADE, verbose_name="related place", ) | cs |
5. 1:1 관계
- 예제
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 | from django.db import models class Place(models.Model): name = models.CharField(max_length=50) address = models.CharField(max_length=80) def __str__(self): return "%s the place" % self.name class Restaurant(models.Model): place = models.OneToOneField( Place, on_delete=models.CASCADE, primary_key=True, ) serves_hot_dogs = models.BooleanField(default=False) serves_pizza = models.BooleanField(default=False) def __str__(self): return "%s the restaurant" % self.place.name class Waiter(models.Model): restaurant = models.ForeignKey( Restaurant, on_delete=models.CASCADE ) name = models.CharField(max_length=50) def __str__(self): return "%s the waiter at %s" % (self.name, self.restaurant) | 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 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 | ### >>> p1 = Place(name='Demon Dogs', address='944 W. Fullerton') >>> p1.save() >>> p2 = Place(name='Ace Hardware', address='1013 N. Ashland') >>> p2.save() ### >>> r = Restaurant(place=p1, serves_hot_dogs=True, serves_pizza=False) >>> r.save() ### >>> r.place <Place: Demon Dogs the place> ### >>> p1.restaurant <Restaurant: Demon Dogs the restaurant> ### >>> from django.core.exceptions import ObjectDoesNotExist >>> try: >>> p2.restaurant >>> except ObjectDoesNotExist: >>> print("There is no restaurant here.") There is no restaurant here. ### > hasattr(p2, 'restaurant') False ### >>> r.place = p2 >>> r.save() >>> p2.restaurant <Restaurant: Ace Hardware the restaurant> >>> r.place <Place: Ace Hardware the place> ### >>> p1.restaurant = r >>> p1.restaurant <Restaurant: Demon Dogs the restaurant> ### >>> p3 = Place(name='Demon Dogs', address='944 W. Fullerton') >>> Restaurant.objects.create(place=p3, serves_hot_dogs=True, serves_pizza=False) Traceback (most recent call last): ... ValueError: save() prohibited to prevent data loss due to unsaved related object 'place'. ### >>> Restaurant.objects.all() <QuerySet [<Restaurant: Demon Dogs the restaurant>, <Restaurant: Ace Hardware the restaurant>]> ### >>> Place.objects.order_by('name') <QuerySet [<Place: Ace Hardware the place>, <Place: Demon Dogs the place>]> ### >>> Restaurant.objects.get(place=p1) <Restaurant: Demon Dogs the restaurant> >>> Restaurant.objects.get(place__pk=1) <Restaurant: Demon Dogs the restaurant> >>> Restaurant.objects.filter(place__name__startswith="Demon") <QuerySet [<Restaurant: Demon Dogs the restaurant>]> >>> Restaurant.objects.exclude(place__address__contains="Ashland") <QuerySet [<Restaurant: Demon Dogs the restaurant>]> ### >>> Place.objects.get(pk=1) <Place: Demon Dogs the place> >>> Place.objects.get(restaurant__place=p1) <Place: Demon Dogs the place> >>> Place.objects.get(restaurant=r) <Place: Demon Dogs the place> >>> Place.objects.get(restaurant__place__name__startswith="Demon") <Place: Demon Dogs the place> ### >>> w = r.waiter_set.create(name='Joe') >>> w <Waiter: Joe the waiter at Demon Dogs the restaurant> ### >>> Waiter.objects.filter(restaurant__place=p1) <QuerySet [<Waiter: Joe the waiter at Demon Dogs the restaurant>]> >>> Waiter.objects.filter(restaurant__place__name__startswith="Demon") <QuerySet [<Waiter: Joe the waiter at Demon Dogs the restaurant>]> | cs |
6. 1대n 관계
- 기본 구조
1 2 3 4 5 6 7 8 | from django.db import models class Manufacturer(models.Model): # ... pass class Car(models.Model): manufacturer = models.ForeignKey(Manufacturer, on_delete=models.CASCADE) # ... | cs |
1 2 3 4 5 6 | class Car(models.Model): company_that_makes_it = models.ForeignKey( Manufacturer, on_delete=models.CASCADE, ) # ... | cs |
- 예제
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | from django.db import models class Reporter(models.Model): first_name = models.CharField(max_length=30) last_name = models.CharField(max_length=30) email = models.EmailField() def __str__(self): return "%s %s" % (self.first_name, self.last_name) class Article(models.Model): headline = models.CharField(max_length=100) pub_date = models.DateField() reporter = models.ForeignKey(Reporter, on_delete=models.CASCADE) def __str__(self): return self.headline class Meta: ordering = ('headline',) | cs |
1 2 3 4 | >>> r = Reporter(first_name='John', last_name='Smith', email='john@example.com') >>> r.save() >>> r2 = Reporter(first_name='Paul', last_name='Jones', email='paul@example.com') >>> r2.save() | 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 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | ### >>> from datetime import date >>> a = Article(id=None, headline="This is a test", pub_date=date(2005, 7, 27), reporter=r) >>> a.save() >>> a.reporter.id 1 >>> a.reporter <Reporter: John Smith> ### >>> r3 = Reporter(first_name='John', last_name='Smith', email='john@example.com') >>> Article.objects.create(headline="This is a test", pub_date=date(2005, 7, 27), reporter=r3) Traceback (most recent call last): ... ValueError: save() prohibited to prevent data loss due to unsaved related object 'reporter'. ### >>> r = a.reporter ### >>> new_article = r.article_set.create(headline="John's second story", pub_date=date(2005, 7, 29)) >>> new_article <Article: "John's second story"> >>> new_article.reporter <Reporter: John Smith> >>> new_article.reporter.id 1 ### >>> new_article2 = Article(headline="Paul's story", pub_date=date(2006, 1, 17)) >>> r.article_set.add(new_article2) >>> new_article2.reporter <Reporter: John Smith> >>> new_article2.reporter.id 1 >>> r.article_set.all() <QuerySet [<Article: John's second story>, <Article: Paul's story>, <Article: This is a test>]> ### >>> r2.article_set.add(new_article2) >>> new_article2.reporter.id 2 >>> new_article2.reporter <Reporter: Paul Jones> ### >>> r.article_set.add(r2) Traceback (most recent call last): ... TypeError: 'Article' instance expected >>> r.article_set.all() <QuerySet [<Article: "John's second story">, <Article: This is a test>]> >>> r2.article_set.all() <QuerySet [<Article: "Paul's story">]> >>> r.article_set.count() 2 >>> r2.article_set.count() 1 ### >>> r.article_set.filter(headline__startswith='This') <QuerySet [<Article: This is a test>]> # Find all Articles for any Reporter whose first name is "John". >>> Article.objects.filter(reporter__first_name='John') <QuerySet [<Article: "John's second story">, <Article: This is a test>]> ### >>> Article.objects.filter(reporter__first_name='John') <QuerySet [<Article: "John's second story">, <Article: This is a test>]> ### >>> Article.objects.filter(reporter__first_name='John', reporter__last_name='Smith') <QuerySet [<Article: "John's second story">, <Article: This is a test>]> ### >>> Article.objects.filter(reporter__pk=1) <QuerySet [<Article: "John's second story">, <Article: This is a test>]> >>> Article.objects.filter(reporter=1) <QuerySet [<Article: "John's second story">, <Article: This is a test>]> >>> Article.objects.filter(reporter=r) <QuerySet [<Article: "John's second story">, <Article: This is a test>]> >>> Article.objects.filter(reporter__in=[1,2]).distinct() <QuerySet [<Article: "John's second story">, <Article: "Paul's story">, <Article: This is a test>]> ### >>> Article.objects.filter(reporter__in=[r,r2]).distinct() <QuerySet [<Article: John's second story>, <Article: Paul's story>, <Article: This is a test>]> ### >>> Article.objects.filter(reporter__in=Reporter.objects.filter(first_name='John')).distinct() <QuerySet [<Article: "John's second story">, <Article: This is a test>]> ### >>> Reporter.objects.filter(article__pk=1) <QuerySet [<Reporter: John Smith>]> >>> Reporter.objects.filter(article=1) <QuerySet [<Reporter: John Smith>]> >>> Reporter.objects.filter(article=a) <QuerySet [<Reporter: John Smith>]> >>> Reporter.objects.filter(article__headline__startswith='This') <QuerySet [<Reporter: John Smith>, <Reporter: John Smith>, <Reporter: John Smith>]> >>> Reporter.objects.filter(article__headline__startswith='This').distinct() <QuerySet [<Reporter: John Smith>]> ### >>> Reporter.objects.filter(article__headline__startswith='This').count() 3 >>> Reporter.objects.filter(article__headline__startswith='This').distinct().count() 1 ### >>> Reporter.objects.filter(article__reporter__first_name__startswith='John') <QuerySet [<Reporter: John Smith>, <Reporter: John Smith>, <Reporter: John Smith>, <Reporter: John Smith>]> >>> Reporter.objects.filter(article__reporter__first_name__startswith='John').distinct() <QuerySet [<Reporter: John Smith>]> >>> Reporter.objects.filter(article__reporter=r).distinct() <QuerySet [<Reporter: John Smith>]> ### >>> Article.objects.all() <QuerySet [<Article: "John's second story">, <Article: "Paul's story">, <Article: This is a test>]> >>> Reporter.objects.order_by('first_name') <QuerySet [<Reporter: John Smith>, <Reporter: Paul Jones>]> >>> r2.delete() >>> Article.objects.all() <QuerySet [<Article: "John's second story">, <Article: This is a test>]> >>> Reporter.objects.order_by('first_name') <QuerySet [<Reporter: John Smith>]> >>> Reporter.objects.filter(article__headline__startswith='This').delete() >>> Reporter.objects.all() <QuerySet []> >>> Article.objects.all() <QuerySet []> | cs |
7. n대n 관계
1 2 3 4 5 6 7 8 9 | from django.db import models class Topping(models.Model): # ... pass class Pizza(models.Model): # ... toppings = models.ManyToManyField(Topping) | cs |
- 예제
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | from django.db import models class Publication(models.Model): title = models.CharField(max_length=30) def __str__(self): return self.title class Meta: ordering = ('title',) class Article(models.Model): headline = models.CharField(max_length=100) publications = models.ManyToManyField(Publication) def __str__(self): return self.headline class Meta: ordering = ('headline',) | 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 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 | ### >>> p1 = Publication(title='The Python Journal') >>> p1.save() >>> p2 = Publication(title='Science News') >>> p2.save() >>> p3 = Publication(title='Science Weekly') >>> p3.save() ### >>> a1 = Article(headline='Django lets you build Web apps easily') ### >>> a1.publications.add(p1) Traceback (most recent call last): ... ValueError: 'Article' instance needs to have a primary key value before a many-to-many relationship can be used. ### >>> a1.save() ### >>> a1.publications.add(p1) ### >>> a2 = Article(headline='NASA uses Python') >>> a2.save() >>> a2.publications.add(p1, p2) >>> a2.publications.add(p3) ### >>> a2.publications.add(p3) ### >>> a2.publications.add(a1) Traceback (most recent call last): ... TypeError: 'Publication' instance expected ### >>> new_publication = a2.publications.create(title='Highlights for Children') ### >>> a1.publications.all() <QuerySet [<Publication: The Python Journal>]> >>> a2.publications.all() <QuerySet [<Publication: Highlights for Children>, <Publication: Science News>, <Publication: Science Weekly>, <Publication: The Python Journal>]> ### >>> p2.article_set.all() <QuerySet [<Article: NASA uses Python>]> >>> p1.article_set.all() <QuerySet [<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>]> >>> Publication.objects.get(id=4).article_set.all() <QuerySet [<Article: NASA uses Python>]> ### >>> Article.objects.filter(publications__id=1) <QuerySet [<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>]> >>> Article.objects.filter(publications__pk=1) <QuerySet [<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>]> >>> Article.objects.filter(publications=1) <QuerySet [<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>]> >>> Article.objects.filter(publications=p1) <QuerySet [<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>]> >>> Article.objects.filter(publications__title__startswith="Science") <QuerySet [<Article: NASA uses Python>, <Article: NASA uses Python>]> >>> Article.objects.filter(publications__title__startswith="Science").distinct() <QuerySet [<Article: NASA uses Python>]> ### >>> Article.objects.filter(publications__title__startswith="Science").count() 2 >>> Article.objects.filter(publications__title__startswith="Science").distinct().count() 1 >>> Article.objects.filter(publications__in=[1,2]).distinct() <QuerySet [<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>]> >>> Article.objects.filter(publications__in=[p1,p2]).distinct() <QuerySet [<Article: Django lets you build Web apps easily>, <Article: NASA usesPython>]> ### >>> Publication.objects.filter(id=1) <QuerySet [<Publication: The Python Journal>]> >>> Publication.objects.filter(pk=1) <QuerySet [<Publication: The Python Journal>]> >>> Publication.objects.filter(article__headline__startswith="NASA") <QuerySet [<Publication: Highlights for Children>, <Publication: Science News>, ,!<Publication: Science Weekly>, <Publication: >>> Publication.objects.filter(article__id=1) <QuerySet [<Publication: The Python Journal>]> >>> Publication.objects.filter(article__pk=1) <QuerySet [<Publication: The Python Journal>]> >>> Publication.objects.filter(article=1) <QuerySet [<Publication: The Python Journal>]> >>> Publication.objects.filter(article=a1) <QuerySet [<Publication: The Python Journal>]> >>> Publication.objects.filter(article__in=[1,2]).distinct() <QuerySet [<Publication: Highlights for Children>, <Publication: Science News>, <Publication: Science Weekly>, <Publication: The Python Journal>]> >>> Publication.objects.filter(article__in=[a1,a2]).distinct() <QuerySet [<Publication: Highlights for Children>, <Publication: Science News>, <Publication: Science Weekly>, <Publication: The Python Journal>]> ### >>> Article.objects.exclude(publications=p2) <QuerySet [<Article: Django lets you build Web apps easily>]> ### >>> p1.delete() >>> Publication.objects.all() <QuerySet [<Publication: Highlights for Children>, <Publication: Science News>, <Publication: Science Weekly>]> >>> a1 = Article.objects.get(pk=1) >>> a1.publications.all() <QuerySet []> ### >>> a2.delete() >>> Article.objects.all() <QuerySet [<Article: Django lets you build Web apps easily>]> >>> p2.article_set.all() <QuerySet []> ### >>> a4 = Article(headline='NASA finds intelligent life on Earth') >>> a4.save() >>> p2.article_set.add(a4) >>> p2.article_set.all() <QuerySet [<Article: NASA finds intelligent life on Earth>]> >>> a4.publications.all() <QuerySet [<Publication: Science News>]> ### >>> new_article = p2.article_set.create(headline='Oxygen-free diet works wonders') >>> p2.article_set.all() <QuerySet [<Article: NASA finds intelligent life on Earth>, <Article: Oxygen-free diet works wonders>]> >>> a5 = p2.article_set.all()[1] >>> a5.publications.all() <QuerySet [<Publication: Science News>]> ### >>> a4.publications.remove(p2) >>> p2.article_set.all() <QuerySet [<Article: Oxygen-free diet works wonders>]> >>> a4.publications.all() <QuerySet []> ### >>> p2.article_set.remove(a5) >>> p2.article_set.all() <QuerySet []> >>> a5.publications.all() <QuerySet []> ### >>> a4.publications.all() <QuerySet [<Publication: Science News>]> >>> a4.publications.set([p3]) >>> a4.publications.all() <QuerySet [<Publication: Science Weekly>]> ### >>> p2.article_set.clear() >>> p2.article_set.all() <QuerySet []> ### >>> p2.article_set.add(a4, a5) >>> p2.article_set.all() <QuerySet [<Article: NASA finds intelligent life on Earth>, <Article: Oxygen-free diet works wonders>]> >>> a4.publications.all() <QuerySet [<Publication: Science News>, <Publication: Science Weekly>]> >>> a4.publications.clear() >>> a4.publications.all() <QuerySet []> >>> p2.article_set.all() <QuerySet [<Article: Oxygen-free diet works wonders>]> ### >>> p1 = Publication(title='The Python Journal') >>> p1.save() >>> a2 = Article(headline='NASA uses Python') >>> a2.save() >>> a2.publications.add(p1, p2, p3) ### >>> Publication.objects.filter(title__startswith='Science').delete() >>> Publication.objects.all() <QuerySet [<Publication: Highlights for Children>, <Publication: The Python Journal>]> >>> Article.objects.all() <QuerySet [<Article: Django lets you build Web apps easily>, <Article: NASA findsintelligent life on Earth>, <Article: NASA uses Python>, <Article: Oxygen-free dietworks wonders>]> >>> a2.publications.all() <QuerySet [<Publication: The Python Journal>]> ### >>> q = Article.objects.filter(headline__startswith='Django') >>> print(q) <QuerySet [<Article: Django lets you build Web apps easily>]> >>> q.delete() ### >>> print(q) <QuerySet []> >>> p1.article_set.all() <QuerySet [<Article: NASA uses Python>]> | cs |
- 추가 필드 예제
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | from django.db import models class Person(models.Model): name = models.CharField(max_length=128) def __str__(self): return self.name class Group(models.Model): name = models.CharField(max_length=128) members = models.ManyToManyField(Person, through='Membership') def __str__(self): return self.name class Membership(models.Model): person = models.ForeignKey(Person, on_delete=models.CASCADE) group = models.ForeignKey(Group, on_delete=models.CASCADE) date_joined = models.DateField() invite_reason = models.CharField(max_length=64) | 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 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | ### >>> ringo = Person.objects.create(name="Ringo Starr") >>> paul = Person.objects.create(name="Paul McCartney") >>> beatles = Group.objects.create(name="The Beatles") >>> m1 = Membership(person=ringo, group=beatles, ... date_joined=date(1962, 8, 16), ... invite_reason="Needed a new drummer.") >>> m1.save() >>> beatles.members.all() <QuerySet [<Person: Ringo Starr>]> >>> ringo.group_set.all() <QuerySet [<Group: The Beatles>]> >>> m2 = Membership.objects.create(person=paul, group=beatles, ... date_joined=date(1960, 8, 1), ... invite_reason="Wanted to form a band.") >>> beatles.members.all() <QuerySet [<Person: Ringo Starr>, <Person: Paul McCartney>]> ### >>> # The following statements will not work >>> beatles.members.add(john) >>> beatles.members.create(name="George Harrison") >>> beatles.members.set([john, paul, ringo, george]) ### >>> Membership.objects.create(person=ringo, group=beatles, ... date_joined=date(1968, 9, 4), ... invite_reason="You've been gone for a month and we miss you.") >>> beatles.members.all() <QuerySet [<Person: Ringo Starr>, <Person: Paul McCartney>, <Person: Ringo Starr>]> >>> # This will not work because it cannot tell which membership to remove >>> beatles.members.remove(ringo) ### >>> # Beatles have broken up >>> beatles.members.clear() >>> # Note that this deletes the intermediate model instances >>> Membership.objects.all() <QuerySet []> ### # Find all the groups with a member whose name starts with 'Paul' >>> Group.objects.filter(members__name__startswith='Paul') <QuerySet [<Group: The Beatles>]> ### # Find all the members of the Beatles that joined after 1 Jan 1961 >>> Person.objects.filter( ... group__name='The Beatles' ... membership__date_joined__gt=date(1961,1,1)) <QuerySet [<Person: Ringo Starr]> ### >>> ringos_membership = Membership.objects.get(group=beatles, person=ringo) >>> ringos_membership.date_joined datetime.date(1962, 8, 16) >>> ringos_membership.invite_reason 'Needed a new drummer.' ### >>> ringos_membership = ringo.membership_set.get(group=beatles) >>> ringos_membership.date_joined datetime.date(1962, 8, 16) >>> ringos_membership.invite_reason 'Needed a new drummer.' | cs |
8. Models across files
1 2 3 4 5 6 7 8 9 10 11 | from django.db import models from geography.models import ZipCode class Restaurant(models.Model): # ... zip_code = models.ForeignKey( ZipCode, on_delete=models.SET_NULL, blank=True, null=True, ) | cs |
9. Field 명 제약
1 2 3 4 5 6 7 | class Example(models.Model): pass = models.IntegerField() # 'pass' is a reserved word! class Example(models.Model): foo__bar = models.IntegerField() # 'foo__bar' has two underscores! | cs |
- 예약어
- 2번의 언더스코어
10. Meta options
1 2 3 4 5 6 7 | from django.db import models class Ox(models.Model): horn_length = models.IntegerField() class Meta: ordering = ["horn_length"] verbose_name_plural = "oxen" | cs |
- ordering : 정렬 컬럼 설정
- verbose_name : 요약된 컬럼의 이름
- verbose_name_plural : verbose_name의 복수형
- db_table : 테이블명
- base_manager_name : manager 지정
- abstract : 추상모델 (부모클래스는 DB에 테이블이 생성되지 않는다.)
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 | ### from django.db import models class CommonInfo(models.Model): name = models.CharField(max_length=100) age = models.PositiveIntegerField() class Meta: abstract = True class Student(CommonInfo): home_group = models.CharField(max_length=5) ### from django.db import models class CommonInfo(models.Model): # ... class Meta: abstract = True ordering = ['name'] class Student(CommonInfo): # ... class Meta(CommonInfo.Meta): db_table = 'student_info' | 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 | ### from django.db import models class Person(models.Model): first_name = models.CharField(max_length=30) last_name = models.CharField(max_length=30) class MyPerson(Person): class Meta: proxy = True def do_something(self): # ... pass ### >>> p = Person.objects.create(first_name="foobar") >>> MyPerson.objects.get(first_name="foobar") <MyPerson: foobar> ### class OrderedPerson(Person): class Meta: ordering = ["last_name"] proxy = True | cs |
11. Models methods
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | from django.db import models class Person(models.Model): first_name = models.CharField(max_length=50) last_name = models.CharField(max_length=50) birth_date = models.DateField() def baby_boomer_status(self): "Returns the person's baby-boomer status." import datetime if self.birth_date < datetime.date(1945, 8, 1): return "Pre-boomer" elif self.birth_date < datetime.date(1965, 1, 1): return "Baby boomer" else: return "Post-boomer" @property def full_name(self): "Returns the person's full name." return '%s %s' % (self.first_name, self.last_name) | cs |
- property 데코레이터를 사용하여 얻고 싶은 값을 지정하는 getter
- get_absolte_url() : 개별 데이터 접근 url (PK 접근)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | ### def get_absolute_url(self): return "/people/%i/" % self.id ### def get_absolute_url(self): from django.urls import reverse return reverse('people.views.details', args=[str(self.id)]) ### <!-- BAD template code. Avoid! --> <a href="/people/{{ object.id }}/">{{ object.name }}</a> ### <!-- Much better! --> <a href="{{ object.get_absolute_url }}">{{ object.name }}</a> | cs |
- save() : 데이터 저장시 추가 작업을 할 경우
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ### from django.db import models class Blog(models.Model): name = models.CharField(max_length=100) tagline = models.TextField() def save(self, *args, **kwargs): do_something() super().save(*args, **kwargs) # Call the "real" save() method. do_something_else() ### from django.db import models class Blog(models.Model): name = models.CharField(max_length=100) tagline = models.TextField() def save(self, *args, **kwargs): if self.name == "Yoko Ono's blog": return # Yoko shall never have her own blog! else: super().save(*args, **kwargs) # Call the "real" save() method. | cs |
12. Model 상속
- Multi-table inheritance (부모는 자식을 포함한다.)
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 | ### from django.db import models class Place(models.Model): name = models.CharField(max_length=50) address = models.CharField(max_length=80) class Restaurant(Place): serves_hot_dogs = models.BooleanField(default=False) serves_pizza = models.BooleanField(default=False) ### >>> Place.objects.filter(name="Bob's Cafe") >>> Restaurant.objects.filter(name="Bob's Cafe") ### >>> p = Place.objects.get(id=12) # If p is a Restaurant object, this will give the child class: >>> p.restaurant <Restaurant: ...> ### place_ptr = models.OneToOneField( Place, on_delete=models.CASCADE, parent_link=True, ) |
- Meta and multi-table inheritance
(자식은 부모의 Meta 클래스를 상속받지 않지만, ordering, get_latest_by 옵션이 설정되지 않았을 경우에만 해당 설정값을 상속받는다.)
1 2 3 4 5 | class ChildModel(ParentModel): # ... class Meta: # Remove parent's ordering effect ordering = [] | cs |
- Inheritance and reverse relations
(부모를 N대N으로 관계를 맺으면 에러가 발생한다. 에러를 막기위해 related_name을 설정한다.)
1 2 3 4 5 6 7 8 9 10 11 12 13 | ### class Supplier(Place): customers = models.ManyToManyField(Place) ### Reverse query name for 'Supplier.customers' clashes with reverse query name for 'Supplier.place_ptr'. HINT: Add or change a related_name argument to the definition for 'Supplier.customers' or 'Supplier.place_ptr'. ### models. ManyToManyField(Place, related_name='provider') | cs |