0

我正在用 django 建立一个照片共享站点,允许用户创建组来共享照片。我在创建一个合适的用户数据模型/逻辑来满足我的所有要求时遇到问题。

基本要求是:

  • 允许用户 A 创建一个组,他可以在其中添加其他用户(用户 B)
  • 如果必须添加到组的用户 B 已经存在,那么我们将使用这个现有的用户 B 添加到代表组的组模型的 manytomany 字段
  • 如果用户 B 不存在,我们将创建一种“虚拟”用户。将 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 和 user 模型:



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 正在返回“root”。似乎 django 以某种方式弄乱了我的 pk 在这个模型中的内容,即使我在模型中指定了它:

    id = models.AutoField(primary_key=True)
4

1 回答 1

0

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

于 2013-09-09T19:47:08.513 回答