Django Form.is_valid()が常にFalseとなる。
Q&A
アプリケーションの構成
/LedgerEmployee/
/LedgerStation/
施設(Station)、看護師(Employee)のモデルがあり、看護師は複数の施設に所属するため、施設とは多対多の関係にあります(ManyToManyField: belong_to)。
【症状】
看護師の新規登録フォームのPOST時に、バリデーションが常にFalseとなる。
【補足】
看護師の新規登録フォームは、belong_to設置前までは正常に登録できていた(True)ため、おそらく多対多に関わるミスではないかと考えています。
(設置後でも/adminページでは正しく登録できましたが、他の人には/adminに入れさせたくない)
当方、非IT業種のため、コードが読みづらいと思います。
長々してしまうため、関係がありそうなファイルのみ載せてみました。
ご助言お願いします。
/LedgerEmployee/models.py
from django.db import models
# Create your models here.
from django.conf import settings
from LedgerStation.models import Station # 施設台帳
class Employee(models.Model):
name_kanji = models.CharField('氏名(漢字)', max_length=20)
name_kana = models.CharField('氏名(かな)', max_length=20)
tel1 = models.CharField('電話番号1', max_length=13)
tel2 = models.CharField('電話番号2', max_length=13, default='', blank=True)
postal_code = models.CharField('郵便番号', max_length=8, default='', blank=True)
address = models.TextField('住所', default='', blank=True)
email = models.CharField('email', max_length=30, default='', blank=True)
nurse_licence_type = models.CharField('看護師免許種別', max_length=4, \
choices=settings.NURSE_LICENCE_TYPE, default='なし')
nurse_licence_num = models.CharField('看護師免許番号', max_length=10, default='', blank=True)
nurse_licence_date = models.CharField('看護師免許取得日', max_length=10, default='', blank=True)
belong_to = models.ManyToManyField(Station, verbose_name='所属', blank=True) # 施設台帳とのリレーション。
memo = models.TextField('メモ', default='', blank=True) # TextField … 制限なし
created_at = models.DateTimeField('登録日時', auto_now_add=True, editable=True)
created_by = models.CharField('登録者', max_length=20, default='', blank=True)
updated_at = models.DateTimeField('更新日時', auto_now=True, editable=True)
updated_by = models.CharField('最終編集者', max_length=20, default='', blank=True)
class Meta:
db_table = 'T_Employees'
def __str__(self):
return f'{self.pk}{self.name_kanji}'
/LedgerEmployee/views.py
def le_new(request): # データ登録用のview
form = EmployeeForm(request.POST)
if form.is_valid(): # False のため、そもそもこの分岐には入らない。
employee = form.save(commit=False)
employee.created_by = str(request.user.last_name) + ' ' + str(request.user.first_name) # 管理画面より参照。
employee.save()
return redirect(le_detail, employee_id=employee.pk)
else: # GET時とバリデーションFalse時にデータ登録画面のFormを表示するため、POSTしても全てここを辿る。
context = {'form': form, 'navigation': '社員台帳: 新規登録'}
return render(request, 'LedgerEmployee/le_new.html', context)
/LedgerEmployee/forms.py
from django import forms
from LedgerEmployee.models import Employee
class EmployeeForm(forms.ModelForm):
class Meta:
model = Employee
# fields = ['name_kanji', 'name_kana', 'tel1', 'tel2', 'postal_code', 'address', 'email', 'nurse_licence_type', 'nurse_licence_type', 'nurse_licence_num', 'nurse_licence_date', 'belong_to', 'memo',]
fields = '__all__'
exclude = ('belong_to', 'created_at', 'created_by', 'updated_at', 'updated_by', ) # 除外フィールド最後にカンマ。
/templates/LedgerEmployee/le_new.html
{% extends 'base.html' %}
{% block main %}
<form method='post mt-1'>
{% csrf_token %}
{{ form.as_p }}
<button class='btn btn-primary' type='submit'>登録</button>
<a class='btn btn-primary' href='{% url "le_top" %}'>戻る</a>
</form>
{% endblock %}
/LedgerStation/models.py
from django.db import models
# Create your models here.
from django.conf import settings
class Station(models.Model):
name_kanji = models.CharField('施設名(漢字)', max_length=50, default='')
name_kana = models.CharField('施設名(かな)', max_length=50, default='')
postal_code = models.CharField('郵便番号', max_length=8)
address = models.TextField('住所')
tel1 = models.CharField('電話番号1', max_length=13)
tel2 = models.CharField('電話番号2', max_length=13, blank=True, default='')
fax = models.CharField('Fax番号', max_length=13, blank=True, default='')
memo = models.TextField('メモ', default='', blank=True)
created_at = models.DateTimeField('登録日時', auto_now_add=True, editable=True)
created_by = models.CharField('登録者', max_length=20, default='', blank=True)
updated_at = models.DateTimeField('更新日時', auto_now=True, editable=True)
updated_by = models.CharField('最終編集者', max_length=20, default='', blank=True)
class Meta:
db_table = 'T_Stations'
def __str__(self):
return self.name_kanji
Log的なアレ
(0.004) SELECT "django_session"."session_key", "django_session"."session_data", "django_session"."expire_date" FROM "django_session" WHERE ("django_session"."expire_date" > '2021-10-08 13:54:47.332823' AND "django_session"."session_key" = 'guvgg58fs7b57ai9yik9t9moswbrldp9') LIMIT 21; args=('2021-10-08 13:54:47.332823', 'guvgg58fs7b57ai9yik9t9moswbrldp9')
(0.001) SELECT "auth_user"."id", "auth_user"."password", "auth_user"."last_login", "auth_user"."is_superuser", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."date_joined" FROM "auth_user" WHERE "auth_user"."id" = 1 LIMIT 21; args=(1,)
[08/Oct/2021 22:43:34] "GET /LedgerEmployee/new/?csrfmiddlewaretoken=I7fFEpDGYJ9c8fJl6Z5ezk2lGqWNCvSss0eJm4wEHjWkQDuw2pjjwAPpLPQufrKI&name_kanji=test1&name_kana=test2&tel1=test&tel2=&postal_code=&address=&email=&nurse_licence_type=%E3%81%AA%E3%81%97&nurse_licence_num=&nurse_licence_date=&memo= HTTP/1.1" 200 3733
0 likes