Let's say I've the following models:
from django.db import models
class TenantModelBase(models.Model):
tenant = models.ForeignKey(to='accounts.TenantModel', on_delete=models.CASCADE)
class Meta:
abstract = True
class ModelFacade(models.Model):
class Meta:
abstract = True
@entry_exit
def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
return super().save(force_insert=force_insert, force_update=force_update, using=using, update_fields=update_fields)
@entry_exit
def get(self, *args, **kwargs):
return super().objects.get(*args, **kwargs)
@entry_exit
def all(self):
return super().objects.all()
class LocationModel(TenantModelBase, ModelFacade):
city = models.CharField()
country = models.CharField()
building = models.CharField(blank=True)
department = models.CharField(blank=True)
contact_name = models.CharField(blank=True)
email_address = models.EmailField(blank=True)
phone_number = models.CharField(blank=True)
class Meta(TenantModelBase.Meta):
db_table = 'oam_locations'
ordering = ['city']
The field "foo" should not be shown in the create form. Therefore the form is:
from django.forms import ModelForm
class LocationCreateForm(ModelForm):
class Meta:
model = LocationModel
fields = ('city', 'country', 'building', 'department', 'contact_name', 'email_address', 'phone_number')
The field is NOT shown in the form. Excellent!
Now when POSTing the form, a middleware adds the 'TenantModelBase.tenant' field to the POST vars. The middleware looks like this:
def __call__(self, request):
if request.method == 'POST' and request.path not in ['/admin/login/']:
user_profile = UserProfileModel.objects.get(user_id=request.user.id)
_mutable = request.POST._mutable
request.POST._mutable = True
request.POST['tenant'] = str(user_profile.last_tenant_id)
request.POST._mutable = _mutable
But when saving I get an "NOT NULL constraint failed: oam_locations.tenant_id" error. There seems to be some magic code aligning the POST vars (with "tenant" added by the middleware) to the form "fields" (w/o "tenant").
The stacktrace looks like this:
Environment:
Request Method: POST
Request URL: http://127.0.0.1:8000/oam/location/create
Django Version: 3.2.16
Python Version: 3.10.9
Installed Applications:
['django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.admindocs',
'bootstrap5',
'easyaudit',
'main.apps.MainConfig',
'accounts.apps.AccountsConfig',
'oam.apps.OamConfig']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.contrib.admindocs.middleware.XViewMiddleware',
'easyaudit.middleware.easyaudit.EasyAuditMiddleware',
'accounts.middleware.tenant_middleware.TenantMiddleware']
Traceback (most recent call last):
File "C:\work\pro\vending\apollo\venv\lib\site-packages\django\db\backends\utils.py", line 84, in _execute
return self.cursor.execute(sql, params)
File "C:\work\pro\vending\apollo\venv\lib\site-packages\django\db\backends\sqlite3\base.py", line 423, in execute
return Database.Cursor.execute(self, query, params)
The above exception (NOT NULL constraint failed: oam_locations.tenant_id) was the direct cause of the following exception:
File "C:\work\pro\vending\apollo\venv\lib\site-packages\django\core\handlers\exception.py", line 47, in inner
response = get_response(request)
File "C:\work\pro\vending\apollo\venv\lib\site-packages\django\core\handlers\base.py", line 181, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\work\pro\vending\apollo\venv\lib\site-packages\django\views\generic\base.py", line 70, in view
return self.dispatch(request, *args, **kwargs)
File "C:\work\pro\vending\apollo\venv\lib\site-packages\django\contrib\auth\mixins.py", line 71, in dispatch
return super().dispatch(request, *args, **kwargs)
File "C:\work\pro\vending\apollo\venv\lib\site-packages\django\views\generic\base.py", line 98, in dispatch
return handler(request, *args, **kwargs)
File "C:\work\pro\vending\apollo\venv\lib\site-packages\django\views\generic\edit.py", line 172, in post
return super().post(request, *args, **kwargs)
File "C:\work\pro\vending\apollo\venv\lib\site-packages\django\views\generic\edit.py", line 142, in post
return self.form_valid(form)
File "C:\work\pro\vending\apollo\venv\lib\site-packages\django\views\generic\edit.py", line 125, in form_valid
self.object = form.save()
File "C:\work\pro\vending\apollo\venv\lib\site-packages\django\forms\models.py", line 468, in save
self.instance.save()
File "C:\work\pro\vending\apollo\main\utils\decorators.py", line 22, in wrapper
result = func(*args, **kwargs)
File "C:\work\pro\vending\apollo\main\models\model_facade.py", line 15, in save
return super().save(force_insert=force_insert, force_update=force_update, using=using, update_fields=update_fields)
File "C:\work\pro\vending\apollo\venv\lib\site-packages\django\db\models\base.py", line 739, in save
self.save_base(using=using, force_insert=force_insert,
File "C:\work\pro\vending\apollo\venv\lib\site-packages\django\db\models\base.py", line 776, in save_base
updated = self._save_table(
File "C:\work\pro\vending\apollo\venv\lib\site-packages\django\db\models\base.py", line 881, in _save_table
results = self._do_insert(cls._base_manager, using, fields, returning_fields, raw)
File "C:\work\pro\vending\apollo\venv\lib\site-packages\django\db\models\base.py", line 919, in _do_insert
return manager._insert(
File "C:\work\pro\vending\apollo\venv\lib\site-packages\django\db\models\manager.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "C:\work\pro\vending\apollo\venv\lib\site-packages\django\db\models\query.py", line 1270, in _insert
return query.get_compiler(using=using).execute_sql(returning_fields)
File "C:\work\pro\vending\apollo\venv\lib\site-packages\django\db\models\sql\compiler.py", line 1416, in execute_sql
cursor.execute(sql, params)
File "C:\work\pro\vending\apollo\venv\lib\site-packages\django\db\backends\utils.py", line 98, in execute
return super().execute(sql, params)
File "C:\work\pro\vending\apollo\venv\lib\site-packages\django\db\backends\utils.py", line 66, in execute
return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
File "C:\work\pro\vending\apollo\venv\lib\site-packages\django\db\backends\utils.py", line 75, in _execute_with_wrappers
return executor(sql, params, many, context)
File "C:\work\pro\vending\apollo\venv\lib\site-packages\django\db\backends\utils.py", line 79, in _execute
with self.db.wrap_database_errors:
File "C:\work\pro\vending\apollo\venv\lib\site-packages\django\db\utils.py", line 90, in __exit__
raise dj_exc_value.with_traceback(traceback) from exc_value
File "C:\work\pro\vending\apollo\venv\lib\site-packages\django\db\backends\utils.py", line 84, in _execute
return self.cursor.execute(sql, params)
File "C:\work\pro\vending\apollo\venv\lib\site-packages\django\db\backends\sqlite3\base.py", line 423, in execute
return Database.Cursor.execute(self, query, params)
Exception Type: IntegrityError at /oam/location/create
Exception Value: NOT NULL constraint failed: oam_locations.tenant_id
Any idea how to solve this?
CodePudding user response:
I think you need to add Meta
class in Modelform
models.py
from django.db import models
class MyModel(models.Model):
foo = models.CharField(max_length=120)
bar = models.CharField(max_length=120)
form.py
from django.forms import ModelForm
class MyForm(ModelForm):
class Meta:
model = MyModel
fields = ('bar',)
CodePudding user response:
You didn't specify whether the foo
field can be null
or not.
I believe this is why it cannot create a MyModel
object as it needs a foo
value. Try adding null=True
to your foo
field.
Note: depending on what you want, you should consider looking whether blank=True
is needed or not. Don't forget to migrate your changes to models.