Django-Admin与auth认证

什么是 django自带的admin系统

  • Django 最强大的部分之一是自动生成的Admin 界面。它读取模型数据来提供一个强大的、生产环境就绪的界面,使内容提供者能立即用它向站点中添加内容。
  • 它可以快速的开发出一个后台管理界面

如何开启admin系统

  1. 确保在settings.py中的INSTALLED_APPS安装了'django.contrib.admin'
  2. INSTALLED_APPS中添加了四个依赖的app
    django.contrib.auth
    django.contrib.contenttypes
    django.contrib.messages
    django.contrib.sessions
    Django-Admin与auth认证_第1张图片
    image.png
  3. 在模板上下文中添加以下依赖
    django.contrib.auth.context_processors.authdjango.contrib.messages.context_processors.messages
    Django-Admin与auth认证_第2张图片
    image.png
  4. 在中间件中添加以下依赖django.contrib.auth.middleware.AuthenticationMiddlewaredjango.contrib.messages.middleware.MessageMiddleware
    Django-Admin与auth认证_第3张图片
    image.png
  5. 运行命令python manage.py createsuperuser创建一个超级用户,然后输入超级用户的用户名和密码。创建的用户是保存在auth_user表中
  6. 使用该命令创建的用户是一个超级管理员用户,它拥有所有的权限,需要妥善保管
    Django-Admin与auth认证_第4张图片
    image.png
  7. 如果没有通过migrate,需要先同步migrate
  8. 在浏览器中输入127.0.0.1:8000/admin/进入admin登录界面。输入刚刚创建的用户名和密码,进入admin管理界面。
  9. admin 界面默认是英文,如需要修改成中文,修改settings中的属性,

    ps: 控制这个语言展示的模块叫i18n,i18n实际就是国际化,就代表支持多种语言的功能
    image.png

    界面效果图:
    Django-Admin与auth认证_第5张图片
    image.png

    Django-Admin与auth认证_第6张图片
    image.png

自定义admin:

  • 把需要管理的模型添加到admin中:
    首先要在INSTALLED_APPS中添加对应的应用,然后在应用的admin.py中注册,有2中方法注册,方法二常用
 方法一:
class ArticleAdmin(admin.ModelAdmin):
    pass
admin.site.register(Article, ArticleAdmin)
方法二:
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.contrib import admin
from .models import *
# Register your models here.
@admin.register(Classesnumber)
class ClassesnumberAuth(admin.ModelAdmin):
    pass
  • 修改app显示名称:
    Django-Admin与auth认证_第7张图片
    image.png

    所有跟app相关的内容配置,可以实现一个Appconfig类的子类来完成,django一般会默认在apps.py中建立一个
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.apps import AppConfig
class TestappConfig(AppConfig):
    name = 'TestApp'
  • 然后在apps.py对应的子类中配置verbose_name
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.apps import AppConfig
class TestappConfig(AppConfig):
    name = 'TestApp'
    verbose_name = u'练习项目'
  • 我们只需要指定一下即可,需要管理的__init__.py中配置如下:
from .apps import *
default_app_config = 'TestApp.apps.TestappConfig'
Django-Admin与auth认证_第8张图片
image.png
  • 修改模型显示的名称:
    设置model中的元属性即可
 class Meta:
        verbose_name = u"班号"
        verbose_name_plural = u"班号列表"

效果:

Django-Admin与auth认证_第9张图片
image.png

Django-Admin与auth认证_第10张图片
image.png

注意:要有数据 verbose_name才展示出来,否则显示的是复数形式。

  • 修改模型列表的展示:
    models.py中对应类添加一个__unicode__方法(py3中使用的是__str__),返回需要展示的字符串(注意需要返回字符串,否则Python将抛出一个TypeError 错误,并提示:”coercing to Unicode: need string or buffer, int found” ),如把 return self.id 改为return str(self.s_id)或者返回name
    比如要展示班级名称:
#`models.py
    def __unicode__(self):
        return self.name
Django-Admin与auth认证_第11张图片
image.png
  • 修改展示的列表项,即模型中其他字段内容,可以在admin.py中用 list_display修改展示的列表项
#admin.py
@admin.register(Classesgrade)
class ClassesgradeAuth(admin.ModelAdmin):
    list_display = ['name', 'create_time', 'update_time', 'number']
Django-Admin与auth认证_第12张图片
image.png
  • Admin类管理
    list_display:可以修改展示的列表项
    search_fields:可以提供搜索的查找项
    list_filter:可以提供一个过滤的表
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.contrib import admin
from .models import *

