>我有一个UserSession模型,该模型创建一个使用IP地址和城市数据的会话,以使用Geip2填充模型。我设置了一个表单,该表单采用我希望用户输入但得到的信息:
**django.db.utils.IntegrityError: null value in column "user_id" violates not-null constraint**
当我提交表格时。对象已创建,但表单采用的信息不会保存到对象中。
视图:
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
(旁边,您在此处的 is_valid()
方法中触发user_logged_in()
信号:
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)