Django表单隐藏tenant字段,中间件添加后存库仍报NOT NULL约束错误
问题原因
你的中间件虽然将tenant参数加入了POST请求,但Django ModelForm仅会处理在fields或exclude中声明的字段。由于LocationCreateForm的fields没有包含tenant,表单不会把POST中的tenant值赋值给模型实例,最终保存时触发NOT NULL约束错误。
解决方案
方法一:在表单save方法中手动设置租户(推荐)
直接在表单的save方法中从用户信息获取租户ID,无需依赖中间件修改POST:
from django.forms import ModelForm from accounts.models import UserProfileModel class LocationCreateForm(ModelForm): class Meta: model = LocationModel fields = ('city', 'country', 'building', 'department', 'contact_name', 'email_address', 'phone_number') def __init__(self, *args, **kwargs): self.request = kwargs.pop('request', None) super().__init__(*args, **kwargs) def save(self, commit=True): if self.request and self.request.user.is_authenticated: user_profile = UserProfileModel.objects.get(user_id=self.request.user.id) self.instance.tenant_id = user_profile.last_tenant_id return super().save(commit=commit)
然后在基于类的视图中传递request给表单:
class LocationCreateView(CreateView): # ... 其他配置 def get_form_kwargs(self): kwargs = super().get_form_kwargs() kwargs['request'] = self.request return kwargs
方法二:在视图的form_valid方法中设置租户
如果使用类视图(如CreateView),直接在form_valid中为实例赋值租户:
from django.views.generic.edit import CreateView from accounts.models import UserProfileModel class LocationCreateView(CreateView): model = LocationModel form_class = LocationCreateForm success_url = '/oam/location/list/' def form_valid(self, form): user_profile = UserProfileModel.objects.get(user_id=self.request.user.id) form.instance.tenant_id = user_profile.last_tenant_id return super().form_valid(form)
方法三:让表单包含租户字段并隐藏
将tenant加入表单字段,用隐藏控件渲染,这样表单会自动处理POST中的tenant参数:
from django.forms import ModelForm, HiddenInput class LocationCreateForm(ModelForm): class Meta: model = LocationModel fields = ('tenant', 'city', 'country', 'building', 'department', 'contact_name', 'email_address', 'phone_number') widgets = { 'tenant': HiddenInput(), }
内容的提问来源于stack exchange,提问作者Michael Sanders
相关产品推荐
相关产品推荐

