나는 Django에 대해 잘 알고 있지만 최근 on_delete=models.CASCADE에는 모델에 대한 옵션 이 있음을 발견 했으며 같은 문서를 검색했지만 더 이상 찾을 수 없었습니다.
장고 1.9에서 변경 :
on_delete이제 두 번째 위치 인수로 사용할 수 있습니다 (이전에는 일반적으로 키워드 인수로만 전달됨). Django 2.0에서는 필수 인수입니다.
from django.db import models
class Car(models.Model):
    manufacturer = models.ForeignKey(
        'Manufacturer',
        on_delete=models.CASCADE,
    )
    # ...
class Manufacturer(models.Model):
    # ...
    pass
on_delete는 무엇을합니까? ( 모델이 삭제되면 수행해야 할 작업 )
무엇을 models.CASCADE합니까? ( 문서의 힌트 )
다른 옵션을 사용할 수 있습니까 ( 내 추측이 맞다면 )?
이에 대한 문서는 어디에 있습니까?
답변
이것은 참조 된 객체가 삭제 될 때 채택하는 동작 입니다. django에만 국한된 것은 아니며 SQL 표준입니다.
이러한 이벤트가 발생할 때 수행 할 수있는 6 가지 가능한 조치가 있습니다.
CASCADE: 참조 된 오브젝트가 삭제되면 해당 오브젝트를 참조하는 오브젝트도 삭제하십시오 (예를 들어 블로그 게시물을 제거 할 때 주석도 삭제하려고 할 수 있음). SQL에 상응하는 내용 :CASCADE.PROTECT: 참조 된 객체의 삭제를 금지합니다. 삭제하려면 수동으로 참조하는 모든 객체를 삭제해야합니다. SQL에 상응하는 내용 :RESTRICT.SET_NULL: 참조를 NULL로 설정하십시오 (필드가 널 입력 가능해야 함). 예를 들어, 사용자를 삭제할 때 블로그 게시물에 게시 한 주석은 유지하지만 익명 (또는 삭제 된) 사용자가 게시 한 것으로 말할 수 있습니다. SQL에 상응하는 내용 :SET NULL.SET_DEFAULT: 기본값을 설정합니다. SQL에 상응하는 내용 :SET DEFAULT.SET(...): 주어진 값을 설정합니다. 이것은 SQL 표준의 일부가 아니며 Django가 전적으로 처리합니다.DO_NOTHING: 데이터베이스에 무결성 문제 (실제로는 존재하지 않는 개체 참조)가 발생할 수 있으므로 매우 나쁜 아이디어 일 수 있습니다. SQL에 상응하는 내용 :NO ACTION.
출처 : Django documentation
예를 들어 PostGreSQL의 문서 도 참조하십시오 .
대부분의 경우 CASCADE예상되는 동작이지만 모든 ForeignKey에 대해 항상이 상황에서 예상되는 동작이 무엇인지 자문해야합니다. PROTECT그리고 SET_NULL종종 유용하다. CASCADE원하지 않는 위치를 설정 하면 단일 사용자를 삭제하여 모든 데이터베이스를 계단식으로 삭제할 수 있습니다.
계단식 방향을 명확하게하기위한 추가 참고 사항
CASCADE행동 의 방향이 많은 사람들에게 명확하지 않다는 것을 알아 두는 것이 재미있다 . 사실, 그 통지에 재미 만CASCADE 조치가 명확하지 않다. 캐스케이드 동작이 혼동 될 수 있음을 이해하지만 다른 동작과 동일한 방향 이라고 생각해야합니다 . 따라서 CASCADE지시가 명확하지 않다고 생각되면 실제로 on_delete행동이 명확하지 않다는 것을 의미 합니다.
데이터베이스에서 외래 키는 기본적으로 정수 필드로 표시되며 값은 외래 객체의 기본 키입니다. 항목 article_B에 대한 외래 키 가있는 항목 comment_A 가 있다고 가정 해 봅시다 . 당신이 항목을 삭제하면 comment_A을 , 모든 벌금입니다 article_B이 없이 살았 comment_A 과이 삭제됩니다 경우 귀찮게하지 않습니다. 그러나, 당신은 삭제 article_B을 한 후, comment_A의 패닉! 그것은 article_B 없이는 살지 않았으며 그것을 필요로합니다. 그것은 그것의 속성의 일부입니다 ( 그러나 * article_B ** ???는 무엇입니까). 이 무결성 오류 를 해결하는 방법을 결정하기위한 단계입니다.article=article_Bon_delete다음과 같이 말하면됩니다.
- “아니오! 제발! 하지마! 난 너 없이는 살 수 없어!” ( 
PROTECTSQL 언어로 알려짐) - “나는 당신을 아니에요 경우 좋아는, 그때는 아무도 해요” (라고한다 
SET_NULL) - “안녕 세상에, article_B 없이는 살 수 없어” 자살 (이것은 
CASCADE행동입니다). - “괜찮아, 여분의 애인이있어, 지금부터 article_C를 참조 할 것이다” ( 
SET_DEFAULT또는 심지어SET(...)). - “나는 현실에 직면 할 수 없다, 그것이 나에게 남아있는 유일한 것이더라도 계속 너의 이름을 부르겠다!” ( 
DO_NOTHING) 
캐스케이드 방향이 더 명확 해지기를 바랍니다. 🙂
답변
이 on_delete방법은 삭제 한 모델 인스턴스에 의존하는 모델 인스턴스로 수행 할 작업을 Django에 알리는 데 사용됩니다. (예 : ForeignKey관계). 은 on_delete=models.CASCADE즉뿐만 아니라 종속 모델을 삭제 계속 삭제 효과를 계단식으로 장고를 알려줍니다.
보다 구체적인 예는 다음과 같습니다. 당신은이 가정 Author인 모델 ForeignKeyA의 Book모델을. 이제 Author모델 의 인스턴스를 삭제하면 Django는 해당 Book모델의 인스턴스에 의존 하는 모델의 인스턴스로 수행 할 작업을 알 수 없습니다 Author. 이 on_delete방법은 Django에게이 경우 수행 할 작업을 알려줍니다. 설정 on_delete=models.CASCADE하면 Django가 삭제 효과를 계단식으로 표시합니다. 즉, 삭제 한 Book모델 인스턴스에 따라 모든 모델 인스턴스가 Author삭제됩니다.
참고 : on_deleteDjango 2.0에서는 필수 인수가됩니다. 이전 버전에서는 기본값이 CASCADE입니다.
답변
참고로, on_delete모델 의 매개 변수는 원래의 소리와 반대입니다. on_delete레코드에서 가리키고있는 FK 항목이 삭제 된 경우 django에 수행 할 작업을 알려주기 위해 모델에 외래 키 (FK)를 착용 합니다. 옵션 저희 가게는 대부분이 사용하고 PROTECT, CASCADE하고 SET_NULL. 내가 알아 낸 기본 규칙은 다음과 같습니다.
- 사용하다 
PROTECT하여 FK 정말 변경해서는 안하고가하는 룩업 테이블을 가리키는 경우 확실히 변화에 테이블을 야기해서는 안된다. 해당 룩업 테이블에서 항목을 삭제하려고PROTECT하면 레코드에 묶여 있으면 삭제되지 않습니다. 또한 방지 삭제에서 장고 당신 은 룩업 테이블에서 항목을 삭제해서 기록을. 이 마지막 부분이 중요합니다. 누군가가 성별 테이블에서 성별 “여성”을 삭제하려는 경우, 본인은 해당 성별을 가진 Person 테이블에있는 모든 사람을 즉시 삭제하기를 원하지 않습니다. - 사용하다 
CASCADEFK가 “부모”레코드를 가리킬 때 . 사람이 많은 PersonEthnicity 항목을 가질 수 있습니다 경우에 따라서, (그 / 그녀는 아메리칸 인디언, 흑인과 백인이 될 수 있습니다), 그리고 사람이 있다고 한다 삭제, 난 정말 것이다 어떤 “아이”PersonEthnicity 항목을 삭제하고 싶습니다. 그것들은 사람 없이는 관련이 없습니다. SET_NULL당신이 할 때 사용 않는 사람들이 룩업 테이블에서 항목을 삭제하도록 허용 할,하지만 당신은 여전히 당신의 기록을 보존하고자합니다. 예를 들어, 한 사람이 HighSchool을 가질 수 있지만 해당 고등학교가 내 룩업 테이블에서 사라지면 실제로 중요하지 않습니다on_delete=SET_NULL. 이것은 내 개인 기록을 거기에 남겨 둘 것입니다. 내 Person의 고등학교 FK를 null로 설정했을뿐입니다. 분명히, 당신은null=True그 FK 를 허용해야합니다 .
다음은 세 가지를 모두 수행하는 모델의 예입니다.
class PurchPurchaseAccount(models.Model):
    id = models.AutoField(primary_key=True)
    purchase = models.ForeignKey(PurchPurchase, null=True, db_column='purchase', blank=True, on_delete=models.CASCADE) # If "parent" rec gone, delete "child" rec!!!
    paid_from_acct = models.ForeignKey(PurchPaidFromAcct, null=True, db_column='paid_from_acct', blank=True, on_delete=models.PROTECT) # Disallow lookup deletion & do not delete this rec.
    _updated = models.DateTimeField()
    _updatedby = models.ForeignKey(Person, null=True, db_column='_updatedby', blank=True, related_name='acctupdated_by', on_delete=models.SET_NULL) # Person records shouldn't be deleted, but if they are, preserve this PurchPurchaseAccount entry, and just set this person to null.
    def __unicode__(self):
        return str(self.paid_from_acct.display)
    class Meta:
        db_table = u'purch_purchase_account'
