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