on_delete ทำในรุ่น Django ได้อย่างไร


348

ฉันค่อนข้างคุ้นเคยกับ Django แต่เมื่อไม่นานมานี้พบว่ามีon_delete=models.CASCADEตัวเลือกสำหรับรุ่นฉันค้นหาเอกสารเหมือนกัน แต่ไม่พบอะไรมากไปกว่า:

เปลี่ยนเป็น Django 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ทำอย่างไร ( คำแนะนำใด ๆ ในเอกสาร )

มีตัวเลือกอื่น ๆ อีกบ้าง ( ถ้าฉันเดาถูกต้อง )

เอกสารสำหรับที่อยู่อาศัยนี้อยู่ที่ไหน


นอกจากนี้ยังมีคำตอบสำหรับคำถามที่คล้ายกันที่stackoverflow.com/questions/47914325/…
HelenM

1
ข้อความจากคำถามที่คล้ายกันนี้อยู่ในรายการด้านล่างในคำตอบนี้ มันเริ่มต้น "FYI พารามิเตอร์ on_delete ในแบบจำลองจะย้อนกลับจากที่ฟังดูเหมือน" มันให้รายละเอียดมากกว่าคำตอบดั้งเดิม
HelenM

คำตอบ:


785

นี่คือพฤติกรรมที่จะนำมาใช้เมื่อวัตถุที่อ้างอิงถูกลบ ไม่เฉพาะเจาะจงกับ django นี่เป็นมาตรฐาน SQL

มี 6 การกระทำที่เป็นไปได้เมื่อเหตุการณ์ดังกล่าวเกิดขึ้น:

  • CASCADE: เมื่อลบออบเจ็กต์อ้างอิงแล้วให้ลบออบเจ็กต์ที่มีการอ้างอิงด้วย (เมื่อคุณลบโพสต์บล็อกเช่นคุณอาจต้องการลบความคิดเห็นด้วย) เทียบเท่า CASCADESQL:
  • PROTECT: ห้ามการลบวัตถุอ้างอิง ในการลบคุณจะต้องลบวัตถุทั้งหมดที่อ้างอิงด้วยตนเอง เทียบเท่า RESTRICTSQL:
  • SET_NULL: ตั้งค่าการอ้างอิงเป็น NULL (ต้องการให้ฟิลด์เป็นโมฆะ) ตัวอย่างเช่นเมื่อคุณลบผู้ใช้คุณอาจต้องการเก็บความคิดเห็นที่เขาโพสต์ไว้ในบล็อกโพสต์ แต่บอกว่ามันถูกโพสต์โดยผู้ใช้ที่ไม่ระบุชื่อ (หรือถูกลบ) เทียบเท่า SET NULLSQL:
  • SET_DEFAULT: ตั้งค่าเริ่มต้น เทียบเท่า SET DEFAULTSQL:
  • SET(...): ตั้งค่าที่กำหนด อันนี้ไม่ได้เป็นส่วนหนึ่งของมาตรฐาน SQL และจัดการโดย Django ทั้งหมด
  • DO_NOTHING: อาจเป็นความคิดที่แย่มากเนื่องจากสิ่งนี้จะสร้างปัญหาด้านความสมบูรณ์ในฐานข้อมูลของคุณ (อ้างอิงวัตถุที่ไม่มีอยู่จริง) เทียบเท่า NO ACTIONSQL:

ที่มา: เอกสาร Django

ดูเอกสารประกอบของ PostGreSQL ได้เช่นกัน

ในกรณีส่วนใหญ่CASCADEเป็นพฤติกรรมที่คาดหวัง แต่สำหรับชาวต่างชาติทุกคนคุณควรถามตัวเองเสมอว่าอะไรคือพฤติกรรมที่คาดหวังในสถานการณ์นี้ PROTECTและSET_NULLมักจะมีประโยชน์ การตั้งค่าCASCADEที่ไม่ควรสามารถลบฐานข้อมูลทั้งหมดของคุณในแบบเรียงซ้อนได้โดยเพียงแค่ลบผู้ใช้คนเดียว