# Register your models here.
@admin.register(Classesnumber)
class ClassesnumberAuth(admin.ModelAdmin):
    pass

@admin.register(Classesgrade)
class ClassesgradeAuth(admin.ModelAdmin):
    list_display = ['id','name', 'create_time', 'update_time', 'number']
    #提供搜索的查找项(模糊搜索),几个则是或or的关系
    search_fields = ['id','name']
    #提供一个过滤的表,如果多个,则且and的关系
    list_filter = ['id','name']

Django-Admin与auth认证_第13张图片
image.png

注意:list_display不支持多对多的,需要处理下:/

#admin.py
@admin.register(Student)
class StudentAuth(admin.ModelAdmin):
    #list_display不能显示多对多的
    list_display = ('id', 'name', 'age', 'sex', 'classesno','teachers_list')

    #然后自己定义个字段名来代替teacher在teachers_list中显示即可。因为待会我们要写一个同名方法来获取teacher的里的值。
    def teachers_list(self,obj):
        return [a.name for a in obj.teacher.all()] #获取老师所有对象,然后再迭代获取对应名称组成列表
    teachers_list.short_description = u'老师'
    # filter_horizontal = ['teacher']# filter_horizontal是用来编辑状态下的teacher页面的。

Django-Admin与auth认证_第14张图片
image.png

search_fields,在使用 Django admin 系统中的搜索时可能会出现“related Field has invalid lookup: icontains”错误,主要原因是外键查询是需要指定相应的字段的。外键不应该只是一个model,而该是另一个表的明确的一个字段。所以我们需要指定特定的字段 "本表外键字段__外键所在表需查询字段"。

  • 更多操作:
    参考文档:
    https://docs.djangoproject.com/en/1.11/ref/contrib/admin/
    https://yiyibooks.cn/xx/Django_1.11.6/ref/contrib/admin/index.html

  • 其它:
    在admin操作后台的时候,如果选择多对多对象,需要ctrl+ 鼠标点击完全多选。

auth系统:

  1. auth系统是django内置一个的一个app,它是专门用于管理用户权限的一个组件;
  2. 创建一个用户:from django.contrib.auth.models import User,然后使用create_user来创建一个用户。
from django.contrib.auth.models import User

User.objects.create_user(**kwargs)
  • 验证用户
from django.contrib.auth import authenticate
#authenticate接受两个参数,用户名 username 和 密码 password ,并在密码对给出的用户名合法的情况下返回一个 User 对象,如果密码不合法。authenticate()返回None。
user = authenticate(username='john', password='secret')
if user is not None:
   # 这个用户存在数据库中
else:
   # 用户名或者密码错误
  • 登录
        from django.contrib.auth import authenticate, login

        def post(self, request):
            username = request.POST['username']
            password = request.POST['password']
            user = authenticate(username=username, password=password)
            if user is not None:
#authenticate() 只是验证一个用户的证书而已。而要登录一个用户,使用 login() 。该函数接受一个 HttpRequest 对象和一个 User 对象作为参数并使用Django的会话( session )框架把用户的ID保存在该会话中。
                login(request, user)
                    # 登录成功
            else:
                # 用户名或者密码错误
  • 注销
 from django.contrib.auth import logout
     def get(self, request)
           logout(request)  # 当执行完logout,实际就是清除了session中的user信息
#它接受一个HttpRequest对象并且没有返回值,所以,因为没有返回值,需要返回一个页面。
  • 登录验证
from django.contrib.auth.mixins import LoginRequiredMixin

class Show(LoginRequiredMixin, View):
        login_url = "/account/login/" #如果没有登录成功,则跳转至内部定义的login_url,否则会跳转到`settings.LOGIN_URL`指定的URL中。即先找内部再找外部
#注意登录验证是用于一些只有登录了才能看的到的页面,但是可能存在一些直接输入url也可以看到这个页面,
#只不过没对应值而已,这样是不安全的,所以在进入这些页面前需要进行验证,以避免直接输入url的情况,
#如果验证已经登录成功的则进入对应页面,没有则通过使用LoginRequiredMixin来实现与login_required相同的行为,#如果没有登录成功,则跳转至内部定义的login_url,否则会跳转到`settings.LOGIN_URL`指定的URL中。即先找内部再找外部
  • 修改密码,即找回密码
