扩展 django 用户 django-rest_framework 给了我 KeyError
Posted
技术标签:
【中文标题】扩展 django 用户 django-rest_framework 给了我 KeyError【英文标题】:Extending django User django-rest_framework gives me KeyError 【发布时间】:2017-02-17 19:01:52 【问题描述】:我是 django rest_framework 的新手,并且有问题,我已经根据 django 文档扩展了 auth_user,但是这让我很难过...
models.py
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'
serializers.py
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
views.py
class UserView(viewsets.ModelViewSet):
serializer_class = UserSerializer
queryset = get_user_model().objects
urls.py
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),
但一直给我:
环境:
请求方法:POST 请求地址:http://localhost:8000/user/
Django 版本:1.10.2 Python 版本:3.5.2 已安装的应用程序: ['django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'rest_framework', 'restful'] 已安装的中间件: ['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']
追溯:
文件 “C:\Users\echavez\Envs\YEiPii\lib\site-packages\django\core\handlers\exception.py” 在内部 39. response = get_response(request)
文件 "C:\Users\echavez\Envs\YEiPii\lib\site-packages\django\core\handlers\base.py" 在 _get_response 187. response = self.process_exception_by_middleware(e, request)
文件 "C:\Users\echavez\Envs\YEiPii\lib\site-packages\django\core\handlers\base.py" 在 _get_response 185. response = Wrapped_callback(request, *callback_args, **callback_kwargs)
文件 "C:\Users\echavez\Envs\YEiPii\lib\site-packages\django\views\decorators\csrf.py" 在wrapped_view 58. return view_func(*args, **kwargs)
文件 "C:\Users\echavez\Envs\YEiPii\lib\site-packages\rest_framework\viewsets.py" 在视野中 87. return self.dispatch(request, *args, **kwargs)
文件 "C:\Users\echavez\Envs\YEiPii\lib\site-packages\rest_framework\views.py" 在调度中 474. 响应 = self.handle_exception(exc)
文件 "C:\Users\echavez\Envs\YEiPii\lib\site-packages\rest_framework\views.py" 在句柄异常中 434. self.raise_uncaught_exception(exc)
文件 "C:\Users\echavez\Envs\YEiPii\lib\site-packages\rest_framework\views.py" 在调度中 471. 响应 = 处理程序(请求,*args,**kwargs)
文件 "C:\Users\echavez\Envs\YEiPii\lib\site-packages\rest_framework\mixins.py" 在创建 21. self.perform_create(序列化器)
文件 "C:\Users\echavez\Envs\YEiPii\lib\site-packages\rest_framework\mixins.py" 在 perform_create 26. 序列化器.save()
文件 "C:\Users\echavez\Envs\YEiPii\lib\site-packages\rest_framework\serializers.py" 在保存 192. self.instance = self.create(validated_data)
创建中的文件“C:\Users\echavez\Source\ws\restful\serializers.py” 45.national_id=validated_data['national_id'],
异常类型:/user/ 处的 KeyError 异常值:'national_id'
我知道这是一个新手问题,但是,我真的需要帮助!
提前致谢。
【问题讨论】:
我忘了提到用户是创建的,但不是个人资料,我的意思是:national_id、移动设备等... 【参考方案1】:您以错误的方式获取个人资料数据。 validated_data 是您将分别保存的用户和配置文件数据的字典。
像这样得到它。
profile_data = validated_data.pop('userprofile')
请注意,我们弹出了 userprofile 数据,所以现在您在 validated_data 中只留下了用户数据。所以一个完整的流程如下所示
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/serializers/#writable-nested-representations
【讨论】:
嗨 LaL,感谢您的快速回答,您是对的,但是向我抛出了这个错误:文件“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感谢 LaL ZaDa 为我指明了正确的方向,我的代码终于看起来像这样并且可以正常工作:
serializers.py
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
因为,这不完全是一个嵌套模型(bank_accounts 是嵌套的),所以当我这样做时:
profile_data = validated_data.pop('userprofile')
user = User.objects.create(**validated_data)
UserProfile.objects.create(user=user, **userprofile)
return user
把我扔了...
环境:
请求方法:POST 请求地址:http://localhost:8000/user/
Django 版本:1.10.2 Python 版本:3.5.2 已安装的应用程序: ['django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'rest_framework', 'restful'] 已安装的中间件: ['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']
追溯:
文件 “C:\Users\echavez\Envs\YEiPii\lib\site-packages\django\core\handlers\exception.py” 在内部 39. response = get_response(request)
文件 "C:\Users\echavez\Envs\YEiPii\lib\site-packages\django\core\handlers\base.py" 在 _get_response 187. response = self.process_exception_by_middleware(e, request)
文件 "C:\Users\echavez\Envs\YEiPii\lib\site-packages\django\core\handlers\base.py" 在 _get_response 185. response = Wrapped_callback(request, *callback_args, **callback_kwargs)
文件 "C:\Users\echavez\Envs\YEiPii\lib\site-packages\django\views\decorators\csrf.py" 在wrapped_view 58. return view_func(*args, **kwargs)
文件 "C:\Users\echavez\Envs\YEiPii\lib\site-packages\rest_framework\viewsets.py" 在视野中 87. return self.dispatch(request, *args, **kwargs)
文件 "C:\Users\echavez\Envs\YEiPii\lib\site-packages\rest_framework\views.py" 在调度中 474. 响应 = self.handle_exception(exc)
文件 "C:\Users\echavez\Envs\YEiPii\lib\site-packages\rest_framework\views.py" 在句柄异常中 434. self.raise_uncaught_exception(exc)
文件 "C:\Users\echavez\Envs\YEiPii\lib\site-packages\rest_framework\views.py" 在调度中 471. 响应 = 处理程序(请求,*args,**kwargs)
文件 "C:\Users\echavez\Envs\YEiPii\lib\site-packages\rest_framework\mixins.py" 在创建 21. self.perform_create(序列化器)
文件 "C:\Users\echavez\Envs\YEiPii\lib\site-packages\rest_framework\mixins.py" 在 perform_create 26. 序列化器.save()
文件 "C:\Users\echavez\Envs\YEiPii\lib\site-packages\rest_framework\serializers.py" 在保存 192. self.instance = self.create(validated_data)
创建中的文件“C:\Users\echavez\Source\ws\restful\serializers.py” 49. user = User.objects.create(**validated_data)
文件 "C:\Users\echavez\Envs\YEiPii\lib\site-packages\django\db\models\manager.py" 在 manager_method 中 85. return getattr(self.get_queryset(), name)(*args, **kwargs)
文件 "C:\Users\echavez\Envs\YEiPii\lib\site-packages\django\db\models\query.py" 在创建 397. obj = self.model(**kwargs)
文件 “C:\Users\echavez\Envs\YEiPii\lib\site-packages\django\contrib\auth\base_user.py” 在 初始化 68. super(AbstractBaseUser, self).init(*args, **kwargs)
文件 "C:\Users\echavez\Envs\YEiPii\lib\site-packages\django\db\models\base.py" 在 初始化 550. setattr(self, prop, kwargs[prop])
文件 “C:\Users\echavez\Envs\YEiPii\lib\site-packages\django\db\models\fields\related_descriptors.py” 在设置 500. manager.set(值)
文件 “C:\Users\echavez\Envs\YEiPii\lib\site-packages\django\db\models\fields\related_descriptors.py” 在集合中 687. self.add(*objs, bulk=bulk)
文件 “C:\Users\echavez\Envs\YEiPii\lib\site-packages\django\db\models\fields\related_descriptors.py” 在添加 597. self.field.name:self.instance,
文件 "C:\Users\echavez\Envs\YEiPii\lib\site-packages\django\db\models\query.py" 更新中 637. rows = query.get_compiler(self.db).execute_sql(CURSOR)
文件 "C:\Users\echavez\Envs\YEiPii\lib\site-packages\django\db\models\sql\compiler.py" 在执行_sql 1148. cursor = super(SQLUpdateCompiler, self).execute_sql(result_type)
文件 "C:\Users\echavez\Envs\YEiPii\lib\site-packages\django\db\models\sql\compiler.py" 在执行_sql 824. sql,参数 = self.as_sql()
文件 "C:\Users\echavez\Envs\YEiPii\lib\site-packages\django\db\models\sql\compiler.py" 在 as_sql 1102. val.prepare_database_save(字段),
文件 "C:\Users\echavez\Envs\YEiPii\lib\site-packages\django\db\models\base.py" 在 prepare_database_save 999. raise ValueError("未保存的模型实例 %r 不能用于 ORM 查询。" % self)
异常类型:ValueError at /user/ 异常值:未保存的模型 实例不能在 ORM 查询中使用。
现在我将完成包含嵌套的创建以及更新和删除...
谢谢拉尔
【讨论】:
以上是关于扩展 django 用户 django-rest_framework 给了我 KeyError的主要内容,如果未能解决你的问题,请参考以下文章
使用 angularjs 进行 django-rest 分页
使用 angular 向 django-rest 发送 DELETE 请求被解释为 OPTIONS
Django-Rest + React 前端:CORS 问题