Django多个用户,后端和通用视图

问题描述:

我想学习auth django系统,我有几个问题。Django多个用户,后端和通用视图

我想用电子邮件验证创建多个用户。所以,我用AbtractBaseUserAbtractBaseManager。我在网站上阅读了django doc和这个问题:Implementing multiple user types with Django 1.5

我想用它。所以,我尝试实现第二点:我的两个用户类型的所有字段都在1个模型中,并且具有user_type变量,我可以选择要显示的字段。我的代码是楼下:

models.py

# -*- coding: utf-8 -*- 

from django.db import models 
from django.conf import settings 
from django.utils.translation import ugettext_lazy as _ 
from django.contrib.auth.models import (
    BaseUserManager, AbstractBaseUser 
) 

TYPE_USER = (
    ('student', _('Student')), 
    ('employee', _('Employee')), 
) 

class MyuserManager(BaseUserManager): 
    def create_user(self, email, last_name, first_name, date_of_birth, user_type, password=None): 
     if not email: 
      raise ValueError("users must have an email address") 

     user = self.model(
      email   = self.normalize_email(email), 
      last_name  = last_name, 
      first_name = first_name, 
      date_of_birth = date_of_birth, 
      user_type  = user_type, 
     ) 

     user.set_password(password) 
     user.save() 
     return user 

    def create_superuser(self, email, password, last_name, first_name, date_of_birth, user_type): 
     user = self.create_user(email, 
      password  = password, 
      date_of_birth = date_of_birth, 
      last_name  = last_name, 
      first_name = first_name, 
      user_type  = user_type, 
     ) 
     user.is_admin = True 
     user.is_staff = True 
     user.save() 
     return user 

class MyUser(AbstractBaseUser): 
    """Based model user""" 
    email = models.EmailField(
     verbose_name = 'email', 
     max_length=255, 
     unique=True, 
    ) 
    last_name  = models.CharField(max_length=30) 
    first_name = models.CharField(max_length=30) 
    date_of_birth = models.DateField() 
    user_type  = models.CharField(_('Type'), choices=TYPE_USER, max_length=20, default='student') 
    phone   = models.CharField(max_length=20, blank=True) 
    friends  = models.ManyToManyField("self", blank=True) 
    faculty  = models.ForeignKey(Faculty, null=True, blank=True) 
    desk   = models.CharField(max_length=30, blank=True) 
    campus  = models.ForeignKey(Campus, null=True, blank=True) 
    job   = models.ForeignKey(Function, null=True, blank=True) 
    cursus  = models.ForeignKey(Cursus, null=True, blank=True) 
    year   = models.IntegerField(null=True, blank=True) 
    is_active  = models.BooleanField(default=True) 
    is_admin  = models.BooleanField(default=False) 
    is_staff  = models.BooleanField(default=False) 

    objects = MyuserManager() 
    USERNAME_FIELD = 'email' 
    REQUIRED_FIELDS = ['last_name', 'first_name', 'date_of_birth', 'user_type'] 

问:你认为这是正确的吗?或者我应该创建1类与共同领域和2类为不同类型的用户?

接下来,我想用我自己的后台,所以我实现我的项目backend.py文件

backend.py

from fbLike.models import MyUser 
from django.contrib.auth.backends import ModelBackend 


class EmailAuthBackend(ModelBackend): 
    def authenticate(self, email=None, password=None, **kwargs): 
     try: 
      user = MyUser.objects.get(email=email) 
      if user.check_password(password): 
       return user 
     except MyUser.DoesNotExist: 
      return None 

    def get_user(self, user_id): 
     try: 
      return MyUser.objects.get(pk=user_id) 
     except: 
      return None 

对于我来说,似乎是一个正确的实现。

问题:但是,如何进行多表继承?可能吗 ?如何知道什么是用户之前,检查密码类型,如果我有,例如:

class BaseUser(AbstractBaseUser): 
    email = models.EmailField(max_length=254, unique=True) 
    # common fields 


class Student(BaseUser): 
    first_name = models.CharField(max_length=30) 
    last_name = models.CharField(max_length=30) 
    # ... 


class employee(BaseUser): 
    company_name = models.CharField(max_length=100) 
    # ... 

最后,我的models.py,backend.py我会尝试使用CRUD系统在我views.py到创建和更新用户。

下面我的文件:

forms.py

class StudentProfileForm(forms.ModelForm): 
    phone = forms.CharField(required=True) 
    faculty = forms.ModelChoiceField(Faculty.objects.all()) 
    campus = forms.ModelChoiceField(Campus.objects.all()) 
    cursus = forms.ModelChoiceField(Cursus.objects.all()) 
    year = forms.IntegerField(required=True) 

    class Meta: 
     model = MyUser 
     fields = ('email', 'password', 'first_name', 'last_name', 
        'date_of_birth', 'phone', 'faculty', 'campus', 'cursus', 'year' 
     ) 
     widgets = { 
      'password': forms.PasswordInput(render_value=True), 
     } 

