bulk_create
메서드를 이용하면 여러 개의 신규 객체를 한 번에 저장 가능>>> Category.objects.all().count()
2
>>> Category.objects.bulk_create([Category(name="God"),Category(name="Demi God"),Category(name="Mortal")])
[<Category: God>, <Category: Demi God>, <Category: Mortal>]
>>> Category.objects.all().count()
5
pk
필드 값이 None
으로 지정되어 있으면 데이터베이스에 새 행으로 저장>>> Hero.objects.all().count()
4
>>> hero = Hero.objects.first()
>>> hero.pk = None
>>> hero.save()
>>> Hero.objects.all().count()
5
Origin
이라는 모델을 싱글턴(단일개체)으로 만드는 기법class Origin(models.Model):
name = models.CharField(max_length=100)
def save(self, *args, **kwargs):
if self.__class__.objects.count():
self.pk = self.__class__.objects.first().pk
super().save(*args, **kwargs)
save
메서드를 재정의하여 pk
필드를 이미 존재하는 값으로 지정하도록 강제create
메서드를 호출하는 경우 IntegrityError
예외가 발생hero_count
필드와 villain_count
필드를 갱신해야 할 때save
메서드를 재정의하면 됨class Hero(models.Model):
# ...
def save(self, *args, **kwargs):
if not self.pk:
Category.objects.filter(pk=self.category_id).update(hero_count=F('hero_count')+1)
super().save(*args, **kwargs)
class Villain(models.Model):
# ...
def save(self, *args, **kwargs):
if not self.pk:
Category.objects.filter(pk=self.category_id).update(villain_count=F('villain_count')+1)
super().save(*args, **kwargs)
self.category.hero_count += 1
과 같이 인스턴스의 값을 수정하는 것이 아니라, update 메서드로 데이터베이스의 갱신을 수행Tip! 추가 내용
hero_count
필드와 villain_count
필드를 갱신해야 할 때from django.db.models.signals import pre_save
from django.dispatch import receiver
@receiver(pre_save, sender=Hero, dispatch_uid="update_hero_count")
def update_hero_count(sender, **kwargs):
hero = kwargs['instance']
if hero.pk:
Category.objects.filter(pk=hero.category_id).update(hero_count=F('hero_count')+1)
@receiver(pre_save, sender=Villain, dispatch_uid="update_villain_count")
def update_villain_count(sender, **kwargs):
villain = kwargs['instance']
if villain.pk:
Category.objects.filter(pk=villain.category_id).update(villain_count=F('villain_count')+1)
save
메서드를 재정의하는 방법과 시그널을 이용하는 방법 모두 사용 가능save
메서드를 재정의delete
메서드를 이용해 비슷한 결과를 얻을 수 있음>>> Category.objects.all().count()
7
>>> Category.objects.all().delete()
(7, {'entity.Category': 7})
>>> Category.objects.all().count()
0
DELETE FROM ...
과 같은 SQL 질의를 수행truncate
명령이 필요하다면 다음과 같이 Category
모델에 classmethod
로 추가하면 됨class Category(models.Model):
# ...
@classmethod
def truncate(cls):
with connection.cursor() as cursor:
cursor.execute('TRUNCATE TABLE "{0}" CASCADE'.format(cls._meta.db_table))
Category.truncate()
를 실행하여 정말로 데이터베이스 시스템에 TRUNCATE 문을 질의할 수 있음pre_init
post_init
pre_save
post_save
pre_delete
post_delete
save
메서드를 재정의하는 것과 비슷한 효과를 누릴 수 있음save
메서드를 재정의·커스터마이즈하도록 허용하려면 직접 시그널을 발생시켜야 함save
메서드가 호출될 때 원하는 코드가 실행되도록 하려면 post_save
시그널 또는 pre_save
시그널을 이용해야 함save
메서드를 재정의해야 함>>> user = User.objects.get(id=1)
>>> date_str = "2018-03-11"
>>> from django.utils.dateparse import parse_date
>>> temp_date = parse_date(date_str)
>>> a1 = Article(headline="String converted to date", pub_date=temp_date, reporter=user)
>>> a1.save()
>>> a1.pub_date
datetime.date(2018, 3, 11)
>>> from datetime import datetime
>>> temp_date = datetime.strptime(date_str, "%Y-%m-%d").date()
>>> a2 = Article(headline="String converted to date way 2", pub_date=temp_date, reporter=user)
>>> a2.save()
>>> a2.pub_date
datetime.date(2018, 3, 11)