ORM(Object Relational Mapping) : 객체 관계 맵핑OOP(Object Oriented Programming) : 객체 지향 프로그래밍 RDB(Relational Database) : 관계형 데이터베이스queryset 이라는 프로젝트 파일 생성blogs 라는 앱 생성models.py 작성from django.db import models
class Blog(models.Model):
name = models.CharField(max_length=100)
tagline = models.TextField()
class Meta:
db_table = "blogs"
class Author(models.Model):
name = models.CharField(max_length=200)
email = models.EmailField()
class Meta:
db_table = "authors"
class Entry(models.Model):
blog = models.ForeignKey(Blog, on_delete=models.CASCADE)
headline = models.CharField(max_length=255)
body_text = models.TextField()
pub_date = models.DateField()
mod_date = models.DateField()
authors = models.ManyToManyField(Author)
number_of_comments = models.IntegerField()
number_of_pingbacks = models.IntegerField()
rating = models.IntegerField()
class Meta:
db_table = "entries"
DB와 연동 후 ORM 연습을 하기 위한 임의의 데이터 삽입
ManyToMany 테이블 : entries 테이블과 authors 테이블은 다대다 관계로 연결되어 있다. 그렇기 때문에 DB에 자동으로 entries_authors라는 중간 테이블이 생겼다. 이 ManyToMany 테이블 기능은 장고에만 있는 기능이라고 한다.
Q.
다대다 관계의 테이블은 ORM 어떻게 쓰는지 확인


Q.
다대다 관계인데authors = models.ManyToManyField(Author)이 컬럼이 entries 테이블이 있는 상황이다. 만약에 authors 테이블에entries = models.ManyToManyField(Entry)컬럼을 생성하면 어떻게 될까?
Q.
Column(컬럼), row(로우), field(필드) 란?
Q.
쿼리셋을 반환하는 메소드와 그렇지 않은 메소드
- QuerySet 반환하는 :
all,filter,exclude,values,values_list,
추가 공부할 메소드 :annotate,order_by,select_related,prefetch_related- QuerySet 반환하지 않는(=인스턴스를 반환) :
create,get,update,delete,save,exists
추가 공부할 메소드 :get_or_create,update_or_create,bulk_create,bultk_update,count,first,aggregate
In [17]: Author.objects.all()
Out[17]: <QuerySet [<Author: Author object (1)>, <Author: Author object (2)>, <Author: Author object (3)>, <Author: Author object (4)>]>
all()과 같이 쿼리셋을 반환하는 메소드들은 for 문과 함께 쓰이면서 쿼리셋 안의 인스턴스 하나하나에 접근하여 사용된다In [22]: for author in Author.objects.all():
...: print(author.id)
...:
1
2
3
4
In [23]: for author in Author.objects.all():
...: print(author.name)
...:
김민호
taehoon
지광선
최은환
In [24]: for author in Author.objects.all():
...: print(author.email)
...:
minho@gmail.com
taehoon@gmail.com
wlrhkdtjs@gmail.com
chldmsghks@gmail.com
filter(**kwargs) : 키워드 인자로 주어진 lookup 조건에 일치하는 레코드들의 QuerySet을 반환한다.In [29]: Blog.objects.filter(tagline="태그1")
Out[29]: <QuerySet [<Blog: Blog object (1)>, <Blog: Blog object (4)>, <Blog: Blog object (5)>]>
In [30]: Blog.objects.filter(tagline="태그1").filter(id=4)
Out[30]: <QuerySet [<Blog: Blog object (4)>]>
In [31]: Blog.objects.filter(tagline="태그1").filter(id=2)
Out[31]: <QuerySet []>
In [32]: Blog.objects.filter(tagline="태그1").exclude(id=4)
Out[32]: <QuerySet [<Blog: Blog object (1)>, <Blog: Blog object (5)>]>
In [34]: Blog.objects.all().values()
Out[34]: <QuerySet [
{'id': 1, 'name': '김민호블로그', 'tagline': '태그1'},
{'id': 2, 'name': '김민호블로그2', 'tagline': '태그22'},
{'id': 3, 'name': '김민호블로그3', 'tagline': '태그33'},
{'id': 4, 'name': '김태훈블로그', 'tagline': '태그1'},
{'id': 5, 'name': '', 'tagline': '태그1'}
]>
bracket notation으로 불러와야 한다In [49]: blogs = Blog.objects.filter(tagline="태그1").values()
In [50]: blogs
Out[50]: <QuerySet [
{'id': 1, 'name': '김민호블로그', 'tagline': '태그1'},
{'id': 4, 'name': '김태훈블로그', 'tagline': '태그1'},
{'id': 5, 'name': '', 'tagline': '태그1'}
]>
In [51]: for blog in blogs:
...: print(blog["id"])
...:
1
4
5
dot notation 으로 접근하면 AtrributeError 발생
In [52]: for blog in blogs:
...: print(blog.id)
...:
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-52-b3c04ad11c93> in <module>
1 for blog in blogs:
----> 2 print(blog.id)
3
AttributeError: 'dict' object has no attribute 'id'
values() 가 딕셔너리를 반환한다면, values_list()는 튜플을 반환한다In [53]: Blog.objects.all().values_list()
Out[53]: <QuerySet [
(1, '김민호블로그', '태그1'),
(2, '김민호블로그2', '태그22'),
(3, '김민호블로그3', '태그33'),
(4, '김태훈블로그', '태그1'),
(5, '', '태그1')
]>
In [9]: author1 = Author.objects.create(name="최은환", email="chldmsghks@gmail.com")
In [10]: author1
Out[10]: <Author: Author object (4)>
In [11]: author1.name
Out[11]: '최은환'
In [12]: author1.email
Out[12]: 'chldmsghks@gmail.com'
In [13]: Author.objects.get(id=2)
Out[13]: <Author: Author object (2)>
In [14]: print(Author.objects.get(id=2))
Author object (2)
In [15]: a = Author.objects.get(id=2)
In [16]: print(a)
Author object (2)
행 수를 반환한다In [59]: Blog.objects.filter(id=3).update(tagline="홀수 태그")
Out[59]: 1 # 총 업데이트된 row 개수
삭제 된 개체 수와 개체 유형별 삭제 횟수가 있는 dictionary를 반환한다In [60]: Blog.objects.filter(id=5).delete()
Out[60]: (1, {'blogs.Blog': 1})
INSERT 또는 UPDATE 를 수행하는 method로, 단일 객체에 대해서 업데이트를 수행할 때 많이 사용
id=4인 인스턴스를 변수 blog에 담고 그 인스턴스의 name 필드를 불러오면 아래와 같다.
In [73]: blog = Blog.objects.get(id=4)
In [74]: blog.name
Out[74]: '김태훈의 블로그'
여기서 '김태훈의 블로그'라는 이름을 수정하고 싶을 경우
In [75]: blog.name = "김태훈의 새로운 블로그!!!!!"
이라고 blog.name을 새롭게 선언해준다. 이제 쉘에서 blog.name를 치면 "김태훈의 새로운 블로그!!!!!" 이게 나오지만 현재 데이터베이스에는 저장이 되지 않은 상황이다. "김태훈의 새로운 블로그!!!!!"를 DB에 저장하고 싶을 경우에 save() 메소드를 쓴다
In [76]: blog.save()
In [77]: blog.name
Out[77]: '김태훈의 새로운 블로그!!!!!'

In [78]: Blog.objects.filter(id=3).exists()
Out[78]: True
In [79]: Blog.objects.filter(tagline="태그태그").exists()
Out[79]: False