基于Django的员工管理系统2

1.编辑用户(基于modelform)

  • 点击编辑,跳转到编辑界面(将编辑行的id携带过去)

  • 编辑页面(默认数据,根据id获取并设置页面中)

  • 提交:错误提示,数据校验,在数据库更新

urls.py

path('user//edit/', views.user_edit),

views.py

def user_edit(request, nid):
    """ 基于modelform版本的用户编辑 """
    row_object = UserInfo.objects.filter(id=nid).first()
    if request.method == 'GET':
        # 根据id去数据库去获取要编辑的那一行的数据
        form = UserModelForm(instance=row_object)
        return render(request, "user_edit.html", {'form': form})
    # 使用post提交数据,数据校验
    form = UserModelForm(data=request.POST, instance=row_object)
    if form.is_valid():
        form.save()
        return redirect('/user/list/')
    # 校验失败,在页面显示错误信息
    return render(request, 'user_edit.html', {'form': form})

user_edit.html

{% extends 'layout.html'%}

{% block content %}
     
编辑用户
{% csrf_token %} {% for field in form %}
{{ field }} {{ field.errors.0 }}
{% endfor %}
{% endblock %}

2.删除用户

urls.py

path('user//delete/', views.user_delete),

views.py

def user_delete(request, nid):
    UserInfo.objects.filter(id=nid).delete()
    return redirect('/user/list/')

3.靓号管理

3.1创建表结构

models.py

class PrettyNum(models.Model):
    """ 靓号表 """
    mobile = models.CharField(verbose_name='手机号', max_length=11)
    price = models.DecimalField(verbose_name='价格', max_digits=10, decimal_places=2, default=0)
    level_choice = (
        (1, '1级'),
        (2, '2级'),
        (3, '3级'),
        (4, '4级')
    )
    level = models.SmallIntegerField(verbose_name='等级', choices=level_choice, default=1)
    status_choice = (
        (1, '已占用'),
        (2, '未占用')
    )
    status = models.SmallIntegerField(verbose_name='状态', choices=status_choice, default=2)
    

创建一些数据

 mysql -u root -p 
use db2;
insert into app01_prettynum(mobile, price, level, status) values('11111111111', 19, 1, 1);

3.2靓号列表

urls.py

path('num/list/', views.num_list),

views.py

{% extends 'layout.html' %}

{% block content %}
    
