1. ホーム
  2. python

[解決済み] DjangoにおけるIntegrityError

2022-02-15 16:54:31

質問

あるフォームにMany2Manyフィールドを追加したところ、送信時にIntegrityErrorが発生しました。正確なエラーテキストは以下の通りです。

IntegrityError at /add_person/ hireterm_person.mail_lists may not be NULL

新しいフィールドを追加するまでは問題なく動作していました。デバッグ変更でPOSTデータを見ると、パスされているので、どこでブレイクしているのかがわかりません。

モデル

from django.db import models
from django.forms import ModelForm
from django import forms
from django.contrib.auth.models import User

class Mailists(models.Model):
    name = models.CharField(blank=True, max_length=100)
    email = models.CharField(blank=True, max_length=100)

    def __unicode__(self):
        return u'%s' % (self.name)

class Person(models.Model):
    ROLE_CHOICES = (
        ('Mrkt', 'Marketing'),
        ('Fin/Off', 'Finance / Office'),
        ('Care', 'Care'),
        ('Sales', 'Sales'),
        )
    ROLE_TYPE = (
        ('Full', 'Full Time'),
        ('Part', 'Part Time'), 
        ('Intern', 'Intern'),
        )

    first_name = models.CharField(blank=True, max_length=100)
    last_name = models.CharField(blank=True, max_length=100)
    date_added = models.DateField(auto_now_add=True)
    date_start = models.DateField(auto_now=False)
    role = models.CharField(max_length=100, default = "", choices = ROLE_CHOICES)
    manager = models.ForeignKey('self', limit_choices_to = {'is_manager': True}, null=True, blank=True)
    title = models.CharField(blank=True, max_length=100)
    role_type = models.CharField(max_length=100, default = "", choices = ROLE_TYPE)
    laptop_needed = models.BooleanField(default=True)
    phone_needed = models.BooleanField(default=True)
    desk_loco = models.CharField(blank=True, max_length=100)
    mail_lists = models.ManyToManyField(Mailists, blank=True)
    notes = models.CharField(blank=True, max_length=500)
    is_manager = models.BooleanField(default=False)
    is_active = models.BooleanField(default=True)

    def __unicode__(self):
        return u'%s %s' % (self.first_name, self.last_name)

class PersonForm(ModelForm):
    mail_lists = forms.ModelMultipleChoiceField(queryset=Mailists.objects.all(), widget=forms.CheckboxSelectMultiple(), required=False)
    class Meta:
        model = Person

EDIT

mail_lists = request.POST.getlist('mail_lists') を追加しました。これにprintを追加すると、返されるリストはすべてのチェックボックスで、POSTデータは最後のチェックボックスという単一の文字列のままになっています。

表示

from hireterm.models import Person, Mailists, PersonForm
from django.shortcuts import get_object_or_404, render
from django.template import Context, loader
from django.http import HttpResponseRedirect, HttpResponse
from django.contrib.auth.decorators import login_required
from django.contrib.auth import authenticate, login
from django.contrib.auth import logout
from django.core.mail import send_mail

@login_required
def home(request):
    return render(request, 'hireterm/home.html')

def add_person(request):
    if request.method == 'POST':
        mail_lists = request.POST.getlist('mail_lists') 
        person_form = PersonForm(request.POST)
        if person_form.is_valid(): 
            person_form.save()
            return HttpResponseRedirect('/new_hire') # Redirect after POST

    else:
        person_form = PersonForm() # An unbound form

    return render(request, 'hireterm/additem.html', {
        'form': person_form,
    })

解決方法は?

あなたのフィールドで。

mail_lists = models.ManyToManyField(Mailists, blank=True)

を追加しました。 blank=True はフィールドに追加されますが null=True . これは、DBがそのフィールドに値があることを期待していることを意味します。そのため、値がない場合はエラーになります。

ヌル

True の場合、Django は空の値を NULL としてデータベースに保存します。デフォルトは False です。 空文字列の値は NULL ではなく、常に空文字列として格納されることに注意し て下さい。null=True は整数、ブーリアン、日付のような文字列でないフィールドにだけ使 って下さい。いずれのタイプのフィールドでも、フォームで空の値を許可したい場合は、blank=Trueを設定する必要があります。

ブランク

Trueの場合、フィールドを空白にすることが許可されます。デフォルトはFalseです。

nullは純粋にデータベースに関連するものであるのに対し、blankはバリデーションに関連するものであることに注意してください。フィールドがblank=Trueの場合、フォームバリデーションは空の値の入力を許可します。フィールドがblank=Falseの場合、そのフィールドは必須となります。

その他にも、こんな説明があります。