Tengo el modelo Foo que tiene barra de campo. El campo de la barra debe ser único, pero permitir nulos en él, lo que significa que quiero permitir más de un registro si el campo de la barra es null
, pero si no lo es, null
los valores deben ser únicos.
Aquí está mi modelo:
class Foo(models.Model):
name = models.CharField(max_length=40)
bar = models.CharField(max_length=40, unique=True, blank=True, null=True, default=None)
Y aquí está el SQL correspondiente para la tabla:
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)
)
Cuando uso la interfaz de administrador para crear más de 1 objetos foo donde la barra es nula, me da un error: "Foo con esta barra ya existe".
Sin embargo, cuando inserto en la base de datos (PostgreSQL):
insert into appl_foo ("name", bar) values ('test1', null)
insert into appl_foo ("name", bar) values ('test2', null)
Esto funciona, está bien, me permite insertar más de 1 registro con la barra nula, por lo que la base de datos me permite hacer lo que quiero, es simplemente algo mal con el modelo Django. ¿Algunas ideas?
EDITAR
La portabilidad de la solución en lo que respecta a DB no es un problema, estamos contentos con Postgres. Intenté establecer un valor único para un invocable, que era mi función que devolvía Verdadero / Falso para valores específicos de barra , no daba ningún error, sin embargo, parecía que no tenía ningún efecto.
Hasta ahora, eliminé el especificador único de la propiedad de la barra y manejé la singularidad de la barra en la aplicación, sin embargo, todavía busco una solución más elegante. ¿Alguna recomendación?
def get_db_prep_value(self, value, connection, prepared=False)
como método de llamada. Visite groups.google.com/d/msg/django-users/Z_AXgg2GCqs/zKEsfu33OZMJ para obtener más información. El siguiente método también funciona para mí: def get_prep_value (self, value): if value == "": #si Django intenta guardar la cadena '', envíe el db None (NULL) return Ninguno más: valor de retorno #otherwise, solo pasar el valor