【问题标题】:Django Integrity Error while saving form保存表单时出现 Django 完整性错误
【发布时间】:2017-11-13 20:57:10
【问题描述】:

我扩展了 Django 用户模型并添加了自己的字段,目前正在努力在注册期间填写这些字段。表单似乎工作正常,除了保存之外的所有内容。

我使用了this 来帮助我。

这是用户模型的扩展:

class StudentProfile(models.Model):
    user = models.OneToOneField(User, null = True, related_name='user', on_delete=models.CASCADE)
    teacher = models.BooleanField(default = False)
    school = models.CharField(max_length = 50)

def create_StudentProfile(sender, **kwargs):
    if kwargs['created']:
        user_profile = StudentProfile.objects.create(user = kwargs['instance'])


post_save.connect(create_StudentProfile, sender = User)

这是我的表格:

class StudentRegistrationForm(UserCreationForm):
    email = forms.EmailField(required = True)
    school = forms.CharField(required = True)

    def __init__(self, *args, **kwargs):
        super(StudentRegistrationForm, self).__init__(*args, **kwargs)
        self.fields['username'].help_text = ''
        self.fields['password2'].help_text = ''


    class Meta:
        model = User

        fields = (
            'username',
            'first_name',
            'last_name',
            'email',
            'school',
            'password1',
            'password2'            
        )

    def save(self, commit = True):
        user = super(StudentRegistrationForm, self).save(commit = False)
        user.first_name = self.cleaned_data['first_name']
        user.last_name = self.cleaned_data['last_name']
        user.email = self.cleaned_data['email']


        student_profile = StudentProfile(user = user, school = self.cleaned_data['school'])

        if commit:
            user.save()
            student_profile.save()

        return user, student_profile

这是我的看法:

def registration(request):
    if request.method == 'POST':
        form = StudentRegistrationForm(request.POST)
        if form.is_valid():
            user, user_profile = form.save(commit = False)
            form.save()
            return render(request, 'accounts/home.html')
        else:
            args = {'form': form}
            return render(request, 'accounts/reg_form.html', args)

    else:
        form = StudentRegistrationForm()

        args = {'form': form}
        return render(request, 'accounts/reg_form.html', args)

这是我的回溯:

File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/db/backends/utils.py" in execute
  64.                 return self.cursor.execute(sql, params)

File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/db/backends/sqlite3/base.py" in execute
  337.         return Database.Cursor.execute(self, query, params)

The above exception (NOT NULL constraint failed: userprofile_studentprofile.user_id) was the direct cause of the following exception:

File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/core/handlers/exception.py" in inner
  39.             response = get_response(request)

File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
  187.                 response = self.process_exception_by_middleware(e, request)

File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
  185.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "/Users/wtreston/GDrive/LesRev/lesssonreview/userprofile/views.py" in registration
  13.             form.save()

File "/Users/wtreston/GDrive/LesRev/lesssonreview/userprofile/forms.py" in save
  41.             student_profile.save()

File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/db/models/base.py" in save
  796.                        force_update=force_update, update_fields=update_fields)

File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/db/models/base.py" in save_base
  824.             updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)

File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/db/models/base.py" in _save_table
  908.             result = self._do_insert(cls._base_manager, using, fields, update_pk, raw)

File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/db/models/base.py" in _do_insert
  947.                                using=using, raw=raw)

File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/db/models/manager.py" in manager_method
  85.                 return getattr(self.get_queryset(), name)(*args, **kwargs)

File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/db/models/query.py" in _insert
  1045.         return query.get_compiler(using=using).execute_sql(return_id)

File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/db/models/sql/compiler.py" in execute_sql
  1054.                 cursor.execute(sql, params)

File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/db/backends/utils.py" in execute
  79.             return super(CursorDebugWrapper, self).execute(sql, params)

File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/db/backends/utils.py" in execute
  64.                 return self.cursor.execute(sql, params)

File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/db/utils.py" in __exit__
  94.                 six.reraise(dj_exc_type, dj_exc_value, traceback)

File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/utils/six.py" in reraise
  685.             raise value.with_traceback(tb)

File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/db/backends/utils.py" in execute
  64.                 return self.cursor.execute(sql, params)

File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/django/db/backends/sqlite3/base.py" in execute
  337.         return Database.Cursor.execute(self, query, params)

Exception Type: IntegrityError at /users/
Exception Value: NOT NULL constraint failed: userprofile_studentprofile.user_id

谢谢!

【问题讨论】:

    标签: python django django-forms


    【解决方案1】:

    您必须使用User 模型创建一个用户,然后您必须将此用户传递给StudentProfile,因为它是一个onetoone 字段给您StudentProfile

    def save(self, request):
            form = StudentRegistrationForm(request.POST)
            user = User.objects.create(first_name=form.cleaned_data['first_name'],
                                last_name=form.cleaned_data['last_name'],
                                email=form.cleaned_data['email'],
                                username=form.cleaned_data['username'])
            user_profile = StudentProfile.objects.create(user=user,
                                                    teacher=form.cleaned_data['teacher'],
                                                    school=form.cleaned_data['school'])
    
    
            return user, student_profile
    

    【讨论】:

    • 在尝试您的方法时,我在“user, user_profile = form.save()”行的视图中收到一条错误消息,提示“save() 缺少 1 个必需的位置参数:'request'”跨度>
    • 让它工作。将其更改为 self.cleaned_data 并且效果很好!
    • 检查你的request.POST是否有数据。
    • 我必须删除信号处理程序才能使其工作,我将如何调整我的代码以允许我拥有信号处理程序以及此方法?
    • 您究竟想使用信号处理程序做什么?
    【解决方案2】:

    看起来use对象没有被保存,所以它可以存储它的引用StudentProfile模型。

    【讨论】:

      【解决方案3】:

      这里有很多问题。

      直接的问题是您要在两个地方创建 UserProfile。您已经注册了一个信号处理程序 - create_StudentProfile - 在创建用户时自动创建一个;但您也在表单的 save 方法中创建一个新的。

      您应该考虑是否真的需要该信号处理程序。如果您总是要通过此表单创建用户,则不需要该处理程序。

      如果您确实决定需要该信号,那么您需要重做保存方法以将其考虑在内。比如:

      def save(self, commit=True):
          user = super(StudentRegistrationForm, self).save(commit = False)
          if commit:
              user.save()
              profile = user.userprofile
          else:
              profile = UserProfile(user=user)
      
          profile.school = self.cleaned_data['school']
      
          if commit:
              profile.save()
      
          return user, student_profile
      

      您会注意到不需要设置电子邮件和姓名,因为这些都是通过超级调用中的表单完成的。

      第二个问题是您在视图中调用了两次 save 方法。不要那样做。

          if form.is_valid():
              user, user_profile = form.save()
              return render(request, 'accounts/home.html')
      

      【讨论】:

      • 我已删除信号处理程序并更改了 views.py 中的代码,但我仍然收到相同的错误:“IntegrityError at /users/ NOT NULL 约束失败:userprofile_studentprofile.user_id”。正在创建用户并将其添加到数据库中,但是未保存添加的字段(例如学校)。
      • 你不应该同时做这两件事,它们是替代品。您仍然需要在某处创建配置文件。
      • 我很困惑...对不起。根据我对您所写内容的理解,信号处理程序制作了 StudentProfile,以及 Forms 保存方法中的一个。因为我只会通过这个表单添加用户,所以我删除了信号处理程序,并保留了我的保存方法。然后我在我的视图中更新了保存方法。我不明白你的意思是我不应该做这两件事?谢谢
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-06-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-18
      相关资源
      最近更新 更多