[django项目] 后台用户管理功能

用户管理功能

用户管理功能也是我们在OA系统中最常见的, 它可以让管理员具有: 查询,修改,删除用户的能力, 那么本次我们就来实现后台功能上的用户管理功能

I. 业务功能分析

用户管理就是对用户的增删改查, 由于我们已经有了注册功能, 所以增加用户就不需要额外写出来了, 新增管理员可以直接使用命令增加

可以把更多的专注点放在其他功能(删改查)的实现上

功能分析:

  • 用户列表, 展示用户的个人信息, 并具有删除修改用户的接口
  • 修改用户, 进入到用户详情界面, 修改的数据会被应用到后台数据库
  • 删除用户, 逻辑删除, 用户的信息对我们来说是非常重要的, 不可以真删除

大数据时代, 最重要的就是用户数据

II. 用户列表

1>业务流程分析

  • 接收参数
  • 校验参数
  • 查询数据
  • 分页展示

2>接口设计

  1. 接口说明:
类目说明
请求方法GET
url定义/admin/users/
参数格式查询参数
  1. 参数说明:
参数名类型是否必须描述
username字符串要查询的用户名
group整数要查询的group_id
is_staff整数用户是否员工
is_superuser整数父菜单id
page整数页码
  1. 返回数据

    返回的是一个html页面

3>后端代码

3.1>视图
# 在myadmin/views.py下创建如下视图
class UserListView(View):
    """
    用户列表视图
    """

    def get(self, request):
        user_queryset = User.objects.only('username', 'is_active', 'mobile', 'is_staff', 'is_superuser')
        groups = Group.objects.only('name').all()
        query_dict = {}
        # 检索
        groups__id = request.GET.get('group')
        if groups__id:
            try:
                groups__id = int(groups__id)
                query_dict['groups__id'] = groups__id
            except Exception as e:
                pass

        is_staff = request.GET.get('is_staff')
        if is_staff == '0':
            query_dict['is_staff'] = False
        if is_staff == '1':
            query_dict['is_staff'] = True

        is_superuser = request.GET.get('is_superuser')
        if is_superuser == '0':
            query_dict['is_superuser'] = False
        if is_superuser == '1':
            query_dict['is_superuser'] = True

        username = request.GET.get('username')

        if username:
            query_dict['username'] = username

        try:
            page = int(request.GET.get('page', 1))
        except Exception as e:
            page = 1

        paginater = Paginator(user_queryset.filter(**query_dict), 2)

        users = paginater.get_page(page)
        context = {
            'users': users,
            'groups': groups
        }
        context.update(query_dict)
        return render(request, 'myadmin/user/user_list.html', context=context)
3.2>路由
# 在myadmin/urls.py中添加如下视图
path('users/', views.UsersView.as_view(), name='user_list')

4>前端代码

4.1>html

既然我们之前已经做过了分页, 那么就可以拿到之前在news中创建的分页过滤器来使用, 也就是page_bar

