zoukankan      html  css  js  c++  java
  • django中使用Profile扩展User模块(基于django 1.10版本下)

    版本:Django 1.10.1(其他版本可能有不同的实现好解决办法)

    参考官方文档:https://docs.djangoproject.com/en/1.10/topics/auth/customizing/

    在开发过程中,Django的用户管理模块能够给我们带来非常大的便利,但是Django的User模块所提供的字段太少,所以对User模块的扩展是必须的,下面结合我自己的开发过程中,使用Profile扩展User模块时遇到的问题以及解决的方法进行记录。

    先看一段我根据官方文档最先开发完成的代码:

    admin.py

    from django.contrib import admin
    from django.contrib.auth.models import User
    from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
    
    from models import *
    
    class AccountInline(admin.StackedInline):
        model = Account
        can_delete = False
        verbose_name_plural = 'account'
        
    
    class UserAdmin(BaseUserAdmin):
        inlines = (AccountInline, )
    
    
    admin.site.unregister(User)
    admin.site.register(User, UserAdmin)
    

    model.py:

    from __future__ import unicode_literals
    
    from mysite import settings
    from django.db import models
    from django.contrib.auth.models import User
    from django.db.models.signals import post_save
    
    
    class Account(models.Model):
        """
        Registered users
        """
        SEX_CHOICES = {
            1: 'boy',
            2: 'girl',
        }
        
        user = models.OneToOneField(User, on_delete=models.CASCADE)
        sex = models.SmallIntegerField(default=1, choices=SEX_CHOICES.items())
        birth = models.DateField(blank=True, null=True)
        age = models.SmallIntegerField(blank=True,null=True)
        contact_number = models.CharField(max_length=128, blank=True, null=True)
        personalized_signature = models.CharField(max_length=128, blank=True, null=True)
        picture = models.ImageField(upload_to="Image/", blank=True,null=True)
        openid = models.CharField(max_length=128, blank=True, null=True)
            
        def __unicode__(self):
            return self.user.username
        
        class Meta:
            db_table = 'Account'
    
    def create_user_profile(sender, instance, created, **kwargs):
        if created:
            profile = Account()
            profile.user = instance
            profile.save()
            
    post_save.connect(create_user_profile, sender=User)
    

    settings.py:

    INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        'rest_framework',
        'Blog'
    ]
    AUTH_PROFILE_MODULE = 'Blog.Account'

    这段是官方文档给出的参考方法:可以很好的让你自己的model跟User模块进行一对一的外键映射。

    我们可以通过admin页面进行用户的创建,可以看到我们的Account模型很好的嵌入了User模块,然后可以对User模块进行字段的扩张。

    但是此时,当你保存的时候,出现了问题,请看截图:

    这个问题告诉我(仅仅是我的理解,如果有错误希望留言提出),当django创建完User表中的用户时,通过Userprofile去创建第二个实例(Account)的时候,执行save操作的时候,执行了俩次,从而导致上面的user_id已经存在无法完成操作,这个原因在于:上面model中调用post_save发生了俩次(django自己的save一次,然后通过信号post_save一次,导致第二个调用save的时候发现已经存在了相同的主键ID)

    所以我们需要做的就是对model.py文件中的save进行重写,重写之后的model.py文件为:

    class Account(models.Model):
        """
        Registered users
        """
        SEX_CHOICES = {
            1: 'boy',
            2: 'girl',
        }
        
        user = models.OneToOneField(User, on_delete=models.CASCADE)
        sex = models.SmallIntegerField(default=1, choices=SEX_CHOICES.items())
        birth = models.DateField(blank=True, null=True)
        age = models.SmallIntegerField(blank=True,null=True)
        contact_number = models.CharField(max_length=128, blank=True, null=True)
        personalized_signature = models.CharField(max_length=128, blank=True, null=True)
        picture = models.ImageField(upload_to="Image/", blank=True,null=True)
        openid = models.CharField(max_length=128, blank=True, null=True)
            
        def __unicode__(self):
            return self.user.username
        
        class Meta:
            db_table = 'Account'
    
        def save(self, *args, **kwargs):
            if not self.pk:
                try:
                    p = Account.objects.get(user=self.user)
                    self.pk = p.pk
                except Account.DoesNotExist:
                    pass
    
            super(Account, self).save(*args, **kwargs)
    
    
    def create_user_profile(sender, instance, created, **kwargs):
        if created:
            profile = Account()
            profile.user = instance
            profile.save()
            
    post_save.connect(create_user_profile, sender=User)
    

    这样就会在save创建的时候,对主键pk进行检测然后保存。

    因为我在开发的时候用到了django-rest-framework,所以含有serializer序列化文件,在这里一并给出:

    serializers.py:

    class UserSerializer(serializers.ModelSerializer):
        class Meta:
            model = User
            fields = ("id", "username", "password", "email", "last_login", "date_joined")
    
    
    class AccountSerializer(serializers.ModelSerializer):
        class Meta:
            model = Account
            fields = ("user_id", "user", "sex", "age", "birth", "picture", "contact_number", "personalized_signature", "openid")
    

      

  • 相关阅读:
    css 设置特定条件下的标签
    vue实现导航菜单滚动
    input 默认样式样式 样式修改
    vue 倒计时
    微信小程序 botton默认样式删除
    Notepad++ 快捷键
    css实现div水平垂直居中
    Python爬虫爬取1905电影网视频电影并存储到mysql数据库
    Python爬虫爬取搜狐视频电影并存储到mysql数据库
    第一阶段(十)
  • 原文地址:https://www.cnblogs.com/ShaunChen/p/6159996.html
Copyright © 2011-2022 走看看