为什么Django引发IntegrityError:列“user_id”中的null值在提交表单时违反了非空约束?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为什么Django引发IntegrityError:列“user_id”中的null值在提交表单时违反了非空约束?相关的知识,希望对你有一定的参考价值。
我有一个UserSession模型,它创建一个使用IPaddress的会话,以及使用Geip2填充模型的城市数据。我设置了一个表单,其中包含我希望用户输入的信息,但获取:
**django.db.utils.IntegrityError: null value in column "user_id" violates not-null constraint**
当我提交表格时。创建对象但表单所采用的信息不会保存到对象。
views:
class NewLocationCreateForm(CreateView):
model = UserSession
success_url = reverse_lazy('post:index')
form_class = NewLocationCreateForm
def form_valid(self, form):
if form.is_valid():
roote = Post.objects.filter(owner =self.request.user)
instance = form.save(commit=False)
instance.owner = self.request.user
user_logged_in.send(self.request.user, request=self.request)
return super(NewLocationCreateForm, self).form_valid(form)
def get_form_kwargs(self):
kwargs = super(NewLocationCreateForm, self).get_form_kwargs()
kwargs['user'] = self.request.user
return kwargs
问题似乎是:
if form.is_valid():
return super(NewLocationCreateForm, self).form_valid(form)
Geoip2的用户会话调用似乎有效,但它不保存表单
forms.py
from .models import UserSession
from post.models import Post
from django import forms
class NewLocationCreateForm(forms.ModelForm):
class Meta:
model = UserSession
fields = [
'g_post',
'coordinate',
'place_name'
]
def __init__(self,user=None, *args, **kwargs):
super(NewLocationCreateForm, self).__init__(*args, **kwargs)
self.fields['g_post'].queryset = Post.objects.filter(owner=user)
models.py:
from django.conf import settings
from django.db import models
from django.contrib.contenttypes.models import ContentType
from django.contrib.auth.models import User
from django.db.models.signals import pre_save
from analytics.signals import user_logged_in
from analytics.utils import get_client_city_data, get_client_ip
from post.models import Post
User = settings.AUTH_USER_MODEL
class UserSessionManager(models.Manager):
def create_new(self, user, session_key=None, ip_address=None, city_data=None):
session_new = self.model()
session_new.user = user
session_new.session_key = session_key
if ip_address is not None:
session_new.ip_address = ip_address
if city_data:
session_new.city_data = city_data
try:
city = city_data['city']
except:
city = None
session_new.city = city
try:
country = city_data['country_name']
except:
country = None
session_new.country = country
session_new.save()
return session_new
return None
class UserSession(models.Model):
g_post = models.ForeignKey(Post, on_delete=models.CASCADE, null=True)
user = models.ForeignKey(User)
coordinate = models.CharField(max_length=1000, blank=True)
place_name = models.CharField(max_length=250, blank=True)
location_photo = models.ImageField(upload_to='location_image', blank=True)
updated = models.DateTimeField(auto_now=True, null=True)
session_key = models.CharField(max_length=60, null=True, blank=True)
ip_address = models.GenericIPAddressField(null=True, blank=True)
city_data = models.TextField(null=True, blank=True)
city = models.CharField(max_length=120, null=True, blank=True)
country = models.CharField(max_length=120, null=True, blank=True)
active = models.BooleanField(default=True)
timestamp = models.DateTimeField(auto_now_add=True)
objects = UserSessionManager()
def __str__(self):
city = self.city
country = self.country
place_name = self.place_name
if city and country:
return f"{city}, {country}"
elif city and not country:
return f"{city}"
elif country and not city:
return f"{country}"
return self.place_name
def user_logged_in_receiver(sender, request, *args, **kwargs):
user = sender
ip_address = get_client_ip(request)
city_data = get_client_city_data(ip_address)
request.session['CITY'] = str(city_data.get('city', 'New York'))
session_key = request.session.session_key
UserSession.objects.create_new(
user=user,
session_key=session_key,
ip_address=ip_address,
city_data=city_data
)
user_logged_in.connect(user_logged_in_receiver)
答案
在修复IntegrityError的@solarissmoke修改(更改instance.owner
到instance.user
)旁边,你在user_logged_in()
方法中触发is_valid()
信号:
def form_valid(self, form):
if form.is_valid():
roote = Post.objects.filter(owner =self.request.user)
instance = form.save(commit=False)
instance.user = self.request.user
# Here you trigger signal that creates UserSession!
user_logged_in.send(self.request.user, request=self.request)
return super(NewLocationCreateForm, self).form_valid(form)
因此,使用CreateView创建一个对象,使用此信号创建另一个对象。在form_valid()
中删除此行。
编辑:要包含来自信号的数据,只需将其添加到form_valid()
,如下所示:
def form_valid(self, form):
if form.is_valid():
roote = Post.objects.filter(owner =self.request.user)
instance = form.save(commit=False)
instance.user = self.request.user
instance.ip_address = get_client_ip(self.request)
instance.city_data = get_client_city_data(instance.ip_address)
instance.session_key = self.request.session.session_key
return super(NewLocationCreateForm, self).form_valid(form)
另一答案
你的UserSession
模型没有定义owner
字段,所以在实例上设置它对你没有好处。您可能想要这样做:
if form.is_valid():
roote = Post.objects.filter(owner =self.request.user)
instance = form.save(commit=False)
instance.user = self.request.user # You need to set instance.user, not instance.owner
user_logged_in.send(self.request.user, request=self.request)
return super(NewLocationCreateForm, self).form_valid(form)
以上是关于为什么Django引发IntegrityError:列“user_id”中的null值在提交表单时违反了非空约束?的主要内容,如果未能解决你的问题,请参考以下文章
ActiveStorage::IntegrityError 何时引发?
SQLAlchemy 关联表(关联对象模式)引发 IntegrityError