【问题标题】:ValueError: "needs to have a value for field "id" before this many-to-many relationship can be used"ValueError:“在使用这种多对多关系之前,需要为字段“id”设置一个值”
【发布时间】:2017-06-28 13:37:25
【问题描述】:

我创建了一个扩展用户模型,我在我的注册页面上使用它。这两个自定义模型是“Cristin”和一个名为“Rolle”的多对多字段(该人在组织中的角色)。

添加多对多字段后,我收到以下错误消息:ValueError at /accounts/signup/ –"Userextended: username_that_I_registered_with" 需要为可以使用这种多对多关系之前的字段“id”。

我已经 google 了三个小时,似乎解决方案是在保存模型之前在用户 ID 上使用 commit=False。但是,我是 Django 和 Python 的新手,很难确定我应该在哪里编写代码,而且我的尝试到目前为止都没有成功。如果你能帮我解决这个问题,也请通过代码提供解决方案。

我的 models.py 文件:

class User(auth.models.User,auth.models.PermissionsMixin):
def __str__(self):
    return "@{}".format(self.username)

class Personrolle(models.Model):
    id = models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')
    persrolle = models.CharField(max_length = 30, verbose_name="Role")
    def __str__(self):
        return self.persrolle

class Userextended(models.Model):
    id = models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    cristin = models.IntegerField(blank=True, null=True)
    rolle = models.ManyToManyField(Personrolle)

    def __str__(self):
        return self.user.username

...

我的 forms.py 文件:

...

from django import forms
from django.contrib.auth.models import User
from accounts.models import Userextended
from accounts.models import Personrolle
from django.contrib.auth.forms import UserCreationForm
class UserCreateForm(UserCreationForm):

    cristin = forms.IntegerField(required=False)
    rolle = forms.ModelChoiceField(queryset=Personrolle.objects.all())

    class Meta():
        fields = ('first_name','last_name','username','email','password1','password2')
        model = User
        labels = {'username': 'Email',
                  'first_name': 'First name',
                  'last_name': 'Last name',
                  'email': 'Confirm email',
                  'password1': 'Password',
                  'password2': 'Confirm password',
                  'cristin': 'Cristin-ID',
                  'rolle': 'Rolle'}

    def save(self, commit=True):
        if not commit:
            raise NotImplementedError("Can't create User and Userextended without database save")
        user = super(UserCreateForm, self).save(commit=True)
        user_profile = Userextended(user=user,cristin=self.cleaned_data['cristin'],rolle=self.cleaned_data['rolle'])
        user_profile.save()
        return user

...

更详细的错误描述

  • 请求方法:POST
  • 请求网址:http://127.0.0.1:8000/accounts/signup/
  • Django 版本:1.11.2
  • 异常类型:ValueError
  • 异常值: "Userextended: username_that_I_registered_with" 需要为字段 "id" 设置一个值,然后才能使用这种多对多关系。

  • 异常位置:.../anaconda/envs/myEnv/lib/python3.6/site-packages/django/db/models/fields/related_descriptors.py in init, 830行

  • Python 可执行文件:.../anaconda/envs/myEnv/bin/python

  • Python 版本:3.6.1

我的回溯:

File ".../anaconda/envs/myEnv/lib/python3.6/site-packages/django/core/handlers/exception.py" in inner
  41.             response = get_response(request)

File ".../anaconda/envs/myEnv/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
  187.                 response = self.process_exception_by_middleware(e, request)

File ".../anaconda/envs/myEnv/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
  185.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)

File ".../anaconda/envs/myEnv/lib/python3.6/site-packages/django/views/generic/base.py" in view
  68.             return self.dispatch(request, *args, **kwargs)

File ".../anaconda/envs/myEnv/lib/python3.6/site-packages/django/views/generic/base.py" in dispatch
  88.         return handler(request, *args, **kwargs)

File ".../anaconda/envs/myEnv/lib/python3.6/site-packages/django/views/generic/edit.py" in post
  217.         return super(BaseCreateView, self).post(request, *args, **kwargs)

File ".../anaconda/envs/myEnv/lib/python3.6/site-packages/django/views/generic/edit.py" in post
  183.             return self.form_valid(form)

File ".../anaconda/envs/myEnv/lib/python3.6/site-packages/django/views/generic/edit.py" in form_valid
  162.         self.object = form.save()

File "…PROJECT/accounts/forms.py" in save
  57.         user_profile = Userextended(user=user,cristin=self.cleaned_data['cristin'],rolle=self.cleaned_data['rolle'])

File ".../anaconda/envs/myEnv/lib/python3.6/site-packages/django/db/models/base.py" in __init__
  566.                             _setattr(self, prop, kwargs[prop])

File ".../anaconda/envs/myEnv/lib/python3.6/site-packages/django/db/models/fields/related_descriptors.py" in __set__
  536.         manager = self.__get__(instance)

File ".../anaconda/envs/myEnv/lib/python3.6/site-packages/django/db/models/fields/related_descriptors.py" in __get__
  513.         return self.related_manager_cls(instance)

File ".../anaconda/envs/myEnv/lib/python3.6/site-packages/django/db/models/fields/related_descriptors.py" in __init__
  830.                                  (instance, self.pk_field_names[self.source_field_name]))

Exception Type: ValueError at /accounts/signup/
Exception Value: "<Userextended: testytester@yahoo.com>" needs to have a value for field "id" before this many-to-many relationship can be used.

【问题讨论】:

    标签: python django


    【解决方案1】:

    您只需要在表单中编辑保存方法,

    def save(self, *args, **kwargs): 
        if not commit: 
            raise NotImplementedError("Can't create User and Userextended without database save") 
        user = super().save(*args, **kwargs)
        user_profile = Userextended(user=user, cristin=self.cleaned_data['cristin']) 
        user_profile.save() 
        user_profile.rolle.add(self.cleaned_data['rolle'])
        user_profile.save()
        return user
    

    您需要先保存 UserExtended 模型,然后将 Rolle 实例添加到多对多关系中。

    【讨论】:

      【解决方案2】:

      如果您使用的是 DRF,则可以使用 validate 方法:

      而不是这个

          def create(self, validated_data):
              validated_data['slug'] = slugify(validated_data['name'])
              return budgets.models.BudgetCategory.objects.create(**validated_data)
      
          def update(self, instance, validated_data):
              instance.slug = slugify(validated_data['name'])
              instance.save()
              return instance
      

      这样做

      def validate(self, data):
              data['slug'] = slugify(data['name'])
              return data
      

      【讨论】:

        【解决方案3】:

        出现错误消息是因为“rolle”应指定为多对一关系而不是多对多关系。该模型已更新为以下内容,现在可以完美运行:

        class Userextended(models.Model):
            ...
            rolle = models.ForeignKey(Personrolle, models.SET_NULL, blank=True, null=True)
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2022-07-20
          • 1970-01-01
          • 1970-01-01
          • 2020-09-10
          • 1970-01-01
          • 2020-08-08
          • 1970-01-01
          相关资源
          最近更新 更多