<!-- 创建 templates/myadmin/user/user_list.html 模板-->
{% extends 'admin/content_base.html' %}
{% load static %}
{% load news_customer_filters %}<!-- 加载之前的分页过滤器 -->
{% block page_header %}
    系统设置
{% endblock %}
{% block page_option %}
    用户管理
{% endblock %}
{% block content %}
    <div class="box">
        <div class="box-header with-border">
            <h3 class="box-title">用户列表</h3>
        </div>
        <!-- /.box-header -->

        <div class="box-body">
            <div style="margin-bottom: 10px">
                <form class="form-inline user-query">
                    <div class="form-group">
                        <label for="">用户名</label>
                        <input type="text" class="form-control" name="username" value="{{ username }}">
                    </div>
                    <div class="form-group">
                        <label for="">分组</label>
                        <select name="group" id="" class="form-control">
                            <option value="">所有</option>
                            {% for group in groups %}

                                <option {% if groups__id == group.id %}selected{% endif %}
                                        value="{{ group.id }}">{{ group.name }}</option>

                            {% endfor %}
                        </select>
                    </div>
                    <div class="form-group">
                        <label for="">是否员工</label>
                        <select name="is_staff" id="" class="form-control">
                            <option value="">所有</option>

                            <option {% if is_staff is True %}selected{% endif %} value="1"></option>
                            <option {% if is_staff is False %}selected{% endif %} value="0"></option>
                        </select>
                    </div>
                    <div class="form-group">
                        <label for="">是否管理员</label>
                        <select name="is_superuser" id="" class="form-control">
                            <option value="">所有</option>
                            <option {% if is_superuser is True %}selected{% endif %} value="1"></option>
                            <option {% if is_superuser is False %}selected{% endif %} value="0"></option>
                        </select>
                    </div>
                    <button type="button" class="btn btn-info query">查询</button>
                    <button type="button" class="btn btn-default reset">重置</button>
                </form>
            </div>

            <table class="table table-bordered">
                <tbody>
                <tr>
                    <th>#</th>
                    <th>用户名</th>
                    <th>电话</th>
                    <th>是否可用</th>
                    <th>是否员工</th>
                    <th>是否管理员</th>
                </tr>
                {% for user in users %}
                    <tr>
                        <td style="width: 40px"><a href="#" data-id="{{ user.id }}">{{ forloop.counter }}</a></td>
                        <td>{{ user.username }}</td>
                        <td>{{ user.mobile }}</td>
                        <td>{% if user.is_active %}是{% else %}否{% endif %}</td>
                        <td>{% if user.is_staff %}是{% else %}否{% endif %}</td>
                        <td>{% if user.is_superuser %}是{% else %}否{% endif %}</td>

                    </tr>

                {% endfor %}

                </tbody>
            </table>


        </div>
        <!-- 分页 -->
        <div class="box-footer clearfix">
            <div class="row">
                <div class="col-sm-6">
                    <div class="dataTables_info" id="example2_info" role="status" aria-live="polite">总共:{{ users.paginator.count }}条 第{{ users.start_index }}到{{ users.end_index }}条
                    </div>
                </div>
                <div class="col-sm-6">
                    <ul class="pagination pagination-sm no-margin pull-right">
                        <li {% if not users.has_previous %}class="disabled"{% endif %} data-page="{{ users.number|add:-1 }}"><a href="#">«</a></li>
                    {% for n in users|page_bar %}
                        <li {% if n == users.number %}class="active" {% endif %} data-page="{{ n }}"><a href="#">{{ n }}</a></li>
                    {% endfor %}
                        <li {% if not users.has_next %}class="disabled"{% endif %} data-page="{{ users.number|add:1 }}"><a href="#">»</a></li>
                    </ul>
                </div>
            </div>

        </div>

    </div>
{% endblock %}
{% block script %}
    <script src="{% static 'js/myadmin/user/user_list.js' %}"></script>
{% endblock %}

4.2>js
// 创建static/js/myadmin/user/user.js
$(() => {

    let $queryForm = $('form.user-query');       // 查询表单

    // 分页
    let $pageLi = $('ul.pagination li').not('.active').not('.disabled');

    $pageLi.click(function () {
        let $this = $(this);
        $
            .ajax({
                url: $('.sidebar-menu li.active a').data('url'),
                data: $queryForm.serialize() + '&page=' + $this.data('page'),
                type: 'GET'
            })
            .done((res) => {
                $('#content').html(res)
            })
            .fail(() => {
                message.showError('服务器超时,请重试!')
            })
    });

    // 查询
    let $queryBtn = $('form.user-query button.query');    // 查询按钮
    let $resetBtn = $('form.user-query button.reset');    // 重置按钮

    $queryBtn.click(() => {

        $
            .ajax({
                url: $('.sidebar-menu li.active a').data('url'),
                data: $queryForm.serialize(),
                type: 'GET'
            })
            .done((res) => {
                $('#content').html(res)
            })
            .fail(() => {
                message.showError('服务器超时,请重试!')
            })
    });

    // 重置
    $resetBtn.click(() => {
        // 让表单重置
        $queryForm[0].reset();
        $
            .ajax({
                url: $('.sidebar-menu li.active a').data('url'),
                type: 'GET'
            })
            .done((res) => {
                $('#content').html(res)
            })
            .fail(() => {
                message.showError('服务器超时,请重试!')
            })
    });
    // 用户详情
    $('tr').each(function () {
        $(this).children('td:first').click(function () {
            $('#content').load(
                $(this).data('url'),
                (response, status, xhr) => {
                    if (status !== 'success') {
                        message.showError('服务器超时,请重试!')
                    }
                }
            );
        })
    });

});

