Почему Django поднял IntegrityError: нулевое значение в столбце "user_id" нарушает ограничение not-null при фиксации формы?
У меня есть модель 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)
2 ответа
Рядом с исправлением @solarissmoke (изменение instance.owner
в instance.user
), который исправляет IntegrityError, вы запускаете 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)