Django设计问题:扩展用户模型以创建不能登录的用户

3
我正在处理的网站涉及教师创建学生对象。教师可以选择让学生登录网站(查看日历等),或者仅将学生对象用于记录,不允许学生登录。在学生创建表单中,如果教师提供用户名和密码,则应创建第一种类型的对象-可以登录的常规用户对象。如果教师没有提供用户名/密码,则应创建第二种类型。另一个要求是,教师应该能够随后更改非登录学生为其他类型。如何设计这种情况最好?子类化User并使用户名和密码不是必需的吗?这还会影响什么?
编辑:我最终使用了User.set_unusable_password()。以下是代码-我省略了我在视图中还使用的其他表单等:
class StudentForm(forms.ModelForm):
    username = forms.RegexField(regex=r'^\w+$',
                                required=False,
                                max_length=30,
                                label=("Username"),
                                error_messages={ 'invalid': ("This value must contain only letters, numbers and underscores.") })
    password = forms.CharField(widget=forms.PasswordInput(),
                                    label="Password", required=False)

    class Meta:
        model = User
        fields = ('first_name', 'last_name', 'username', 'email', 'password')

请注意,表单中不需要填写用户名和密码。 查看
def create_student(request):
    if request.method == "POST":
        student_form = StudentForm(request.POST)
        if student_form.is_valid():
            user = student_form.save(commit=False)
            if student_form.cleaned_data['username'] == '':
                user.username = generate_random_username()
                user.set_unusable_password()
            else:
                user.set_password(user.password)
            user.save()

            return HttpResponseRedirect(reverse('student_list', args=['active']))

    #GET an empty form
    else:
        student_form = StudentForm()

return render_to_response('priviostudio/create_student.html', {
    'student_form': student_form,
})

在编辑学生的视图中(这可能与创建学生的视图合并),我使用以下代码进行GET请求:

student_form_initial = {
        'username': user_instance.username if user_instance.has_usable_password() else '',
        'password': user_instance.password if user_instance.has_usable_password() else '',
    }
    student_form = StudentForm(instance=user_instance, initial=student_form_initial)

在POST请求中,如果老师提交了一个新的用户名和有效的密码,我将只是将它们设置在用户实例上。

感谢大家提供的想法。

4个回答

3

认证应用程序的User模型有一个set_unusable_password方法;这个方法可以满足您的需求,而不需要扩展模型。


问题在于我还必须生成一个随机的用户名(因为用户名具有unique=True属性且不具备blank=True属性),这个用户名也会显示在表单上,可能会让老师们感到困惑。 - UrLicht

2
Django默认的用户模型具有一个is_active字段。

http://docs.djangoproject.com/en/dev/topics/auth/#django.contrib.auth.models.User.is_active

您可能想使用这个。
这样,当老师决定让用户能够登录时,您的代码将只是将学生用户设置为is_active=True,反之亦然。
此外,根据上面链接的文档,Django的默认身份验证表单和权限方法会检查is_active标志,因此这部分工作已经为您完成了一些。
您可能还需要为学生生成一个用户名,但如果提供了名称,可以使用slug轻松完成。
对我来说区分学生和教师最明显的方法就是分组,Django也提供了相应的机制。

1
你可以考虑将所有学生都作为一种对象,而不是用户,然后在老师允许学生登录的情况下,补充该模型与用户对象。这两个模型对象的组合可以相对清晰地解决你想要的问题。

这似乎是一个不错的方法,但表格可能会变得有些混乱。我去尝试一下。 - UrLicht
我在这方面遇到了麻烦:我仍然想在用户(User)上使用first_name,last_name和email。以这种方式做将需要在非User对象中保留该数据并将它们同步。 - UrLicht

0
我会避免对用户进行子类化。相反,您可能希望创建一个自定义的身份验证器,以便您可以检查组成员资格以实现登录功能。
"""
DummyBackend.py

"""

from django.contrib.auth.models import User, check_password
from django.contrib.auth.backends import RemoteUserBackend
from lecture_feedback.daily.models import Student
class DummyBackend(RemoteUserBackend):
    """
    Dummy authentication module that takes a username and password. The password must match the username.
    """

    def authenticate(self, username=None, password=None):
        """
        The username passed as ``remote_user`` is considered trusted.  This
        method simply returns the ``User`` object with the given username,
        creating a new ``User`` object if ``create_unknown_user`` is ``True``.

        Returns None if ``create_unknown_user`` is ``False`` and a ``User``
        object with the given username is not found in the database.

        """

        try:
            student = Student.objects.get(globalid=username)
        except Student.DoesNotExist:
            return None

        if username != password:
            return
        user = None

        # Note that this could be accomplished in one try-except clause, but
        # instead we use get_or_create when creating unknown users since it has
        # built-in safeguards for multiple threads.
        if self.create_unknown_user:
            user, created = User.objects.get_or_create(username=username)
            if created:
                user = self.configure_user(user)
        else:
            try:
                user = User.objects.get(username=username)
            except User.DoesNotExist:
                pass
        return user


    def configure_user(self, user):
         """
         Configures a user after creation and returns the updated user.

         By default, returns the user unmodified.
         """
         student = Student.objects.get(globalid=user.username)
         user.first_name = student.first_name
         user.last_name = student.last_name
         return user

学生模型可以包含一个字段,指示该学生是否被允许登录。 还可以查看http://docs.djangoproject.com/en/dev/howto/auth-remote-user/#attributes


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接