ฉันมีโมเดล Foo ที่มีแถบฟิลด์ ฟิลด์แถบควรไม่ซ้ำกัน แต่อนุญาตให้มีค่าว่างในนั้นหมายความว่าฉันต้องการอนุญาตมากกว่าหนึ่งระเบียนหากฟิลด์บาร์เป็นnull
แต่ถ้าไม่ใช่null
ค่าจะต้องไม่ซ้ำกัน
นี่คือโมเดลของฉัน:
class Foo(models.Model):
name = models.CharField(max_length=40)
bar = models.CharField(max_length=40, unique=True, blank=True, null=True, default=None)
และนี่คือ SQL ที่สอดคล้องกันสำหรับตาราง:
CREATE TABLE appl_foo
(
id serial NOT NULL,
"name" character varying(40) NOT NULL,
bar character varying(40),
CONSTRAINT appl_foo_pkey PRIMARY KEY (id),
CONSTRAINT appl_foo_bar_key UNIQUE (bar)
)
เมื่อใช้อินเทอร์เฟซผู้ดูแลระบบเพื่อสร้างออบเจ็กต์ foo มากกว่า 1 ชิ้นโดยที่ bar เป็นค่าว่างมันทำให้ฉันมีข้อผิดพลาด: "Foo with this Bar มีอยู่แล้ว"
อย่างไรก็ตามเมื่อฉันแทรกลงในฐานข้อมูล (PostgreSQL):
insert into appl_foo ("name", bar) values ('test1', null)
insert into appl_foo ("name", bar) values ('test2', null)
มันใช้งานได้ดีมันช่วยให้ฉันสามารถแทรกมากกว่า 1 เรคคอร์ดโดยที่บาร์เป็นโมฆะดังนั้นฐานข้อมูลจึงอนุญาตให้ฉันทำในสิ่งที่ฉันต้องการมันมีบางอย่างผิดปกติกับโมเดล Django ความคิดใด ๆ ?
แก้ไข
ความสามารถในการพกพาของโซลูชันตราบเท่าที่ DB ไม่ใช่ปัญหาเราพอใจกับ Postgres ฉันได้ลองตั้งค่าเฉพาะให้กับ callable ซึ่งเป็นฟังก์ชันของฉันที่คืนค่า True / False สำหรับค่าเฉพาะของbarแต่ก็ไม่ได้ให้ข้อผิดพลาดใด ๆ แต่ดูเหมือนว่าจะไม่มีผลเลย
จนถึงตอนนี้ฉันได้ลบตัวระบุที่ไม่ซ้ำกันออกจากคุณสมบัติบาร์และจัดการความเป็นเอกลักษณ์ของบาร์ในแอปพลิเคชัน แต่ก็ยังคงมองหาโซลูชันที่หรูหรากว่านี้ ข้อเสนอแนะใด ๆ
def get_db_prep_value(self, value, connection, prepared=False)
ใช้วิธีการโทร ตรวจสอบgroups.google.com/d/msg/django-users/Z_AXgg2GCqs/zKEsfu33OZMJสำหรับข้อมูลเพิ่มเติม วิธีการต่อไปนี้ใช้ได้ผลกับฉันเช่นกัน: def get_prep_value (self, value): if value == "": #if Django พยายามบันทึกสตริง '' ส่ง db None (NULL) ส่งคืน None else: return value # ไม่เช่นนั้น ผ่านค่า