class EmployeeProfileForm(forms.ModelForm): 
    date_of_birth = forms.DateField(widget = AdminDateWidget) 
    phone = forms.CharField(required=True) 
    faculty = forms.ModelChoiceField(Faculty.objects.all()) 
    campus = forms.ModelChoiceField(Campus.objects.all()) 
    job = forms.ModelChoiceField(Function.objects.all()) 
    desk = forms.IntegerField(required=True) 

    class Meta: 
     model = MyUser 
     fields = ('email', 'password', 'first_name', 'last_name', 
        'date_of_birth', 'phone', 'faculty', 'campus', 'job', 'desk' 
     ) 
     widgets = { 
      'password': forms.PasswordInput(render_value=True), 
     } 

在这里,我觉得它太复杂,但我不知道如何来降低复杂性。

views.py

class RegisterProfile(CreateView): 
    model = MyUser 
    template_name = 'fbLike/user_profile.html' 
    form_class = StudentProfileForm 
    second_form_class = EmployeeProfileForm 

    def get_object(self): 
     return super(RegisterProfile, self).get_object() 

    def get_success_url(self): 
     return reverse('login',) 

    def get_context_data(self, **kwargs): 
     context = super(RegisterProfile, self).get_context_data(**kwargs) 
     if 'studenForm' not in context: 
      context['studentForm'] = self.form_class 
     if 'employeeForm' not in context: 
      context['employeeForm'] = self.second_form_class 
     return context 


    def form_valid(self, form): 
     self.object = MyUser.objects.create_user(**form) 
     return super(RegisterProfile, self).form_valid(form) 

    def form_invalid(self, form): 
     return super(RegisterProfile, self).form_invalid(form) 

    def post(self, request, *args, **kwargs): 
     self.object = None 
     if request.POST['profileType'] == 'student': 
      form = self.form_class(request.POST, prefix='st') 
      form.user_type = 'student' 
     else: 
      form = self.second_form_class(request.POST, prefix='em') 
      form.user_type = 'employee' 

     if form.is_valid(): 
      return self.form_valid(form) 
     else: 
      return self.form_invalid(form) 


class UpdateProfile(UpdateView): 
    model = MyUser 
    template_name = 'fbLike/modify_profile.html' 

    def get_form_class(self): 
     if self.request.user.user_type == 'student': 
      return StudentProfileForm 
     return EmployeeProfileForm 

    def get_success_url(self): 
     return reverse('welcome',) 

对于CreateProfile,我想向我的模板,并感谢2种形式javscript,我可以选择正确的形式。但是当我提交表单时,我有一个用户密码错误。当我在管理页面检查我的用户时,hashpassword系统似乎失败。 所以,我第一次尝试解决:它是重写我的表单中的保存方法使用request.user.set_password,但它不起作用。

我知道这是一个很长的解释。但是,每个人都可以给我一个2格式的CreateView类的例子吗?如果不可能使用一个类而是一个函数如何实现这个功能?

我感谢你在

+0

请阅读[this](http://*.com/help/dont-ask)。 –

我将尝试回答您的多个问题,但请在未来的 - 平均每个职位的一个问题。我意识到你是新手,但*不是讨论论坛,请查看帮助部分(每页底部的链接),特别是关于asking questions的部分。


我想创建多个用户使用电子邮件认证。 [012]请问 是否正确?或者我应该创建1类与共同领域 和2类为不同类型的用户?

它是正确的,如果它与你合作。这些问题更适合于codereview.stackexchange.com。特别是因为没有错误。

但是,如何进行多表继承?可能吗 ? 怎么知道什么是用户之前,检查密码类型,如果我有 例如[...]

首先,认证后端是完全不同的话题;他们没有任何关系的多表继承(我认为你的意思是关系或多个用户配置文件)。

如果您的密码验证算法对于每种用户类型都不相同,则只需要多个验证后端。如果所有用户密码都存储在相同的位置/系统/数据库中,则不需要多个身份验证后端。

您应该在您的基本用户类中实现一个方法,该方法返回用户类型。然后,您可以使用user_passes_check decorator来限制视图中的访问。

这样,您将获得什么,我想是你是什么“这一节只让学生”等之后,

最后,我的models.py,backend.py我会尝试使用CRUD系统在我的views.py中创建和更新用户[..]在这里,我认为它太复杂了,但我不知道如何减少复杂性。

您不需要在ModelForm中重复模型中的所有字段,只需要在需要修改它们的情况下覆盖字段,或向表单中添加额外的“非模型”字段。你可以用简单的ModelForm开始,像这样:

class UserForm(forms.ModelForm): 
    class Meta: 
     model = User 
     fields = ('name', 'email', 'password') 

一个常见的用途增加一个额外的领域是要求进行密码确认,将有一个额外的密码字段。

对于CreateProfile,我想向我的模板2点的形式和 感谢javscript,我可以选择正确的形式。但是,当我提交 表单时,我与用户密码有误。当我在管理页面中检查我的 用户时,hashpassword系统似乎失败。所以,我的 第一次尝试解决:它是将我的表单中的保存方法覆盖到 使用request.user.set_password,但它不起作用。

使用form wizard来实现多步注册过程。第一步,您要求创建基本信息和账户类型;在第二步中,您只发送相关表单,而不是发送两个表单,然后使用javascript切换它们。

我没有看到你的代码中的任何地方使用set_password,所以不能对第二部分进行评论。