Wenn Sie einem nicht wesentlichen CharField eine eindeutige Einschränkung hinzufügen, tritt ein DuplicateError auf. Ich war ein wenig süchtig danach, ein Feld zu erstellen, das Null anstelle von leeren Zeichen speichert, wenn keine Eingabe erfolgt, also schrieb ich ein Memo.
Wenn in Django CharField und TextField als leer gespeichert werden, werden sie als leere Zeichen anstelle von Null gespeichert. Wenn IntegerField usw. leer ist, wird Null ordnungsgemäß gespeichert. Wenn Sie also die Quelle von Django überprüfen, was Sie tun Ich habe die folgende Methode in der IntegerField-Klasse gefunden.
def get_prep_value(self, value):
value = super(IntegerField, self).get_prep_value(value)
if value is None:
return None
return int(value)
Dies ist wie eine Methode, die den Wert vor dem Speichern der Datenbank konvertiert. Wenn Sie also None zurückgeben, wenn das Zeichen leer ist, wird Null gespeichert.
class NullCharField(models.CharField):
def get_preg_value(self, value):
value = Super(NullCharField, self).get_preg_value(value)
return value if value else None
Dies speichert vorerst Null, wenn keine Eingabe in Form usw. erfolgt.
Wenn Sie den Administratorbildschirm in diesem Status öffnen, tritt TypeError auf.
Exception Value: coercing to Unicode: need string or buffer, NoneType found
Da gesagt wird, dass "Zeichenfolge oder Puffer übergeben", wenn es "Keine" ist, scheint die Verarbeitung zum Konvertieren in leere Zeichen erforderlich zu sein.
Ich dachte, ich sollte die to_string-Methode neu schreiben, aber es funktioniert nicht. Es scheint notwendig zu sein, django.db.models.SubfieldBase nach verschiedenen Untersuchungen an die Metaklasse zu übergeben. Der von der Datenbank erhaltene Wert wird von setattr eingegeben (siehe die Init-Methode der Modellklasse von django.db.models.base). Wenn Sie SubfieldBase an die Meta-Klasse übergeben, wird die to_python-Methode intern bei setattr aufgerufen.
Aus diesem Grund habe ich Meta angegeben und die Verarbeitung zum Zeitpunkt der Erfassung hinzugefügt.
from django.db import models
from django.utils import six
class NullCharField(six.with_metaclass(models.SubfieldBase, models.CharField)):
def get_preg_value(self, value):
value = super(NullCharField, self).get_preg_value(value)
return value if value else None
def to_python(self, value):
value = super(NullCharField, self).to_python(value)
return value if value is not None else u''
Ich dachte, es könnte etwas sein, und als ich es nachschlug, war es bei Oscar normal. https://github.com/django-oscar/django-oscar/blob/master/src/oscar/models/fields/init.py
class NullCharField(six.with_metaclass(SubfieldBase, CharField)):
"""
CharField that stores '' as None and returns None as ''
Useful when using unique=True and forms. Implies null==blank==True.
When a ModelForm with a CharField with null=True gets saved, the field will
be set to '': https://code.djangoproject.com/ticket/9590
This breaks usage with unique=True, as '' is considered equal to another
field set to ''.
"""
description = "CharField that stores '' as None and returns None as ''"
def __init__(self, *args, **kwargs):
if not kwargs.get('null', True) or not kwargs.get('blank', True):
raise ImproperlyConfigured(
"NullCharField implies null==blank==True")
kwargs['null'] = kwargs['blank'] = True
super(NullCharField, self).__init__(*args, **kwargs)
def to_python(self, value):
val = super(NullCharField, self).to_python(value)
return val if val is not None else u''
def get_prep_value(self, value):
prepped = super(NullCharField, self).get_prep_value(value)
return prepped if prepped != u"" else None
def deconstruct(self):
"""
deconstruct() is needed by Django's migration framework
"""
name, path, args, kwargs = super(NullCharField, self).deconstruct()
del kwargs['null']
del kwargs['blank']
return name, path, args, kwargs
Es war fast da. Ich habe die Null- und Leerzeichen mit init überprüft. Außerdem scheint es für die Migration notwendig zu sein, das Überschreiben zu dekonstruieren.
Recommended Posts