마지막 골치 아픈 사람 이 아니라면 지정on_delete (또는 지정 하지 않은 경우) 기본 동작은 CASCADE? 이는 누군가 성별 테이블에서 성별 항목을 삭제 한 경우 해당 성별을 가진 모든 사람 레코드도 삭제되었음을 의미합니다.
나는 “의심 스럽다면 설정 on_delete=models.PROTECT하십시오” 라고 말할 것입니다 . 그런 다음 응용 프로그램을 테스트하십시오. 데이터를 위험에 빠뜨리지 않고 어떤 FK에 다른 값을 표시해야하는지 신속하게 파악할 수 있습니다.
또한 on_delete=CASCADE선택한 동작 인 경우 실제로는 마이그레이션에 추가되지 않습니다. 나는 이것이 기본값이기 때문에 추측합니다 on_delete=CASCADE. 퍼팅은 아무것도 넣지 않는 것과 같습니다.
답변
앞에서 언급했듯이 CASCADE는 외래 키가있는 레코드를 삭제하고 삭제 된 다른 개체를 참조합니다. 예를 들어 부동산 웹 사이트가 있고 도시를 참조하는 부동산이있는 경우
class City(models.Model):
    # define model fields for a city
class Property(models.Model):
    city = models.ForeignKey(City, on_delete = models.CASCADE)
    # define model fields for a property