from django.contrib.auth.models import User
u = User.objects.get(username='john') #获取对象
u.set_password('new password') #保存可以用u.password = make_password(new password)
u.save()  #保存
User模型常用属性和方法:

username:用户名。
email:邮箱。
groups:多对多的组。
user_permissions:多对多的用户权限。
is_staff: 指明这个用户是否可以进入管理站点。
is_active: 是否激活,判断该用户是否可用。
is_superuser: 是否是超级用户。
last_login: 上次登录时间。
date_joined: 注册时间。
is_authenticated: 是否验证通过了。
is_anonymous:是否是匿名用户。
set_password(raw_password): 设置密码,传原生密码进去。
check_password(raw_password): 检查密码。
has_perm(perm): 判断用户是否有某个权限。
has_perms(perm_list): 判断用户是否有权限列表中的某个列表。

  • Permission权限:
    1.在模型中添加,需要控制权限的模型中添加权限,即通过这些权限,能做什么事情:
class Task(models.Model):
            class Meta:
                permissions = (
                    ("view_task", "查看任务权限"),
                    ("change_task_status", "修改任务权限"),
                    ("close_task", "关闭任务权限"),
                )

2.在代码中添加权限

        from myapp.models import BlogPost
        from django.contrib.auth.models import Permission
        from django.contrib.contenttypes.models import ContentType
        
        content_type = ContentType.objects.get_for_model(BlogPost)
        permission = Permission.objects.create(
            codename='can_publish',
            name='Can Publish Posts',
            content_type=content_type, #必填。一个指向django_content_type数据库表,对于每一个Django模型,在这个表里面都有一个记录对应。
        )

一般在模型中增加,毕竟只有那么一次

  • 给用户赋相应权限
    1.代码中:
