用户管理功能
一、业务功能分析
1. 业务需求分析
用户的增删改查,权限分组的控制。
2.功能分析
- 用户列表
- 修改用户
- 删除用户
二、用户列表
1. 业务流程分析
- 接收参数
- 校验参数
- 查询数据
- 分页
2.接口设计
- 接口说明:
类目 | 说明 |
---|---|
请求方法 | GET |
url定义 | /admin/users/ |
参数格式 | 查询参数 |
- 参数说明:
参数名 | 类型 | 是否必须 | 描述 |
---|---|---|---|
username | 字符串 | 否 | 要查询的用户名 |
group | 整数 | 否 | 要查询的group_id |
is_staff | 整数 | 否 | 用户是否员工 |
is_superuser | 整数 | 否 | 父菜单id |
page | 整数 | 否 | 页码 |
-
返回数据
html
3.后端代码
-
视图
# 在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: group_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)
-
路由
# 在myadmin/urls.py中添加如下视图 path('users/', views.UsersView.as_view(), name='user_list')
4.前端代码
-
html
<!-- 创建 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 %}
-
js
// 创建static/js/myadmin/user/user.js $(() => { let $queryForm = $('form.user-query'); // 查询表单 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('服务器超时,请重试!') }) }); // 分页 给非 let $pageLi = $('ul.pagination li').not('.active').not('.disabled'); $pageLi.click(function () { let $this = $(this); $.each($queryForm.serializeArray(), function () { queryData[this.name] = this.value }); queryData['page'] = $this.data('page') $ .ajax({ url: $('.sidebar-menu li.active a').data('url'), data: queryData, type: 'GET' }) .done((res) => { $('#content').html(res) }) .fail(() => { message.showError('服务器超时,请重试!') }) }) });
三、用户详情页面
1.接口设计
- 接口说明:
类目 | 说明 |
---|---|
请求方法 | GET |
url定义 | /admin/user/<int:user_id>/ |
参数格式 | 路径参数 |
- 参数说明:
参数名 | 类型 | 是否必须 | 描述 |
---|---|---|---|
user_id | 整数 | 是 | 要查询的用户id |
-
返回数据
html
2. 后端代码
-
视图
# 在myadmin/views.py中添加如下视图 class UserUpdateView(View): """ 用户更新视图 url:/admin/user/<int:user_id> """ def get(self, request, user_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})
-
路由
# 在myadmin/urls.py中添加如下路由 path('user/<int:user_id>/', views.UserUpdateView.as_view(), name='user_update')
-
表单
# 在myadmin/forms.py中定义如下表单 class UserModelForm(forms.ModelForm): class Meta: model = User fields = ['username', 'mobile', 'is_staff', 'is_superuser', 'is_active', 'groups']
3.前端代码
-
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 %}
-
js代码
// 在 admin/user/user.js中添加如下代码 ... // 用户详情 $('tr').each(function () { $(this).children('td:first').click(function () { $('#content').load( $(this).data('url'), (response, status, xhr) => { if (status !== 'success') { message.showError('服务器超时,请重试!') } } ); }) }); ... // 注意在user_list中在相应的tr中添加data-url的属性 <td style="width: 40px" data-url="{% url 'myadmin:user_update' user.id %}">
四、修改用户
1.接口设计
- 接口说明:
类目 | 说明 |
---|---|
请求方法 | PUT |
url定义 | /admin/user/<int:user_id> |
参数格式 | 路径参数+表单参数 |
- 参数说明:
参数名 | 类型 | 是否必须 | 描述 |
---|---|---|---|
user_id | 整数 | 是 | 用户id |
username | 字符串 | 是 | 用户名 |
mobile | 字符串 | 是 | 手机号码 |
is_staff | 字符串 | 否 | 是否职员 |
is_superuser | 字符串 | 否 | 是否超级用户 |
is_active | 字符串 | 否 | 渲染图标类名 |
-
返回数据
# 添加正常返回json数据 { "errno": "0", "errmsg": "用户修改成功!" }
如果有错误,返回html表单
2.后端代码
-
视图
# 在admin/views.py中的UserUpdateView视图中添加put方法 class UserUpdateView(View): """ 用户更新视图 url:/admin/user/<int:user_id> """ def get(self, request, user_id): user = User.objects.filter(id=user_id).first() if user: form = UserModelForm(instance=user) else: form = UserModelForm() return render(request, 'admin/user/user_detail.html', context={'form': form}) def put(self, request, user_id): user = User.objects.filter(id=user_id).first() put = QueryDict(request.body) if user: form = UserModelForm(put, instance=user) else: form = UserModelForm() if form.is_valid(): form.save() return json_response() else: return render(request, 'admin/user/user_detail.html', context={'form': form})
3.前端代码
-
js
// 新建 js/admin/user/user_detail.js 注意在user_detail.html中引入 $(() => { $('.box-footer button.back').click(() => { $('#content').load( $('.sidebar-menu li.active a').data('url'), (response, status, xhr) => { if (status !== 'success') { message.showError('服务器超时,请重试!') } } ); }); $('.box-footer button.save').click(function () { $ .ajax({ url: $(this).data('url'), data: $('form').serialize(), type: 'PUT' }) .done((res) => { if (res.errno === '0') { message.showSuccess('修改用户成功!'); $('#content').load( $('.sidebar-menu li.active a').data('url'), (response, status, xhr) => { if (status !== 'success') { message.showError('服务器超时,请重试!') } } ); }else { $('#content').html(res) } }) .fail((res)=>{ message.showError('服务器超时,请重试!') }) }) });