หมายเหตุเพิ่มเติมเพื่อชี้แจงทิศทางของน้ำตก

เป็นเรื่องตลกที่สังเกตว่าทิศทางของการCASCADEกระทำนั้นไม่ชัดเจนสำหรับหลาย ๆ คน ที่จริงแล้วมันเป็นเรื่องตลกที่จะสังเกตเห็นว่ามีเพียงการCASCADEกระทำที่ไม่ชัดเจน ฉันเข้าใจพฤติกรรมของน้ำตกอาจจะทำให้เกิดความสับสน แต่คุณต้องคิดว่ามันเป็นไปในทิศทางเดียวกับการดำเนินการอื่นดังนั้นหากคุณรู้สึกว่าCASCADEทิศทางนั้นไม่ชัดเจนสำหรับคุณนั่นหมายถึงon_deleteพฤติกรรมนั้นไม่ชัดเจนสำหรับคุณ

ในฐานข้อมูลของคุณคีย์ต่างประเทศจะแสดงโดยทั่วไปด้วยฟิลด์จำนวนเต็มซึ่งค่าเป็นคีย์หลักของวัตถุแปลกปลอม สมมติว่าคุณมีรายการcomment_Aซึ่งมีคีย์ต่างประเทศที่จะเข้าarticle_B หากคุณลบรายการcomment_Aทุกอย่างเรียบร้อยแล้วarticle_Bเคยใช้งานได้โดยปราศจากcomment_Aและไม่ต้องกังวลถ้ามันถูกลบ อย่างไรก็ตามหากคุณลบarticle_Bดังนั้นcomment_A panics! มันไม่เคยมีอยู่หากปราศจากArticle_Bและต้องการมันเป็นส่วนหนึ่งของคุณสมบัติ ( article=article_Bแต่ * Article_B ** ???) คืออะไร นี่คือที่on_deleteขั้นตอนในการกำหนดวิธีการแก้ไขข้อผิดพลาดความสมบูรณ์นี้ทั้งพูดโดย:

  • "ไม่ได้โปรดได้โปรดอย่า! ฉันไม่สามารถอยู่ได้โดยปราศจากคุณ!" (ซึ่งกล่าวPROTECTในภาษา SQL)
  • "เอาล่ะถ้าฉันไม่ใช่ของคุณแล้วฉันก็ไม่มีใคร" (ซึ่งพูดกันว่าSET_NULL)
  • "ลาก่อนลาโลกฉันไม่สามารถอยู่ได้โดยปราศจากบทความ _B"และฆ่าตัวตาย (นี่คือCASCADEพฤติกรรม)
  • "ไม่เป็นไรฉันมีคนรักว่างฉันจะอ้างอิง article_C นับจากนี้" ( SET_DEFAULTหรือแม้กระทั่งSET(...))
  • "ฉันไม่สามารถเผชิญกับความจริงฉันจะเรียกชื่อของคุณต่อไปแม้ว่ามันจะเป็นสิ่งเดียวที่เหลือให้ฉัน! ( DO_NOTHING)

ฉันหวังว่ามันจะทำให้ทิศทางของน้ำตกชัดเจนขึ้น :)


19
คำถามโง่ ๆ แต่การเรียงซ้อนควรเป็นทิศทางเดียวใช่ไหม? คือถ้าComment มีกุญแจต่างประเทศที่จะBlogPostลบ BlogPost ควรลบความคิดเห็น แต่การลบความคิดเห็นไม่ควรลบ BlogPost โดยไม่คำนึงถึง RDMS?
Anthony Manning-Franklin

20
@AnthonyManningFranklin Sure เมื่อลบจะเกิดขึ้นเมื่อการอ้างอิงนั้น "เสีย" เท่านั้น ซึ่งไม่ใช่กรณีเมื่อคุณลบความคิดเห็นตามที่คุณลบการอ้างอิงในเวลาเดียวกัน
แอนทอน Pinsard