permission = Permission.objects.get(name=u'查看商品信息')#对应auth_permission表中
myuser.user_permissions.set([permission_list])                           # 设置一个权限列表
myuser.user_permissions.add(permission, permission, ...)          # 添加一个权限
myuser.user_permissions.remove(permission, permission, ...)    # 删除多个权限
myuser.user_permissions.clear()                                                  # 清理所有权限
# 以上操作都需要save,因为他们都是一个数据库操作
myuser.has_perm('foo.add_bar'
  1. 后台管理系统中
    Django-Admin与auth认证_第15张图片
    image.png
  • 权限验证
from django.contrib.auth.mixins import PermissionRequiredMixin
class MyView(PermissionRequiredMixin, View):
    # 单个权限
    permission_required = 'polls.can_vote'  
  # 多个权限,且的关系
    permission_required = ('polls.can_open', 'polls.can_edit')
  • Group模型:
  1. 所属包django.contrib.auth.models.Group
  2. 创建Group:必须传一个name参数进去。
  3. Group`操作:
group.permissions.set([permission_list])                                     # 设置这个组包含的权限列表
group.permissions.add(permission, permission, ...)                    # 添加一个权限到这个组
group.permissions.remove(permission, permission, ...)              # 从这个组中删除一个权限
group.permissions.clear()                                                            # 清理这个组的权限

myuser.groups.set([group_list])                           # 设置一些组
myuser.groups.add(group, group, ...)                  # 添加某些组
myuser.groups.remove(group, group, ...)            # 删除某些组
myuser.groups.clear()                                          # 清理所有租

一般情况下,我们都不会手工添加对应的权限,都会通过models配置对应的权限

学以致用
  1. 使用django的auth组件,完成登录、注册、注销页面;
  2. 使用auth组件的权限,添加一个主页,主页展示商品列表,并设置一个权限才能访问;
  3. 使用admin组件,添加商品列表的数据;
  • 需求分析
    需要使用Django的auth组件,则不要单独建立user模型,使用自带的组件进行操作就可以了。
  • forms.py建立注册表单类,其中名称,价格,商品详细信息:
# -*- coding: utf-8 -*-
from django import forms
from django.contrib.auth.models import User

class RegisterForm(forms.Form):
    userName = forms.CharField(label=u'用户名',min_length = 3,max_length = 20)
    userPassword = forms.CharField(label=u'登录密码',min_length= 6,max_length = 20,error_messages = {'min_length':u'密码至少6位','max_length':u'密码最长20位'})
    userConfirmPassword = forms.CharField(label=u'确认密码',min_length = 6,max_length = 20,error_messages = {'min_length':u'密码至少6位','max_length':u'密码最长20位'})
    userEmail = forms.EmailField(label=u'邮箱')

    def clean_userName(self):
        userName = self.cleaned_data['userName']
        user = User.objects.filter(username = userName)
        if user:
            raise forms.ValidationError(u'用户名已存在')
        return userName

    def clean_userConfirmPassword(self):
        userPassword = self.cleaned_data['userConfirmPassword']
        userConfirmPassword = self.cleaned_data['userConfirmPassword']
        if userPassword != userConfirmPassword:
            raise forms.ValidationError(u'两次密码不一致')
        return userPassword


class ResetPasswordForm(forms.Form):
    userName = forms.CharField(label=u'用户名',min_length = 3,max_length = 20)
    userPassword = forms.CharField(label=u'登录密码', min_length=6, max_length=20,error_messages={'min_length': u'密码至少6位', 'max_length': u'密码最长20位'})
    userConfirmPassword = forms.CharField(label=u'确认密码',min_length = 6,max_length = 20,error_messages = {'min_length':u'密码至少6位','max_length':u'密码最长20位'})

    def clean_userName(self):
        userName = self.cleaned_data['userName']
        user = User.objects.filter(username = userName)
        print(user)
        if not user:
            raise forms.ValidationError(u'用户名不存在')
        return userName


    def clean_userConfirmPassword(self):
        userPassword = self.cleaned_data['userPassword']
        userConfirmPassword = self.cleaned_data['userConfirmPassword']
        print(userPassword,userConfirmPassword)

        if userPassword != userConfirmPassword:
            raise forms.ValidationError(u'两次密码不一致')
        return userPassword

注册页面sign_up.html效果:

Django-Admin与auth认证_第16张图片
image.png

注册成功效果:
Django-Admin与auth认证_第17张图片
image.png

登录页面 sign_in.html效果:
Django-Admin与auth认证_第18张图片
image.png

登录成功,跳转到首页 index.html
Django-Admin与auth认证_第19张图片
image.png

访问主页 home.html
Django-Admin与auth认证_第20张图片
image.png

具有添加权限的页面:
Django-Admin与auth认证_第21张图片
image.png

添加商品 addProduct.html,成功之后返回商品展示页面:
Django-Admin与auth认证_第22张图片
image.png

注销退出,返回登录界面:
Django-Admin与auth认证_第23张图片
image.png

找回密码 resetpassword.html,成功之后返回登录界面:
Django-Admin与auth认证_第24张图片
image.png

  • urls.py:
# -*- coding:utf-8 -*-

from django.conf.urls import url,include
from auth_study import views

urlpatterns = [
    url(r'^register/$', views.Register.as_view(),name='register'),
    url(r'^login/$',views.Login.as_view(),name='login'),
    url(r'^index/$',views.Index.as_view(),name='index'),
    url(r'^logout/$',views.Logout.as_view(),name='logout'),
    url(r'^resetpassword/$',views.ResetPassword.as_view(),name='resetpassword'),
    url(r'^home/$', views.Home.as_view(), name='home'),
    url(r'^addProduct/$', views.AddProduct.as_view(), name='addProduct')
]
  • 视图views.py:
# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.shortcuts import render,redirect,reverse

from django.contrib.auth.models import User,Permission
from django.views import View
from .forms import *
from django.http import HttpResponse
from django.contrib.auth import authenticate,login,logout
from django.contrib.auth.mixins import LoginRequiredMixin,PermissionRequiredMixin
from .models import Product
import TestApp
from TestApp.models import *

# Create your views here.

#注册功能
class Register(View):

    def get(self,request):
        return render(request,'sign_up.html')

    def post(self,request):
        form = RegisterForm(request.POST)
        print(form.is_bound)

        if form.is_valid():
            userName = form.cleaned_data['userName']
            userPassword = form.cleaned_data['userPassword']
            userConfirmPassword = form.cleaned_data['userConfirmPassword']
            userEmail = form.cleaned_data['userEmail']
            #create_user可以由Django自动将密码加密,而create还需要先将密码自己加密再给
            user = User.objects.create_user(username=userName,email=userEmail,password=userPassword)
            #给用户添加权限,多对多关系,用add添加
            user.user_permissions.add(Permission.objects.get(codename='view_products'))
            user.save() #需要save,因为他们都是一个数据库操作

            return HttpResponse(u'注册成功,请返回登录')
        else:

            return render(request,'sign_up.html',locals())

#登录功能
class Login(View):
    def get(self,request):
        return render(request,'sign_in.html')

    def post(self,request):
        userName = request.POST.get('userName')
        userPassword = request.POST.get('userPassword')
        print(userName,userPassword)
        #验证用户,它接受两个参数,用户名 username 和 密码 password,认证只有是否激活跟用户名密码。
        user = authenticate(username = userName,password = userPassword)
        #并在密码对给出的用户名合法的情况下返回一个 User 对象。 如果密码不合法,authenticate()返回None。
        if user is not None:
            if user.is_active:
                #登录,向session中添加SESSION_KEY, 便于对用户进行跟踪:
                login(request,user)
                # 如果调用login方法以后,
                # request对象就会激活user属性,这个属性不管登录或者未登录都是存在
                return redirect(reverse('index'))
            else:
                message = u'该用户未激活'
        else:
            message = u'用户名或密码错误'

        return render(request,'sign_in.html',locals())

class Index(LoginRequiredMixin,View): #登录验证,主要用于比如说直接输入地址情况。
    # 如果需要指定单独的跳转,则该类中指定login_url属性
    # 如果需要指定全局的,则在settings中指定LOGIN_URL属性
    login_url = '/auth/login/'#没有登录则指定跳转
    def get(self,request):
        print(request.COOKIES)
        return render(request, 'index.html', locals())

#注销功能
class Logout(View):
    def get(self,request):
        #注销用户,这个方法就会把我们的session跟cookie清理掉
        logout(request)
        message = u'注销成功'
        return render(request,'sign_in.html',locals())

#重置密码
class ResetPassword(View):
    def get(self,request):
        return render(request,'resetpassword.html')

    def post(self,request):
        form = ResetPasswordForm(request.POST)
        if form.is_valid():
            username = form.cleaned_data['userName']
            userPassword = form.cleaned_data['userPassword']
            user = User.objects.get(username=username)
            print(user)
            if user:
                user.set_password(userPassword)
                user.save()
                return render(request, 'sign_in.html', locals())

        return render(request, 'resetpassword.html', locals())

#展示主页
class Home(PermissionRequiredMixin,View):
    #单个权限
    permission_required = 'auth_study.view_products'
    #多个权限,要同时具有,且的关系,元祖或列表都可
    # permission_required = ['auth_study.view_products','auth_study.update_products']
    #上面个相当于全局的,只有满足了上面权限中的一个就可以进入下面的get了,否则就跳转到setting配置的LOGIN_URL去了
    def get(self,request):
        print('get...',request.user.user_permissions.all())
        #has_perm(perm): 判断用户是否有某个权限。
        #has_perms(perm_list): 判断用户是否有权限列表中的某个列表。
        if request.user.has_perm('auth_study.view_products'):
            products = Product.objects.all()
            if request.user.has_perm('auth_study.add_products'):
                canAdd = True   #判断有没有添加权限,然后置为True,页面去判断是否显示相关
        else:
            message = '没有查看商品的权限'
        return render(request,'home.html',locals())

#添加商品
class AddProduct(View):
    def get(self,request):
        return render(request,'addProduct.html')

    def post(self,request):
        print('post')
        name = request.POST.get('username')
        price = request.POST.get('price')
        detail = request.POST.get('detail')
        print(name,price,detail)
        product = Product.objects.create(name = name,price = price,detail= detail)
        if product:
            return HttpResponse('添加商品成功')

        return HttpResponse('添加商品失败')
  • 页面html:
#注册页面sign_up.html



    
    注册界面


注册

{% csrf_token %} 用 户 名: 登录密码: 确认密码: 邮 箱:
{{ form.errors }}
#登录页面sign_in.html



    
    登录界面


   {{ message }}

登录

{% csrf_token %} 用 户 名: 登录密码:
找回密码
#首页页面index.html



    
    首页
    


欢迎{{user.username}}  {{user.email}}  {{user.is_authenticated}}登录成功!
主页 退出
#主页home.html



    
    查看老师信息


{{user.username}}主页

{% for product in products %}

名称:{{ product.name }}
详细信息:{{product.detail}}
价格:{{product.price}}

{% endfor %} {{ message }} {% if canAdd %} 添加商品 {% endif %}
#添加商品addPruduct.html



    
    添加商品


{% csrf_token %} 名称: 价格: 详细信息:
#找回密码resetpassword.html



    
    找回密码


找回密码

{% csrf_token %} 用 户 名: 重置密码: 确认密码:
{{form.errors}}

你可能感兴趣的:(Django-Admin与auth认证)