Django身份验证 - 在注册时修改现有用户

时间:2013-09-05 21:39:31

标签: django django-models django-authentication django-allauth

我正在使用django构建照片共享网站,允许用户创建分享照片的群组。我在创建适当的用户数据模型/逻辑方面遇到了问题,这些模型/逻

基本要求是:

  • 允许用户A创建一个他可以添加其他用户的组(用户B)
  • 如果必须添加到该组的用户B已经存在,那么我们将使用此现有用户B添加到代表该组的组模型的manytomany字段中
  • 如果用户B不存在,我们将创建一种" dummy"用户。将user_active设置为false。这是因为用户B尚未设置任何类型的验证或密码。

现在,如果新添加的用户B想要注册到站点,而不是创建新用户,我想用注册表单中提供的数据更改现有用户。

我想提一下,我计划将django-allauth用于社交帐户用户。

我的问题(考虑到Django 1.5)是如何使其发挥作用的首选方式:

这是我应该创建自己的用户管理器还是应该查看身份验证后端?我此时真的迷失了。


下面的图表代表了两种情况,注册和添加用户到组:

http://i821.photobucket.com/albums/zz136/jorge_sanchez4/f79934d4-d0a4-4862-ab8b-7e1d09cd5642_zps06ec08f3.jpg


更新:

所以我试着跟随,创建了自定义用户模型,在__new__方法中,如果相关对象已经存在并且is_active设置为False,则返回相关对象。以下是UserManager和用户模型:



class GruppuUserManager(BaseUserManager):
    def create_user(self, username, email=None, password=None, phonenumber=None, **extra_fields):
        now = timezone.now()
        if not username:
            raise ValueError('The given username must be set')

        if not phonenumber:
            raise ValueError('The given phonenumber must be set')
        ''' now lookup the user if it exists and is_active is set
                then it is duplicate, otherwise return the user
                and set the is_active to true '''

        email = self.normalize_email(email)
        if GruppUser.objects.filter(phonenumber__exact=phonenumber).exists():
            if GruppUser.objects.filter(phonenumber__exact=phonenumber).values('is_active'):
                ''' duplicate - raise error '''
                raise ValueError('The user is duplicate ')
            else:
                ''' get the subscriber and set all the values '''
                user = GruppUser.objects.filter(phonenumber__exact=phonenumber)
                user.set_password(password)
                user.is_active=True
                if email:
                    user.email = email
                user.save(using=self._db)
                return user

        user = self.model(username=username, email=email,
                  is_staff=False, is_active=True, is_superuser=False,
                  last_login=now, date_joined=now, phonenumber=phonenumber, **extra_fields)
        user.set_password(password)
        user.save(using=self._db)
        return user


    def create_superuser(self, username, email=None, password=None, phonenumber=None, **extra_fields):
        u = self.create_user(username, email, password, phonenumber, **extra_fields)
        u.is_staff = True
        u.is_active = True
        u.is_superuser = True
        u.save(using=self._db)
        return u



class GruppUser(AbstractBaseUser, PermissionsMixin):
    ''' django 1.5 - creating custom user model '''
    id = models.AutoField(primary_key=True)
    username = models.CharField(_('username'), max_length=30, unique=True,
            help_text=_('Required. 30 characters or fewer. Letters, numbers and '
                    '@/./+/-/_ characters'),
            validators=[
                    validators.RegexValidator(re.compile('^[\w.@+-]+$'), _('Enter a valid username.'), 'invalid')
            ])
    first_name = models.CharField(_('first name'), max_length=30, blank=True)
    last_name = models.CharField(_('last name'), max_length=30, blank=True)
    email = models.EmailField(_('email address'), blank=True)
    is_staff = models.BooleanField(_('staff status'), default=False,
            help_text=_('Designates whether the user can log into this admin '
                    'site.'))
    is_active = models.BooleanField(_('active'), default=True,
            help_text=_('Designates whether this user should be treated as '
                    'active. Unselect this instead of deleting accounts.'))
    date_joined = models.DateTimeField(_('date joined'), default=timezone.now)
    phonenumber = models.CharField(max_length=10)
    #following = models.ManyToManyField(Stream,blank=True,null=True)
    blocked_con = models.ManyToManyField(Blocked_Content,blank=True,null=True)
    mmsemail  = models.EmailField(_('email address'), blank=True)
    smsemail  = models.EmailField(_('email address'), blank=True)
    verified  = models.BooleanField(_('verified'), default=False,
            help_text=_('Defines if the user has been verified'))



    objects = GruppuUserManager()

    USERNAME_FIELD = 'username'
    REQUIRED_FIELDS = ['phonenumber']

    class Meta:
        verbose_name = _('user')
        verbose_name_plural = _('users')

    def __init__(self,phone=None,*args, **kwargs):
        ''' save the phone number '''
        super(GruppUser,self).__init__(*args, **kwargs)
        self.phonetocheck = phone

    @staticmethod
    def __new__(cls,phone=None,*args, **kwargs):
        ''' lookup for the same user '''
        if GruppUser.objects.filter(phonenumber__exact=phone).exists():
            if self.objects.filter(phonenumber__exact=phone).values('is_active'):
                ''' duplicate - raise error '''
                raise ValueError('The user is duplicate')
            else:
                ''' get the subscriber and set all the values '''
                user = self.objects.filter(phonenumber__exact=phone)
                user.is_active = True
                return user

        return super(GruppUser,cls).__new__(cls,*args, **kwargs)


    def get_full_name(self):
        """
        Returns the first_name plus the last_name, with a space in between.
        """
        full_name = '%s %s' % (self.first_name, self.last_name)
        return full_name.strip()

    def get_short_name(self):
        "Returns the short name for the user."
        return self.first_name

    def email_user(self, subject, message, from_email=None):
        """
        Sends an email to this User.
        """
        send_mail(subject, message, from_email, [self.email])