6
คำถามไม่ได้โง่ ฉันต้องการคำอธิบายด้วย ดังนั้นที่นี่เราถือว่าความสัมพันธ์เป็นแบบเอกสิทธิ์ด้านข้างเจ้าของความสัมพันธ์คือCommentผู้ที่มีเขตข้อมูล FK ในตารางในขณะที่BlogPost"เป็นเจ้าของ" Commentถ้าเราพูดถึงรูปแบบชีวิตจริง ดี.
WesternGun

3
สิ่งสำคัญที่ควรทราบคือการตั้งค่า on_delete ใน Django ไม่ได้สร้างอนุประโยค ON DELETE ในฐานข้อมูลเอง พฤติกรรมที่ระบุ (เช่นเรียงซ้อน) จะมีผลกับการลบที่ดำเนินการผ่าน Django เท่านั้นและจะไม่ทำการลบดิบโดยตรงในฐานข้อมูล
JoeMjr2

2
คำพูดเหล่านั้นในตอนท้ายดูเหมือนว่าพวกเขาถูกดึงมาจากแผงหนังสือการ์ตูนของ Roy Lichtenstein! น่าทึ่ง
airstrike

42

on_deleteวิธีการที่ใช้ในการบอก Django จะทำอะไรกับอินสแตนซ์รุ่นที่ขึ้นอยู่กับอินสแตนซ์รูปแบบที่คุณลบ (เช่นForeignKeyความสัมพันธ์) The on_delete=models.CASCADEDjango บอกให้ลดเอฟเฟกต์การลบเช่นลบแบบจำลองที่เกี่ยวข้องต่อไปเช่นกัน

นี่เป็นตัวอย่างที่ชัดเจนมากขึ้น สมมติว่าคุณมีAuthorโมเดลที่อยู่ForeignKeyในBookโมเดล ตอนนี้ถ้าคุณลบอินสแตนซ์ของAuthorโมเดล Django จะไม่รู้ว่าจะทำอย่างไรกับอินสแตนซ์ของBookโมเดลที่ขึ้นอยู่กับอินสแตนซ์ของAuthorโมเดลนั้น on_deleteวิธีบอก Django ว่าจะทำอย่างไรในกรณีที่ การตั้งค่าon_delete=models.CASCADEจะสั่งให้ Django ลดทอนลักษณะการลบเช่นลบBookอินสแตนซ์โมเดลทั้งหมดที่ขึ้นอยู่กับAuthorอินสแตนซ์รุ่นที่คุณลบ

หมายเหตุ: on_deleteจะกลายเป็นอาร์กิวเมนต์ที่จำเป็นใน Django 2.0 CASCADEในรุ่นเก่าเป็นค่าเริ่มต้น

นี่คือเอกสารอย่างเป็นทางการทั้งหมด


37

