Extending django User django-rest_framework gives me KeyError
我不熟悉django rest_框架,我已经发布了,我已经根据django文档扩展了auth_用户,但这让我很难……
型号.py
1 2 3 4 5 6 7 8 9 10 11 | class UserProfile(models.Model): user = models.OneToOneField(User, primary_key=True, on_delete=models.CASCADE) national_id = models.CharField(max_length=10, blank=True, null=True) mobile = models.CharField(max_length=10) pin = models.IntegerField() pattern = models.IntegerField(blank=True, null=True) fingerprint = models.CharField(max_length=45, blank=True, null=True) class Meta: managed = False db_table = 'user_profile' |
序列化程序.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | class UserSerializer(serializers.ModelSerializer): national_id = serializers.CharField(source='userprofile.national_id', allow_null=True, required=False) mobile = serializers.CharField(source='userprofile.mobile') pin = serializers.IntegerField(source='userprofile.pin', write_only=True) pattern = serializers.IntegerField(source='userprofile.pattern', write_only=True) fingerprint = serializers.CharField(source='userprofile.fingerprint', write_only=True, allow_null=True, required=False) class Meta: model = User fields = ('id', 'username', 'password', 'first_name', 'last_name', 'email', 'national_id', 'mobile', 'pin', 'pattern', 'fingerprint') write_only_fields = ('password',) read_only_fields = ('last_login', 'is_superuser', 'is_staff', 'is_active', 'date_joined') def create(self, validated_data): user = User( username=validated_data['username'], first_name=validated_data['first_name'], last_name=validated_data['last_name'], email=validated_data['email'], ) user.set_password(validated_data['password']) user.save() userprofile = UserProfile( user=user, national_id=validated_data['national_id'], mobile=validated_data['mobile'], pin=validated_data['pin'], pattern=validated_data['pattern'], fingerprint=validated_data['fingerprint'], ) userprofile.save() return user |
号
视图.py
1 2 3 | class UserView(viewsets.ModelViewSet): serializer_class = UserSerializer queryset = get_user_model().objects |
网址.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | from django.conf.urls import include, url from django.contrib import admin from rest_framework.routers import DefaultRouter from restful.views import * router = DefaultRouter() router.register(r'availability-notification', AvailabiltyNotificationView) router.register(r'bank', BankView) router.register(r'recipient', RecipientView) router.register(r'user', UserView) urlpatterns = [ url(r'^', include(router.urls)), url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')), url(r'^admin/', admin.site.urls), |
。
但一直在给我:
Environment:
Request Method: POST Request URL: http://localhost:8000/user/
Django Version: 1.10.2 Python Version: 3.5.2 Installed Applications:
['django.contrib.admin', 'django.contrib.auth',
'django.contrib.contenttypes', 'django.contrib.sessions',
'django.contrib.messages', 'django.contrib.staticfiles',
'rest_framework', 'restful'] Installed Middleware:
['django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware']Traceback:
File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages\django\core\handlers\exception.py"
in inner
39. response = get_response(request)File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages\django\core\handlers\base.py"
in _get_response
187. response = self.process_exception_by_middleware(e, request)File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages\django\core\handlers\base.py"
in _get_response
185. response = wrapped_callback(request, *callback_args, **callback_kwargs)File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages\django\views\decorators\csrf.py"
in wrapped_view
58. return view_func(*args, **kwargs)File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages
est_framework\viewsets.py"
in view
87. return self.dispatch(request, *args, **kwargs)File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages
est_framework\views.py"
in dispatch
474. response = self.handle_exception(exc)File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages
est_framework\views.py"
in handle_exception
434. self.raise_uncaught_exception(exc)File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages
est_framework\views.py"
in dispatch
471. response = handler(request, *args, **kwargs)File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages
est_framework\mixins.py"
in create
21. self.perform_create(serializer)File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages
est_framework\mixins.py"
in perform_create
26. serializer.save()File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages
est_framework\serializers.py"
in save
192. self.instance = self.create(validated_data)File"C:\Users\echavez\Source\ws
estful\serializers.py" in create
45. national_id=validated_data['national_id'],Exception Type: KeyError at /user/ Exception Value: 'national_id'
号
我知道这是个新手问题,但我真的需要帮助!
事先谢谢。
您获取配置文件数据的方式不正确。validated_data是用户和配置文件数据的字典,您将分别保存这些数据。
像这样拿。
1 | profile_data = validated_data.pop('userprofile') |
请注意,我们弹出了用户配置文件数据,所以现在您只剩下已验证的用户数据了。所以完整的流程如下
1 2 3 4 | profile_data = validated_data.pop('userprofile') user = User.objects.create(**validated_data) UserProfile.objects.create(user=user, **profile_data) return user |
号
看看这里
http://www.django-rest-framework.org/api-guide/serializer/可写嵌套表示
多亏了Lal Zada给我指明了正确的方向,我的代码最终看起来像这样,并且可以工作:
序列化程序.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | class UserSerializer(serializers.ModelSerializer): national_id = serializers.CharField(source='userprofile.national_id', allow_null=True, required=False) mobile = serializers.CharField(source='userprofile.mobile') pin = serializers.IntegerField(source='userprofile.pin', write_only=True) pattern = serializers.IntegerField(source='userprofile.pattern', write_only=True) fingerprint = serializers.CharField(source='userprofile.fingerprint', write_only=True, allow_null=True, required=False) bank_accounts = UserBankAccountSerializer(many=True) class Meta: model = User fields = ('id', 'username', 'password', 'first_name', 'last_name', 'email', 'national_id', 'mobile', 'pin', 'pattern', 'fingerprint', 'bank_accounts') write_only_fields = ('password',) read_only_fields = ('last_login', 'is_superuser', 'is_staff', 'is_active', 'date_joined') def create(self, validated_data): user = User( username=validated_data['username'], first_name=validated_data['first_name'], last_name=validated_data['last_name'], email=validated_data['email'], ) user.set_password(validated_data['password']) user.save() profile_data = validated_data.pop('userprofile') userprofile = UserProfile( user=user, national_id=profile_data['national_id'], mobile=profile_data['mobile'], pin=profile_data['pin'], pattern=profile_data['pattern'], fingerprint=profile_data['fingerprint'], ) userprofile.save() return user |
因为,这不是一个嵌套的模型(银行帐户是嵌套的),所以当我这样做时:
1 2 3 4 | profile_data = validated_data.pop('userprofile') user = User.objects.create(**validated_data) UserProfile.objects.create(user=user, **userprofile) return user |
。
把我扔了…
Environment:
Request Method: POST Request URL: http://localhost:8000/user/
Django Version: 1.10.2 Python Version: 3.5.2 Installed Applications:
['django.contrib.admin', 'django.contrib.auth',
'django.contrib.contenttypes', 'django.contrib.sessions',
'django.contrib.messages', 'django.contrib.staticfiles',
'rest_framework', 'restful'] Installed Middleware:
['django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware']Traceback:
File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages\django\core\handlers\exception.py"
in inner
39. response = get_response(request)File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages\django\core\handlers\base.py"
in _get_response
187. response = self.process_exception_by_middleware(e, request)File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages\django\core\handlers\base.py"
in _get_response
185. response = wrapped_callback(request, *callback_args, **callback_kwargs)File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages\django\views\decorators\csrf.py"
in wrapped_view
58. return view_func(*args, **kwargs)File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages
est_framework\viewsets.py"
in view
87. return self.dispatch(request, *args, **kwargs)File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages
est_framework\views.py"
in dispatch
474. response = self.handle_exception(exc)File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages
est_framework\views.py"
in handle_exception
434. self.raise_uncaught_exception(exc)File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages
est_framework\views.py"
in dispatch
471. response = handler(request, *args, **kwargs)File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages
est_framework\mixins.py"
in create
21. self.perform_create(serializer)File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages
est_framework\mixins.py"
in perform_create
26. serializer.save()File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages
est_framework\serializers.py"
in save
192. self.instance = self.create(validated_data)File"C:\Users\echavez\Source\ws
estful\serializers.py" in create
49. user = User.objects.create(**validated_data)File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages\django\db\models\manager.py"
in manager_method
85. return getattr(self.get_queryset(), name)(*args, **kwargs)File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages\django\db\models\query.py"
in create
397. obj = self.model(**kwargs)File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages\django\contrib\auth\base_user.py"
in init
68. super(AbstractBaseUser, self).init(*args, **kwargs)File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages\django\db\models\base.py"
in init
550. setattr(self, prop, kwargs[prop])File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages\django\db\models\fields
elated_descriptors.py"
in set
500. manager.set(value)File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages\django\db\models\fields
elated_descriptors.py"
in set
687. self.add(*objs, bulk=bulk)File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages\django\db\models\fields
elated_descriptors.py"
in add
597. self.field.name: self.instance,File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages\django\db\models\query.py"
in update
637. rows = query.get_compiler(self.db).execute_sql(CURSOR)File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages\django\db\models\sql\compiler.py"
in execute_sql
1148. cursor = super(SQLUpdateCompiler, self).execute_sql(result_type)File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages\django\db\models\sql\compiler.py"
in execute_sql
824. sql, params = self.as_sql()File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages\django\db\models\sql\compiler.py"
in as_sql
1102. val.prepare_database_save(field),File
"C:\Users\echavez\Envs\YEiPii\lib\site-packages\django\db\models\base.py"
in prepare_database_save
999. raise ValueError("Unsaved model instance %r cannot be used in an ORM query." % self)Exception Type: ValueError at /user/ Exception Value: Unsaved model
instance cannot be used in an ORM query.
号
现在我将完成创建以包括嵌套的和更新和删除…
谢谢,拉尔