{#
#} {# Panel content#} {#
#} {% for obj in data_list %} {% endfor %}
ID 电话号 价格 等级 状态 操作
{{ obj.id }} {{ obj.mobile }} {{ obj.price }} {{ obj.get_level_display }} {{ obj.get_status_display }} 编辑 删除
{% endblock %}

num_list.html

{% extends 'layout.html' %}

{% block content %}
    
{#
#} {# Panel content#} {#
#} {% for obj in data_list %} {% endfor %}
ID 电话号 价格 等级 状态 操作
{{ obj.id }} {{ obj.mobile }} {{ obj.price }} {{ obj.get_level_display }} {{ obj.get_status_display }} 编辑 删除
{% endblock %}

3.3新建靓号

  • 列表点击【添加靓号】跳转到/num/add/

  • 创建NumModel类

  • def num_add函数:

  • GET:示例化类的对象,通过render将对象传入html中,使用模板循环显示所有的字段。

  • POST:点击提交,数据校验,保存到数据库,跳转到/num/list/

urls.py

path('num/add/', views.num_add),

views.py

from django.core.validators import RegexValidator, ValidationError


class NumModelForm(forms.ModelForm):
    # 验证方式1
    mobile = forms.CharField(
        label='手机号',
        validators=[RegexValidator(r'^1[3-9]\d{9}$', '手机号格式错误')]
    )

    class Meta:
        model = PrettyNum
        # fields = ['mobile', 'price', 'level', 'status']
        # 排除某些字段
        # exclude = ['level']
        # 展示全部字段
        fields = "__all__"

    def __init__(self, *args, **kwarg):
        super().__init__(*args, **kwarg)
        for num, field in self.fields.items():
            # 循环找到所有的插件
            field.widget.attrs = {'class': 'form-control', 'placeholder': field.label}

    # 验证方式2
    def clean_mobile(self):
        txt_mobile = self.cleaned_data['mobile']
        exists = PrettyNum.objects.filter(mobile=txt_mobile).exists()
        if exists:
            raise ValidationError("手机号已存在")
        return txt_mobile

num_add.html

{% extends 'layout.html' %}

{% block content %}
    
新建靓号
{% csrf_token %} {% for field in form %}
{{ field }} {{ field.errors.0 }}
{% endfor %}
{% endblock %}

3.4编辑靓号

  • num_list.html添加:href="/num/{{ obj.id }}/edit/"

  • urls.py添加:path('num//edit/', views.num_edit),

  • 创建NumEditModelForm类(不允许编辑手机号)

  • num_edit函数

  • GET:根据id获取当前编辑的对象

  • POST:提交修改

urls.py

path('num//edit/', views.num_edit),

views.py

class NumEditModelForm(forms.ModelForm):
    # 不允许修改手机号
    mobile = forms.CharField(disabled=True, label='手机号')

    class Meta:
        model = PrettyNum
        fields = ['mobile', "price", "level", "status"]

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        for name, field in self.fields.items():
            field.widget.attrs = {'class': "form-control", "placeholder": field.label}


def num_edit(request, nid):
    """ 靓号编辑 ModelForm """
    row_object = PrettyNum.objects.filter(id=nid).first()
    if request.method == "GET":
        form = NumEditModelForm(instance=row_object)
        return render(request, "num_edit.html", {"form": form})

    form = NumEditModelForm(data=request.POST, instance=row_object)
    if form.is_valid():
        form.save()
        return redirect('/num/list/')
    return render(request, 'num_edit.html', {'form': form})

num_edit.html

{% extends 'layout.html'%}

{% block content %}
     
编辑靓号
{% csrf_token %} {% for field in form %}
{{ field }} {{ field.errors.0 }}
{% endfor %}
{% endblock %}
  • 如果此时,允许修改电话号码(即删除mobile = forms.CharField(disabled=True, label='手机号')这一句),此时如何验证手机号码和数据库里的其他数据不重复呢?还是在类NumEditModelForm里写一个函数clean_mobile()

class NumEditModelForm(forms.ModelForm):
    # 不允许修改手机号
    # mobile = forms.CharField(disabled=True, label='手机号')

    class Meta:
        model = PrettyNum
        fields = ['mobile', "price", "level", "status"]

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        for name, field in self.fields.items():
            field.widget.attrs = {'class': "form-control", "placeholder": field.label}
    
    def clean_mobile(self):
        # 当前编辑的一行数据的id
        print(self.instance.pk)
        txt_mobile = self.cleaned_data['mobile']
        exists = PrettyNum.objects.exclude(id=self.instance.pk).filter(mobile=txt_mobile).exists()
        if exists:
            raise ValidationError("手机号已存在")
        return txt_mobile

3.5删除靓号

urls.py

path('num//delete/', views.num_delete),

views.py


def num_delete(request, nid):
    PrettyNum.objects.filter(id=nid).delete()
    return redirect('/num/list/')

3.6搜索电话号码

views.py

def num_list(request):
    """ 靓号列表 """
    data_dict = {}
    search_data = request.GET.get("q", "")
    if search_data:
        data_dict["mobile__contains"] = search_data
    # 去数据库中获取所有的靓号列表(降序排列)
    queryset = PrettyNum.objects.filter(**data_dict).order_by("-level")
    return render(request, 'num_list.html', {"data_list": queryset, "search_data": search_data})

num_list.html

{% extends 'layout.html' %}

{% block content %}
    
{#
#} {# Panel content#} {#
#} {% for obj in data_list %} {% endfor %}
ID 电话号 价格 等级 状态 操作
{{ obj.id }} {{ obj.mobile }} {{ obj.price }} {{ obj.get_level_display }} {{ obj.get_status_display }} 编辑 删除
{% endblock %}

4.分页

基本逻辑

queryset = PrettyNum.objects.filter(id=1)[0:10]
# 第一页
queryset = PrettyNum.objects.all()[0:10]
# 第二页
queryset = PrettyNum.objects.all()[10:20]
# 第三页
queryset = PrettyNum.objects.all()[20:30]
# 那么分页可以这样写
page_size = 10
page = int(request.GET.get('page'))
start = (page - 1) * page_size
end = page * page_size
queryset = PrettyNum.objects.all()[start:end]

views.py

def num_list(request):
    """ 靓号列表 """
    # for i in range(300):
    #     PrettyNum.objects.create(mobile='18188888818', price=10, level=1, status=1)
    page_size = 10
    page = int(request.GET.get('page', 1))
    start = (page - 1) * page_size
    end = page * page_size
    total_count = PrettyNum.objects.all().count()
    total_page = math.ceil(total_count / page_size)
    # 页码,显示当前页的前5页和后5页
    """
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • """ plus = 5 if total_page <= 2 * plus + 1: # 总页面太少 start_page = 1 end_page = total_page else: # 总页面很多 # 但是当前page total_page: start_page = total_page - 2 * plus end_page = total_page else: start_page = page - plus end_page = page + plus page_str_list = [] # 上一页 if page > 1: prev = '
  • previous
  • '.format(page - 1) else: prev = '
  • previous
  • '.format(1) page_str_list.append(prev) for i in range(start_page, end_page + 1): if i == page: ele = '
  • {}
  • '.format(i, i) else: ele = '
  • {}
  • '.format(i, i) page_str_list.append(ele) # 下一页 if page < total_page: nex = '
  • next
  • '.format(page + 1) else: nex = '
  • next
  • '.format(total_page) page_str_list.append(nex) page_string = mark_safe("".join(page_str_list)) data_dict = {} search_data = request.GET.get("q", "") if search_data: data_dict["mobile__contains"] = search_data # 去数据库中获取所有的靓号列表(降序排列) queryset = PrettyNum.objects.filter(**data_dict).order_by("-level")[start:end] return render(request, 'num_list.html', {"data_list": queryset, "search_data": search_data, 'page_string': page_string})

    num_list.html

    {% extends 'layout.html' %}
    
    {% block content %}
        
    {#
    #} {# Panel content#} {#
    #} {% for obj in data_list %} {% endfor %}
    ID 电话号 价格 等级 状态 操作
    {{ obj.id }} {{ obj.mobile }} {{ obj.price }} {{ obj.get_level_display }} {{ obj.get_status_display }} 编辑 删除
      {{ page_string }}
    {% endblock %}
    基于Django的员工管理系统2_第1张图片

    分页组件的分装

    Pagination.py

    """
    自定义的分页组件,以后如果想要使用这个分页组件,你需要做如下几件事:
    在视图函数文件views.py中:
        def num_list(request):
            # 1.根据自己的情况去筛选自己的数据
            queryset = PrettyNum.objects.all()
            # 2.实例化分页对象
            page_object = Pagination(request, queryset)
    
            context = {
                "data_list": page_object.page_queryset,  # 分完页的数据
                'page_string': page_object.html(),  # 生成的页码
            }
    
            return render(request, 'num_list.html', context)
    在html文件中:
        {% for obj in data_list %}
            {{ obj.xx }}
        {% endfor %}
        
      {{ page_string }}
    """ import math from django.utils.safestring import mark_safe class Pagination(object): def __init__(self, request, queryset, page_param='page', page_size=10, plus=5): """ :param request: 请求对象 :param queryset: 符合对象的数据(根据这个数据进行分页处理) :param page_param: 在url中传递获取分页的参数,例如/num/list/?page=12 :param page_size: 每页显示多少数据 :param plus: 显示当前页的前几页或后几页 """ import copy query_dict = copy.deepcopy(request.GET) query_dict._mutable = True self.query_dict = query_dict self.page_param = page_param page = request.GET.get(page_param, "1") if page.isdecimal(): page = int(page) else: page = 1 # print(page) self.page = page self.page_size = page_size self.plus = plus self.start = (self.page - 1) * self.page_size self.end = self.page * self.page_size self.page_queryset = queryset[self.start:self.end] total_count = queryset.count() # 总页码 self.total_page = math.ceil(total_count / self.page_size) def html(self): # 页码,显示当前页的前5页和后5页 if self.total_page <= 2 * self.plus + 1: # 总页面太少 start_page = 1 end_page = self.total_page else: # 总页面很多 # 但是当前page self.total_page: start_page = self.total_page - 2 * self.plus end_page = self.total_page else: start_page = self.page - self.plus end_page = self.page + self.plus page_str_list = [] # 首页 self.query_dict.setlist(self.page_param, [1]) page_str_list.append('
  • 首页
  • '.format(self.query_dict.urlencode())) # 上一页 if self.page > 1: self.query_dict.setlist(self.page_param, [self.page - 1]) prev = '
  • 上一页
  • '.format(self.query_dict.urlencode()) else: self.query_dict.setlist(self.page_param, [1]) prev = '
  • 上一页
  • '.format(self.query_dict.urlencode()) page_str_list.append(prev) for i in range(start_page, end_page + 1): self.query_dict.setlist(self.page_param, [i]) if i == self.page: ele = '
  • {}
  • '.format(self.query_dict.urlencode(), i) else: ele = '
  • {}
  • '.format(self.query_dict.urlencode(), i) page_str_list.append(ele) # 下一页 if self.page < self.total_page: self.query_dict.setlist(self.page_param, [self.page + 1]) nex = '
  • next
  • '.format(self.query_dict.urlencode()) else: self.query_dict.setlist(self.page_param, [self.total_page]) nex = '
  • next
  • '.format(self.query_dict.urlencode()) page_str_list.append(nex) # 尾页 self.query_dict.setlist(self.page_param, [self.total_page]) page_str_list.append('
  • 尾页
  • '.format(self.query_dict.urlencode())) search_string = """
  • """ page_str_list.append(search_string) page_string = mark_safe("".join(page_str_list)) return page_string

    views.py

    def num_list(request):
        """ 靓号列表 """
        data_dict = {}
        search_data = request.GET.get("q", "")
        if search_data:
            data_dict["mobile__contains"] = search_data
        # 去数据库中获取所有的靓号列表(降序排列)
        queryset = PrettyNum.objects.filter(**data_dict).order_by("-level")
        page_object = Pagination(request, queryset)
    
        context = {
            "search_data": search_data,
            "data_list": page_object.page_queryset,  # 分完页的数据
            'page_string': page_object.html(),  # 生成的页码
        }
    
        return render(request, 'num_list.html', context)

    num_list.html

    {% extends 'layout.html' %}
    
    {% block content %}
        
    {#
    #} {# Panel content#} {#
    #} {% for obj in data_list %} {% endfor %}
    ID 电话号 价格 等级 状态 操作
    {{ obj.id }} {{ obj.mobile }} {{ obj.price }} {{ obj.get_level_display }} {{ obj.get_status_display }} 编辑 删除
      {{ page_string }}
    {% endblock %}

    5.modelform中的时间插件

    在layout.html中在如下位置添加两行

    {% block css %}{% endblock %}
    {% block js %}{% endblock %}
    基于Django的员工管理系统2_第2张图片
    基于Django的员工管理系统2_第3张图片

    在user_model_form_add.html中添加如下内容

    {% block css %}
        
    {% endblock %}
    
    {% block js %}
    
    
    
    
    
    {% endblock %}

    就可以实现ModelForm的时间选择插件了。

    6.modelForm和Bootstrap

    写一个BootstrapModelForm类,让其他的ModelForm继承

    class BootstrapModelForm(forms.ModelForm):
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
            # 循环找到所有的插件,给每个字段的插件设置
            for name, field in self.fields.items():
                # 字段中有属性,保留原来的属性,每有属性,才增加
                if field.widget.attrs:
                    field.widget.attrs['class'] = "form-control"
                    field.widget.attrs['placeholder'] = field.label
                else:
                    field.widget.attrs = {'class': 'form-control', 'placeholder': field.label}

    7.优化

    在app01目录下创建views文件夹,文件夹内分别创建depart.py,user.py,prettynum.py,将views.py里的内容根据功能复制到相应的文件中,最后删除views.py文件,然后修改urls.py文件里的路径。

    你可能感兴趣的:(前端,django,python,后端)