扩展django用户django-rest_framework给了我KeyError

时间:2016-10-09 04:06:47

标签: django django-models django-rest-framework django-users python-3.5

我是django rest_framework的新手并且已经发布了,我已经根据django docs扩展了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&#39 ;,   ' django.contrib.sessions.middleware.SessionMiddleware&#39 ;,   ' django.middleware.common.CommonMiddleware&#39 ;,   ' django.middleware.csrf.CsrfViewMiddleware&#39 ;,   ' django.contrib.auth.middleware.AuthenticationMiddleware&#39 ;,   ' django.contrib.messages.middleware.MessageMiddleware&#39 ;,   ' django.middleware.clickjacking.XFrameOptionsMiddleware']

     

回溯:

     

文件   " C:\用户\ echavez \ ENVS \ YEiPii \ lib中\站点包\ django的\芯\处理程序\ exception.py"   在内心     39. response = get_response(request)

     

文件   " C:\用户\ echavez \ ENVS \ YEiPii \ lib中\站点包\ django的\芯\处理程序\ base.py"   在_get_response中     187. response = self.process_exception_by_middleware(e,request)

     

文件   " C:\用户\ echavez \ ENVS \ YEiPii \ lib中\站点包\ django的\芯\处理程序\ base.py"   在_get_response中     185. response = wrapped_callback(request,* callback_args,** callback_kwargs)

     

文件   " C:\用户\ echavez \ ENVS \ YEiPii \ lib中\站点包\ django的\视图\装饰\ csrf.py"   在wrapped_view中     58. return view_func(* args,** kwargs)

     

文件   " C:\用户\ echavez \ ENVS \ YEiPii \ lib中\站点包\ rest_framework \ viewsets.py"   在视野中     87. return self.dispatch(request,* args,** kwargs)

     

文件   " C:\用户\ echavez \ ENVS \ YEiPii \ lib中\站点包\ rest_framework \ views.py"   在发货     474. response = self.handle_exception(exc)

     

文件   " C:\用户\ echavez \ ENVS \ YEiPii \ lib中\站点包\ rest_framework \ views.py"   在handle_exception中     434. self.raise_uncaught_exception(exc)

     

文件   " C:\用户\ echavez \ ENVS \ YEiPii \ lib中\站点包\ rest_framework \ views.py"   在发货     471. response = handler(request,* args,** kwargs)

     

文件   " C:\用户\ echavez \ ENVS \ YEiPii \ lib中\站点包\ rest_framework \ mixins.py"   在创造     21. self.perform_create(序列化程序)

     

文件   " C:\用户\ echavez \ ENVS \ YEiPii \ lib中\站点包\ rest_framework \ mixins.py"   在perform_create中     26. serializer.save()

     

文件   " C:\用户\ echavez \ ENVS \ YEiPii \ lib中\站点包\ 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'

我知道这是一个新手问题,但是,我真的需要帮助!

提前致谢。

2 个答案:

答案 0 :(得分:2)

您正在以错误的方式获取个人资料数据。 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

答案 1 :(得分:0)