FYI, on_deleteพารามิเตอร์ในแบบจำลองจะย้อนกลับจากที่ฟังดูเหมือน คุณใส่on_deleteForeign Key (FK) ในแบบจำลองเพื่อบอก django ว่าต้องทำอย่างไรถ้ารายการ FK ที่คุณชี้ไปยังบันทึกของคุณถูกลบ ตัวเลือกที่ร้านค้าของเรามีการใช้มากที่สุดคือPROTECT, และCASCADE SET_NULLนี่คือกฎพื้นฐานที่ฉันคิดได้:

  1. ใช้PROTECTเมื่อ FK ของคุณชี้ไปที่ตารางค้นหาที่ไม่ควรเปลี่ยนจริง ๆ และแน่นอนไม่ควรทำให้ตารางของคุณเปลี่ยน หากใครพยายามลบรายการในตารางการค้นหานั้นPROTECTป้องกันไม่ให้ลบออกหากเชื่อมโยงกับบันทึกใด ๆ นอกจากนี้ยังป้องกันไม่ให้ django ลบบันทึกของคุณเพียงเพราะมันลบรายการในตารางการค้นหา ส่วนสุดท้ายนี้มีความสำคัญ หากใครบางคนจะลบเพศ "หญิง" จากตารางเพศของฉันฉันแน่นอนไม่ต้องการที่จะลบทันทีและทุกคนที่ฉันมีในตารางบุคคลของฉันที่มีเพศนั้น
  2. ใช้CASCADEเมื่อ FK ของคุณชี้ไปที่ระเบียน "หลัก" ดังนั้นหากบุคคลสามารถมีหลายรายการ PersonEthnicity (เขา / เธอสามารถเป็นชาวอเมริกันอินเดียน, สีดำและสีขาว) และบุคคลนั้นจะถูกลบฉันอยากจะลบรายการ PersonEthnicity "เด็ก" ใด ๆ พวกเขาไม่เกี่ยวข้องโดยไม่มีบุคคล
  3. ใช้SET_NULLเมื่อคุณไม่ต้องการคนที่จะได้รับอนุญาตให้ลบรายการบนโต๊ะมองขึ้น แต่คุณยังคงต้องการที่จะเก็บรักษาบันทึกของคุณ ตัวอย่างเช่นถ้าเป็นคนที่สามารถมีมัธยมศึกษา on_delete=SET_NULLแต่มันไม่ได้เรื่องจริงๆกับผมว่าที่โรงเรียนมัธยมออกไปบนโต๊ะมองขึ้นของฉันฉันจะบอกว่า นี่จะทำให้คนของฉันบันทึกที่นั่น มันแค่ตั้งค่า FK ของโรงเรียนมัธยมให้กับบุคคลของฉันเป็นโมฆะ เห็นได้ชัดว่าคุณจะต้องให้null=TrueFK นั้น

นี่คือตัวอย่างของโมเดลที่ทำทั้งสามอย่าง:

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จึงเหมือนกับการไม่ใส่อะไรเลย


12

ดังกล่าวก่อนหน้าเรียงซ้อนจะลบระเบียนที่มีคีย์ต่างประเทศและการอ้างอิงวัตถุอื่นที่ถูกลบ ตัวอย่างเช่นหากคุณมีเว็บไซต์อสังหาริมทรัพย์และมีอสังหาริมทรัพย์ที่อ้างอิงถึงเมือง

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บันทึกเหล่านั้น

ประเด็นของฉันคือถ้ามีฟังก์ชั่นการใช้งานจะมีเหตุผลอยู่เบื้องหลังเสมอ ไม่ใช่เหตุผลที่ดีเสมอไป แต่มีเหตุผล และบ่อยครั้งก็เป็นสิ่งที่ดีเช่นกัน


3
สิ่งนี้มีประโยชน์เพราะมันชัดเจนในทิศทางที่เรียงซ้อนเกิดขึ้น คำตอบที่ได้รับการยอมรับไม่ชัดเจนถ้าคุณไม่คุ้นเคยกับการเรียงซ้อนของ SQL
codescribblr

ขอบคุณ :) ชื่นชมมาก!
George Mogilevsky

2
ฉันโหวตคำตอบนี้เพราะมันตอบข้อสงสัยของฉันเกี่ยวกับทิศทางในรูปแบบความสัมพันธ์
edepe

6

นี่คือคำตอบสำหรับคำถามของคุณที่แจ้งว่า: ทำไมเราถึงใช้ on_delete

เมื่อวัตถุที่อ้างอิงโดย ForeignKey ถูกลบ Django โดยค่าเริ่มต้นจะเลียนแบบพฤติกรรมของข้อ จำกัด SQL บน DELETE CASCADE และยังลบวัตถุที่มี ForeignKey พฤติกรรมนี้สามารถถูกแทนที่โดยการระบุอาร์กิวเมนต์ on_delete ตัวอย่างเช่นถ้าคุณมี ForeignKey ที่สามารถลบล้างได้และคุณต้องการให้มันเป็นค่าว่างเมื่อวัตถุที่อ้างอิงถูกลบ:

user = models.ForeignKey(User, blank=True, null=True, on_delete=models.SET_NULL)

ค่าที่เป็นไปได้สำหรับ on_delete พบได้ใน django.db.models:

เรียงซ้อน:ลบเรียงซ้อน ; ค่าเริ่มต้น

PROTECT:ป้องกันการลบวัตถุอ้างอิงโดยการเพิ่ม ProtectedError ซึ่งเป็นคลาสย่อยของ django.db.IntegrityError

SET_NULL:ตั้งค่า ForeignKey null; สิ่งนี้เป็นไปได้ก็ต่อเมื่อ null เป็น True

SET_DEFAULT:ตั้งค่า ForeignKey เป็นค่าเริ่มต้น ต้องตั้งค่าเริ่มต้นสำหรับ ForeignKey


คำง่าย ๆ ทำให้ชัดเจนสำหรับฉันเพราะฉันไม่ได้เป็นผู้ใหญ่ด้วย sql และ django เช่นกัน ขอบคุณ.
wm.p1us

3

สมมติว่าคุณมีสองรุ่นหนึ่งชื่อคนและอีกคนหนึ่งชื่อบริษัท

ตามคำนิยามบุคคลหนึ่งสามารถสร้างมากกว่าหนึ่ง บริษัท

การพิจารณา บริษัท สามารถมีได้เพียงหนึ่งคนและเพียงคนเดียวเท่านั้นที่เราต้องการเมื่อบุคคลนั้นถูกลบ บริษัท ทั้งหมดที่เกี่ยวข้องกับบุคคลนั้นจะถูกลบด้วย

ดังนั้นเราเริ่มต้นด้วยการสร้างแบบจำลองบุคคลเช่นนี้

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) ถูกลบ


1

ปรับโมเดลจิตของคุณเกี่ยวกับฟังก์ชั่น "CASCADE" อีกครั้งโดยคิดถึงการเพิ่ม FK ไปยังน้ำตกที่มีอยู่แล้ว (เช่นน้ำตก) แหล่งที่มาของน้ำตกนี้เป็นคีย์หลัก ลบการไหลลง

ดังนั้นถ้าคุณกำหนด on_delete ของ FK เป็น "เรียงซ้อน" คุณกำลังเพิ่มระเบียนของ FK นี้ลงในน้ำตกที่มีการลบซึ่งมีต้นกำเนิดมาจาก PK บันทึกของ FK อาจมีส่วนร่วมในน้ำตกนี้หรือไม่ ("SET_NULL") ในความเป็นจริงบันทึกที่มี FK อาจป้องกันการไหลของการลบ! สร้างเขื่อนด้วย "PROTECT"


0

การใช้เรียงซ้อนหมายถึงจริงบอก Django เพื่อลบบันทึกอ้างอิง ในตัวอย่างแอพโพลด้านล่าง: เมื่อ 'คำถาม' ถูกลบมันจะลบตัวเลือกคำถามนี้ด้วย

เช่นคำถาม: คุณรู้จักเราได้อย่างไร? (ตัวเลือก: 1. เพื่อน 2. โฆษณาทางทีวี 3. เครื่องมือค้นหา 4. อีเมลโปรโมชั่น)

เมื่อคุณลบคำถามนี้คำถามนี้จะลบตัวเลือกทั้งสี่เหล่านี้ออกจากตาราง โปรดทราบว่าทิศทางนั้นไหล คุณไม่ต้องใส่ on_delete = แบบจำลอง CASCADE ในแบบจำลองคำถามวางไว้ในตัวเลือก

from django.db import models



class Question(models.Model):
    question_text = models.CharField(max_length=200)
    pub_date = models.dateTimeField('date_published')

class Choice(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    choice_text = models.CharField(max_legth=200)
    votes = models.IntegerField(default=0)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.