III. 用户详情页面

对用户详情页的设计是, 点击用户的序号, 就会在局部动态渲染出详情页.

1>接口设计

1.1>接口说明:
类目说明
请求方法GET
url定义/admin/user/<int:user_id>/
参数格式路径参数
1.2>参数说明:
参数名类型是否必须描述
user_id整数要查询的用户id
1.3>返回数据

html

2>后端代码

2.1>视图
# 在myadmin/views.py中添加如下视图

class UserUpdateView(View):
    """
    用户更新视图
    url:/admin/user/<int:user_id>
    """
    def get(self, request, user_id):
        # 通过id获取到指定用户对象
        user = User.objects.filter(id=user_id).first()
        if user:
            form = UserModelForm(instance=user)
        else:
            form = UserModelForm()
        return render(request, 'myadmin/user/user_detail.html', context={'form': form})
2.2>路由
# 在myadmin/urls.py中添加如下路由
path('user/<int:user_id>/', views.UserUpdateView.as_view(), name='user_update')
2.3>表单
# 在myadmin/forms.py中定义如下表单
class UserModelForm(forms.ModelForm):
    class Meta:
        model = User    # 拿到用户模型
        # 获取用户字段集
        fields = ['username', 'mobile', 'is_staff', 'is_superuser', 'is_active', 'groups']

3>前端代码

3.1>html
<!-- 新建 myadmin/user/user_detail.html 模板 -->
{% extends 'myadmin/content_base.html' %}
{% load static %}
{% load admin_customer_tags %}
{% block page_header %}
    系统设置
{% endblock %}
{% block page_option %}
    用户管理
{% endblock %}
{% block content %}
    <div class="box box-primary">
        <div class="box-header with-border">
            <h3 class="box-title">用户详情</h3>
        </div>
        <!-- /.box-header -->
        <!-- form start -->
        <div class="box-body">
            <div class="row">
                <div class="col-md-3"></div>
                <div class="col-md-6">
                    <form class="form-horizontal">
                        {% csrf_token %}

                        {% for field in form %}
                            {% if field.name in 'is_staff,is_active,is_superuser' %}
                                <div class="form-group">

                                    <div class="col-sm-offset-2 col-sm-10">

                                        <div class="checkbox">
                                            <label for="{{ field.id_for_label }}">{{ field }}{{ field.label }}</label>
                                        </div>
                                    </div>

                                </div>
                            {% else %}
                                <div class="form-group {% if field.errors %}has-error{% endif %}">

                                    <label for="{{ field.id_for_label }}"
                                           class="col-sm-2 control-label">{{ field.label }}</label>

                                    <div class="col-sm-10">
                                        {% for error in field.errors %}
                                            <label class="control-label"
                                                   for="{{ field.id_for_label }}">{{ error }}</label>
                                        {% endfor %}
                                        {% add_class field 'form-control' %}
                                    </div>
                                </div>
                            {% endif %}
                        {% endfor %}


                    </form>
                </div>
                <div class="col-md-3"></div>
            </div>
        </div>
        <div class="box-footer">

                    <button type="button" class="btn btn-default back">返回</button>
                    <button type="button" class="btn btn-primary pull-right save
                                                 " data-url="{% url 'myadmin:user_update' form.instance.id %}">保存</button>


        </div>
    </div>
{% endblock %}

写完html之后可以打开看一下:

[外链图片转存失败(img-ciwD9dEp-1567947553459)(django%E9%A1%B9%E7%9B%AE-%E5%90%8E%E5%8F%B0%E7%AE%A1%E7%90%86.assets/1567685861533.png)]

3.2>js代码

但是这个页面还是有点问题, 当我们点返回的时候没有响应(保存到后面再说), 那么我们就要使用js来解决这个问题

