Почему Django дает мне эту ошибку "нарушает ненулевое ограничение"? - PullRequest
3 голосов
/ 11 июня 2011

Ошибка:

Нулевое значение в столбце "postal_code_id" нарушает ненулевое ограничение

Форма:

def add(request):
    if request.method == 'POST':
        address_form = AddressForm(request.POST)
        company_form = CompanyForm(request.POST)
        if address_form.is_valid() and company_form.is_valid():
            print address_form.cleaned_data['postal_code'] # <-- prints (<PostalCode: V4N 1K6>, False)
            address_form.save() # <------------------------------- occurs here
        else:
            print 'Address errors',address_form.errors
            print 'Company errors', company_form.errors
    else:
        address_form = AddressForm()
        company_form = CompanyForm()
    return render(request, 'company/add.html', locals())

Очевидно, что форма имеет действительный объект PostalCode, поэтому я не уверен, почему он говорит, что он нарушает ограничение not-null. Конечно, я делаю что-то смешное с формой:

class AddressForm(ModelForm):
    postal_code = CharField(max_length=10, validators=[validate_postal_code])
    city = CharField(max_length=50, validators=[validate_non_whitespace])
    province = CharField(max_length=50, validators=[validate_non_whitespace])
    country = CharField(max_length=50, initial='Canada', validators=[validate_non_whitespace])

    def clean_postal_code(self):
        code = self.cleaned_data['postal_code']
        code = code.upper()
        code = re.sub('[^A-Z0-9]', '', code)
        code = code[:3] + ' ' + code[-3:]
        return code

    def clean_country(self):
        country = self.cleaned_data['country']

        try:
            country = Country.objects.get(name__iexact=country)
        except Country.DoesNotExist:
            raise ValidationError('Country does not exist')

        return country

    def clean_province(self):
        province = self.cleaned_data['province']

        if not Province.objects.filter(name__iexact=province).exists():
            raise ValidationError('Province does not exist')

        return province

    def clean(self):
        data = self.cleaned_data

        if 'country' in data and 'province' in data:
            try:
                data['province'] = Province.objects.get(country=data['country'], name__iexact=data['province'])
                if 'city' in data:
                    data['city'] = City.objects.get_or_create(name__iexact=data['city'], province=data['province'], defaults={'name':data['city']})[0]
                    if 'postal_code' in data:
                        data['postal_code'] = PostalCode.objects.get_or_create(code=data['postal_code'], city=data['city'])
            except Province.DoesNotExist:
                self._errors['province'] = self.error_class(['Province does not exist in that Country'])
                del data['province']

        return data

    class Meta:
        exclude = ['postal_code']
        model = Address

В частности, я заменяю поле postal_code текстовым полем, а затем нахожу / создаю объект «чистым» методом. Почему это смущает Джанго? В конце концов, он получает объект, который ему нужен, не так ли?

Ответы [ 4 ]

2 голосов
/ 11 июня 2011

Вы исключаете postal_code, что заставит форму модели пропустить поле позже во время попытки сохранения.У меня была похожая проблема, и мне пришлось проследить через код django, чтобы выяснить поведение.Кстати, это стоит сделать.

Вместо этого вы должны установить виджет, используемый для поля postal_code, а не исключать, а затем включать.проверьте правильность поля и сохраните его.Я исключил остальную часть вашей формы для краткости.

Редактировать:

Попытка использовать CharField для ForeignKey чревата ужасными в ModelForm.Вместо этого преобразуйте его в обычную форму.Похоже, вы уже определяете большинство своих полей.Затем вы можете проверить, что поля действительны и уже являются членами базы данных.Создайте метод сохранения, который будет вести себя как метод сохранения ModelForm, и все - и все.

1 голос
/ 13 февраля 2012

Я пришел к этому вопросу, потому что пытался автоматически добавить поле uploaded_by для формирования данных перед сохранением формы.Я использовал ModelForm, за исключением uploaded_by.Я обнаружил, что ответ на вопрос , связанный с *1004*, был кратким решением этой проблемы.

1 голос
/ 11 июня 2011

Я не знаю Django, но, возможно, вам нужно убедиться, что почтовый индекс сохранен, прежде чем пытаться сохранить адрес?

0 голосов
/ 18 апреля 2017

Я пришел к этому вопросу, так как получал эту ошибку IntegrityError, когда я пытался отправить экземпляр ModelForm, который имел CharField с blank=True (да, null=True никогда не должен использоваться с CharField). Проблема была в самой форме: метод clean_field() соответствующего поля сначала проверял наличие значения поля, но если значение не существовало, он возвращал None, именно поэтому ограничение not-null было нарушено. Исправление метода, возвращающего тот же cleaned_data['field'], который был проверен для значения, решило проблему.

...