이제 도시가 데이터베이스에서 삭제되면 모든 관련 속성 (예 : 해당 도시에있는 부동산)도 데이터베이스에서 삭제됩니다.
이제 SET_NULL 또는 SET_DEFAULT 또는 DO_NOTHING과 같은 다른 옵션의 장점을 언급하고 싶습니다. 기본적으로 관리 관점에서 해당 레코드를 “삭제”하려고합니다. 그러나 당신은 그들이 사라지기를 정말로 원하지 않습니다. 여러 이유들로. 누군가 실수로 삭제했거나 감사 및 모니터링을 위해 삭제했을 수 있습니다. 그리고 평범한보고. 따라서 도시에서 재산을 “분리”하는 방법이 될 수 있습니다. 다시 말하지만, 신청서 작성 방법에 따라 다릅니다.
예를 들어, 일부 응용 프로그램에는 “삭제 된”필드가 0 또는 1입니다. 모든 검색 및 목록보기 등 보고서 또는 사용자가 프런트 엔드에서 액세스 할 수있는 모든 위치 등은 제외됩니다 deleted == 1. 그러나 사용자 정의 보고서 또는 사용자 정의 조회를 작성하여 삭제 된 레코드 목록을 풀다운하여 레코드를 마지막으로 수정 한시기 (다른 필드) 및 사용자 (예 : 누가 삭제 한시기 및시기)를 확인할 수 있습니다. 그것은 경영진의 입장에서 매우 유리합니다.
그리고 deleted = 0그 기록 만큼 간단하게 실수로 삭제 한 내용을 되돌릴 수 있습니다 .
내 요점은 기능이 있다면 그 뒤에 항상 이유가 있다는 것입니다. 항상 좋은 이유는 아닙니다. 그러나 이유가 있습니다. 그리고 종종 좋은 것도 있습니다.
답변
다음은 귀하의 질문에 대한 답변입니다. 왜 우리는 on_delete를 사용합니까?
ForeignKey가 참조하는 객체가 삭제되면 Django는 기본적으로 SQL 제약 조건 ON DELETE CASCADE의 동작을 에뮬레이트하고 ForeignKey를 포함하는 객체를 삭제합니다. on_delete 인수를 지정하여이 동작을 대체 할 수 있습니다. 예를 들어 nullable ForeignKey가 있고 참조 된 개체가 삭제 될 때 null로 설정하려는 경우 :
user = models.ForeignKey(User, blank=True, null=True, on_delete=models.SET_NULL)
on_delete에 가능한 값은 django.db.models에 있습니다.
캐스케이드 : 캐스케이드가 삭제됩니다. 디폴트
보호 : django.db.IntegrityError의 서브 클래스 인 ProtectedError를 발생시켜 참조 된 오브젝트의 삭제를 방지하십시오.
SET_NULL : ForeignKey를 null로 설정하십시오. null이 True 인 경우에만 가능합니다.
SET_DEFAULT : ForeignKey를 기본값으로 설정하십시오. ForeignKey의 기본값을 설정해야합니다.
답변
Person 이라는 모델 과 Companies 라는 모델이 있다고 가정 해 봅시다 .
정의에 따라 한 사람이 여러 회사를 만들 수 있습니다.
회사에 한 사람 만있을 수 있다는 점을 고려하면, 사람이 삭제 될 때 해당 사람과 연관된 모든 회사도 삭제되기를 원합니다.
먼저 Person 모델을 생성합니다.
class Person(models.Model):
    id = models.IntegerField(primary_key=True)
    name = models.CharField(max_length=20)
    def __str__(self):
        return self.id+self.name
그러면 회사 모델은 다음과 같습니다.
class Companies(models.Model):
    title = models.CharField(max_length=20)
    description=models.CharField(max_length=10)
    person= models.ForeignKey(Person,related_name='persons',on_delete=models.CASCADE)
on_delete=models.CASCADE회사 모델에서 사용법을 확인 하십시오. 즉, 회사를 소유 한 사람 (Person 클래스의 인스턴스)이 삭제 될 때 모든 회사를 삭제하는 것입니다.
답변
기존 캐스케이드 (예 : 폭포)에 FK를 추가하여 “CASCADE”기능의 정신 모델 방향을 다시 지정하십시오. 이 폭포의 출처는 기본 키입니다. 흐름을 삭제합니다.
따라서 FK의 on_delete를 “CASCADE”로 정의하면이 FK의 레코드를 PK에서 발생하는 일련의 삭제에 추가합니다. FK의 기록은이 계단식에 참여하거나 참여하지 않을 수 있습니다 ( “SET_NULL”). 실제로 FK가있는 레코드는 삭제의 흐름을 방해 할 수도 있습니다! “PROTECT”로 댐을 만드십시오.