// 创建myadmin/user/user_detail.js中并添加如下代码
$(() => {
    // 1. 点击返回
    // 回到用户列表页面,触发点击用户管理菜单
    $('.box-footer button.back').click(() => {
        $('#content').load(
            $('.sidebar-menu li.active a').data('url'),
            (response, status, xhr) => {
                if (status !== 'success') {
                    message.showError('服务器超时,请重试!')
                }
            }
        );
    });
    
});

记得在user_detail.html中, 引用

{% block script %}
    <script src="{% static 'js/myadmin/user/user_detail.js'%}"></script>
{% endblock %}

写代码, 写一步调试一步, 有个循序渐进的过程

IIII. 修改用户

1>接口设计

  1. 接口说明:
类目说明
请求方法PUT
url定义/admin/user/<int:user_id>
参数格式路径参数+表单参数
  1. 参数说明:
参数名类型是否必须描述
user_id整数用户id
username字符串用户名
mobile字符串手机号码
is_staff字符串是否职员
is_superuser字符串是否超级用户
is_active字符串渲染图标类名
  1. 返回数据

    # 添加正常返回json数据
    {
    "errno": "0",
    "errmsg": "用户修改成功!"
    }
    

    如果有错误,返回html表单

2>后端代码

2.1>视图
# 在admin/views.py中的UserUpdateView视图中添加put方法
class UserUpdateView(View):
    """
    用户更新视图
    url:/admin/user/<int:user_id>
    """
    def get(self, request, user_id):
        # 通过id获取到指定用户对象
        user = User.objects.filter(id=user_id).first()
        if user:
            form = UserModelForm(instance=user)
        else:
            return json_response(errno=Code.NODATA, errmsg='没有此用户!')
        return render(request, 'myadmin/user/user_detail.html', context={'form': form})

    def put(self, request, user_id):
        # 1. 拿到要修改的用户对象
        user = User.objects.filter(id=user_id).filter()
        # 1.1 判断用户是否存在
        if not user:
            return json_response(errno=Code.NODATA, errmsg='没有此用户!')
        # 2. 拿到前端传递的函数
        put_data = QueryDict(request.body)
        # 3. 校验参数
        # 3.1 创建表单对象
        form = UserModelForm(put_data, instance=user)
        # `UserModelForm`第一个参数接收页面数据, 第二个参数放上用户标识,用来寻找用户.
        # 找到后会自动比对不同的地方并修改
        if form.is_valid():
            # 4. 如果成功, 保存数据
            form.save()
            return json_response(errmsg='用户修改成功!')
        else:
            # 5. 若不成功, 返回渲染了错误信息的表单页面
            return render(request, 'myadmin/user/user_detail.html', context={'form': form})

3>前端代码

3.1>js
// 新建 js/admin/user/user_detail.js 注意在user_detail.html中引入
$(() => {
    // 1. 点击返回
    // 回到用户列表页面,触发点击用户管理菜单
    $('.box-footer button.back').click(() => {
        $('#content').load(
            $('.sidebar-menu li.active a').data('url'),
            (response, status, xhr) => {
                if (status !== 'success') {
                    message.showError('服务器超时,请重试!')
                }
            }
        );
    });
    // 2. 点击保存
    $('.box-footer button.save').click(function () {
        // 发送ajax
        $
            .ajax({
                url: $(this).data('url'),
                data: $('form').serialize(), // 可以拿到当前页面表单的数据,会自动拼接
                type: 'PUT'
            })
            .done((res) => {
                if (res.errno === '0') {
                    // 等于0说明发送成功, 显示消息
                    message.showSuccess(res.errmsg);
                    // 然后跳转到用户列表
                    $('#content').load(
                        $('.sidebar-menu li.active a').data('url'),
                        (response, status, xhr) => {
                            if (status !== 'success') {
                                message.showError('服务器超时,请重试!')
                            }
                        }
                    );
                } else {
                    // 发送失败就替换为渲染了错误信息的html
                    $('#content').html(res)
                }
            })
            .fail(() => {
                message.showError('服务器超时,请重试!')
            })
    })
});

注意新增的js代码要在前端模板user_detail.html中引用

{% block script %}
    <script src="{% static 'js/myadmin/user/user_detail.js'%}"></script>
{% endblock %}

用户管理的功能到此为止, 之后我们带大家来研究编写权限分组的方法

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值