感谢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已安装的应用程序:   [&#39; django.contrib.admin&#39;,&#39; django.contrib.auth&#39;,   &#39; django.contrib.contenttypes&#39;,&#39; django.contrib.sessions&#39;,   &#39; django.contrib.messages&#39;,&#39; django.contrib.staticfiles&#39;,   &#39; rest_framework&#39;,&#39; restful&#39;]已安装的中间件:   [&#39; django.middleware.security.SecurityMiddleware&#39 ;,   &#39; django.contrib.sessions.middleware.SessionMiddleware&#39 ;,   &#39; django.middleware.common.CommonMiddleware&#39 ;,   &#39; django.middleware.csrf.CsrfViewMiddleware&#39 ;,   &#39; django.contrib.auth.middleware.AuthenticationMiddleware&#39 ;,   &#39; django.contrib.messages.middleware.MessageMiddleware&#39 ;,   &#39; django.middleware.clickjacking.XFrameOptionsMiddleware&#39;]

     

回溯:

     

文件   &#34; C:\用户\ echavez \ ENVS \ YEiPii \ lib中\站点包\ django的\芯\处理程序\ exception.py&#34;   在内心     39. response = get_response(request)

     

文件   &#34; C:\用户\ echavez \ ENVS \ YEiPii \ lib中\站点包\ django的\芯\处理程序\ base.py&#34;   在_get_response中     187. response = self.process_exception_by_middleware(e,request)

     

文件   &#34; C:\用户\ echavez \ ENVS \ YEiPii \ lib中\站点包\ django的\芯\处理程序\ base.py&#34;   在_get_response中     185. response = wrapped_callback(request,* callback_args,** callback_kwargs)

     

文件   &#34; C:\用户\ echavez \ ENVS \ YEiPii \ lib中\站点包\ django的\视图\装饰\ csrf.py&#34;   在wrapped_view中     58. return view_func(* args,** kwargs)

     

文件   &#34; C:\用户\ echavez \ ENVS \ YEiPii \ lib中\站点包\ rest_framework \ viewsets.py&#34;   在视野中     87. return self.dispatch(request,* args,** kwargs)

     

文件   &#34; C:\用户\ echavez \ ENVS \ YEiPii \ lib中\站点包\ rest_framework \ views.py&#34;   在发货     474. response = self.handle_exception(exc)

     

文件   &#34; C:\用户\ echavez \ ENVS \ YEiPii \ lib中\站点包\ rest_framework \ views.py&#34;   在handle_exception中     434. self.raise_uncaught_exception(exc)

     

文件   &#34; C:\用户\ echavez \ ENVS \ YEiPii \ lib中\站点包\ rest_framework \ views.py&#34;   在发货     471. response = handler(request,* args,** kwargs)

     

文件   &#34; C:\用户\ echavez \ ENVS \ YEiPii \ lib中\站点包\ rest_framework \ mixins.py&#34;   在创造     21. self.perform_create(序列化程序)

     

文件   &#34; C:\用户\ echavez \ ENVS \ YEiPii \ lib中\站点包\ rest_framework \ mixins.py&#34;   在perform_create中     26. serializer.save()

     

文件   &#34; C:\用户\ echavez \ ENVS \ YEiPii \ lib中\站点包\ rest_framework \ serializers.py&#34;   在保存     192. self.instance = self.create(validated_data)

     

文件&#34; C:\ Users \ echavez \ Source \ ws \ restful \ serializers.py&#34;在创造     49. user = User.objects.create(** validated_data)

     

文件   &#34; C:\用户\ echavez \ ENVS \ YEiPii \ lib中\站点包\ django的\分贝\模型\ manager.py&#34;   在manager_method中     85. return getattr(self.get_queryset(),name)(* args,** kwargs)

     

文件   &#34; C:\用户\ echavez \ ENVS \ YEiPii \ lib中\站点包\ django的\分贝\模型\ query.py&#34;   在创造     397. obj = self.model(** kwargs)

     

文件   &#34; C:\用户\ echavez \ ENVS \ YEiPii \ lib中\站点包\ django的\的contrib \ AUTH \ base_user.py&#34;   在 init     68. super(AbstractBaseUser,self)。 init (* args,** kwargs)

     

文件   &#34; C:\用户\ echavez \ ENVS \ YEiPii \ lib中\站点包\ django的\分贝\模型\ base.py&#34;   在 init     550. setattr(self,prop,kwargs [prop])

     

文件   &#34; C:\用户\ echavez \ ENVS \ YEiPii \ lib中\站点包\ django的\分贝\模型\字段\ related_descriptors.py&#34;   在设置     500. manager.set(value)

     

文件   &#34; C:\用户\ echavez \ ENVS \ YEiPii \ lib中\站点包\ django的\分贝\模型\字段\ related_descriptors.py&#34;   在集合中     687. self.add(* objs,bulk = bulk)

     

文件   &#34; C:\用户\ echavez \ ENVS \ YEiPii \ lib中\站点包\ django的\分贝\模型\字段\ related_descriptors.py&#34;   另外     597. self.field.name:self.instance,

     

文件   &#34; C:\用户\ echavez \ ENVS \ YEiPii \ lib中\站点包\ django的\分贝\模型\ query.py&#34;   在更新中     637. rows = query.get_compiler(self.db).execute_sql(CURSOR)

     

文件   &#34; C:\用户\ echavez \ ENVS \ YEiPii \ lib中\站点包\ django的\分贝\模型\ SQL \ compiler.py&#34;   在execute_sql中     1148. cursor = super(SQLUpdateCompiler,self).execute_sql(result_type)

     

文件   &#34; C:\用户\ echavez \ ENVS \ YEiPii \ lib中\站点包\ django的\分贝\模型\ SQL \ compiler.py&#34;   在execute_sql中     824. sql,params = self.as_sql()

     

文件   &#34; C:\用户\ echavez \ ENVS \ YEiPii \ lib中\站点包\ django的\分贝\模型\ SQL \ compiler.py&#34;   在as_sql中     1102. val.prepare_database_save(field),

     

文件   &#34; C:\用户\ echavez \ ENVS \ YEiPii \ lib中\站点包\ django的\分贝\模型\ base.py&#34;   在prepare_database_save中     999.引发ValueError(&#34;未保存的模型实例%r不能在ORM查询中使用。&#34;%self)

     

异常类型:/ user /上的ValueError异常值:未保存的模型   实例不能在ORM查询中使用。

现在我完成创建以包含嵌套的一个以及更新和删除...

谢谢LaL