无论如何,我现在遇到的一个奇怪问题是我无法连接到管理网站,这会给我以下错误:

我已经跟踪了django,似乎查询集以某种方式向左移动:

    (Pdb) context[self.user].phonenumber
     u''
    (Pdb) context[self.user].date_joined
     u'9135261969'
    (Pdb) context[self.user].is_active
    datetime.datetime(2013, 9, 8, 20, 47, 30, tzinfo=<UTC>)

但是mysql中的数据是正确的:

    mysql> select is_active from demo_app_gruppuser;
    +-----------+
    | is_active |
    +-----------+
    |         1 |
    +-----------+
    1 row in set (0.00 sec)

    mysql> select phonenumber from demo_app_gruppuser;
    +-------------+
    | phonenumber |
    +-------------+
    | 9135261969  |
    +-------------+
    1 row in set (0.00 sec)


    mysql> select date_joined from demo_app_gruppuser;
    +---------------------+
    | date_joined         |
    +---------------------+
    | 2013-09-08 20:47:30 |
    +---------------------+
    1 row in set (0.00 sec)

以下是尝试登录管理员时的回溯:

      20.             context[self.varname] = LogEntry.objects.filter(user__id__exact=user_id).select_related('content_type', 'user')[:int(self.limit)]
    File "/usr/site/gruppe/lib/python2.7/site-packages/django/db/models/manager.py" in filter
      155.         return self.get_query_set().filter(*args, **kwargs)
    File "/usr/site/gruppe/lib/python2.7/site-packages/django/db/models/query.py" in filter
      667.         return self._filter_or_exclude(False, *args, **kwargs)
    File "/usr/site/gruppe/lib/python2.7/site-packages/django/db/models/query.py" in _filter_or_exclude
      685.             clone.query.add_q(Q(*args, **kwargs))
    File "/usr/site/gruppe/lib/python2.7/site-packages/django/db/models/sql/query.py" in add_q
      1259.                             can_reuse=used_aliases, force_having=force_having)
    File "/usr/site/gruppe/lib/python2.7/site-packages/django/db/models/sql/query.py" in add_filter
      1190.                 connector)
    File "/usr/site/gruppe/lib/python2.7/site-packages/django/db/models/sql/where.py" in add
      71.             value = obj.prepare(lookup_type, value)
    File "/usr/site/gruppe/lib/python2.7/site-packages/django/db/models/sql/where.py" in prepare
      339.             return self.field.get_prep_lookup(lookup_type, value)
    File "/usr/site/gruppe/lib/python2.7/site-packages/django/db/models/fields/__init__.py" in get_prep_lookup
      322.             return self.get_prep_value(value)
    File "/usr/site/gruppe/lib/python2.7/site-packages/django/db/models/fields/__init__.py" in get_prep_value
      555.         return int(value)

    Exception Type: ValueError at /admin/
    Exception Value: invalid literal for int() with base 10: 'root'

同样在pdb中有趣的是self.user.id应该在这种情况下1返回&#34; root&#34;背部。似乎django搞砸了我的pk在这个模型中的含义,即使我在模型中指定了它:

    id = models.AutoField(primary_key=True)

1 个答案:

答案 0 :(得分:0)

事实证明在Django模型上使用__new__方法并不是一个好主意,使用模型管理器create_user正常工作。