Django实战项目-学习任务系统-兑换物品管理

发布时间 2023-10-31 15:15:05作者: PandaCode辉

接着上期代码框架,开发第5个功能,兑换物品管理,再增加一个学习兑换物品表,主要用来维护兑换物品,所需积分,物品状态等信息,还有一个积分流水表,完成任务奖励积分,兑换物品消耗积分。

要想激励一个人的学习动力,最好能有实际的奖励,完成任务后,系统应给予一定的奖励,如积分或实际物品等。

目前系统考虑使用积分奖励,然后这些积分积累多了就可以兑换实际物品,这些奖励可以激励用户持续学习。

第一步:编写第5个功能-兑换物品管理

1,编辑模型文件:

./mysite/study_system/models.py:

class StudyExchangeItem(models.Model):
    item_id = models.AutoField(primary_key=True, verbose_name='兑换物品ID')
    item_name = models.CharField(max_length=200, verbose_name='兑换物品名称', blank=True)
    item_points = models.IntegerField(verbose_name='兑换积分数')
    item_description = models.TextField(verbose_name='兑换物品描述', blank=True)
    item_status = models.CharField(max_length=20, verbose_name='兑换物品状态:0-未兑换, 1-已兑换')
    created_time = models.DateTimeField(verbose_name='创建时间')
    update_time = models.DateTimeField(verbose_name='更新时间')
    created_by = models.ForeignKey(StudyUser, on_delete=models.CASCADE, verbose_name='创建者ID')

    class Meta:
        verbose_name = '兑换物品表'
        verbose_name_plural = '兑换物品表'
        # 用于模型的数据库表的名称
        db_table = "study_exchange_items"

    def __str__(self):
        return self.item_name

class StudyPoint(models.Model):
    point_id = models.IntegerField(primary_key=True, verbose_name='积分ID,使用任务ID或物品ID')
    user_id = models.ForeignKey(StudyUser, on_delete=models.CASCADE, verbose_name='用户ID')
    point_type = models.IntegerField(verbose_name='积分类型')
    points_nums = models.IntegerField(verbose_name='积分数')
    point_name = models.CharField(max_length=200, verbose_name='积分说明')
    created_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)

    class Meta:
        verbose_name = '积分流水表'
        verbose_name_plural = '积分流水表'
        # 用于模型的数据库表的名称
        db_table = "study_points"

    def __str__(self):
        return self.point_name


2,编辑urls配置文件:
./mysite/study_system/urls.py

# 兑换物品管理url
path('item/getExchangeItemList/', views.getExchangeItemList, name='getExchangeItemList'),
path('item/toNewExchangeItem/', views.toNewExchangeItem, name='toNewExchangeItem'),
path('item/addExchangeItem/', views.addExchangeItem, name='addExchangeItem'),
path('item/exchangeItem/', views.exchangeItem, name='exchangeItem'),


3,编辑视图文件:
./mysite/study_system/views.py

def getExchangeItemList(request):
    '''
    @方法名称: 获取兑换物品列表
    @作    者: PandaCode辉
    @weixin公众号: PandaCode辉
    @创建时间: 2023-10-10
    '''
    # 响应容器
    rsp_dict = {}
    # 获取当前用户名
    username = request.session.get('username')
    # 根据用户名获取用户对象
    cur_user = StudyUser.objects.get(username=username)
    print('根据用户名查询用户对象:' + str(cur_user))

    user_list = [cur_user]
    # 如果当前用户是:3-学生,则查找对应辅导员用户
    if cur_user.role == 3:
        parent_id = cur_user.parent_id
        # 根据用户ID获取用户对象
        parent_user = StudyUser.objects.get(user_id=parent_id)
        print('根据用户ID获取用户对象:' + str(parent_user))
        user_list = [cur_user, parent_user]
    # 获取待完成任务列表,限制发布人
    data_list = StudyExchangeItem.objects.filter(created_by__in=user_list).order_by('-pk')
    
    rsp_dict['data_list'] = data_list

    context_object_name = "exchange_item_list"
    template_name = "study_system/home.html"
    rsp_dict['html_file'] = 'study_system/item/exchangeItemList.html'
    rsp_dict['context_object_name'] = context_object_name

    return render(request, template_name, rsp_dict)


def toNewExchangeItem(request):
    '''
    @方法名称: 跳转到新增兑换物品视图
    @作    者: PandaCode辉
    @weixin公众号: PandaCode辉
    @创建时间: 2023-10-10
    '''
    rsp_dict = {}
    rsp_dict["pageTitle"] = "新增兑换物品"
    rsp_dict['html_file'] = 'study_system/item/addExchangeItem.html'

    return render(request, "study_system/home.html", rsp_dict)


def addExchangeItem(request):
    '''
    @方法名称: ajax请求, 表单视图,新增兑换物品
    @作    者: PandaCode辉
    @weixin公众号: PandaCode辉
    @创建时间: 2023-10-10
    '''
    # 初始化响应容器
    rsp_dict = {"result": "error", "errorMsg": "系统错误"}
    # 是否ajax请求
    if request.is_ajax():
        try:
            rest = request.POST
            item_name = rest['itemName']
            item_points = int(rest['itemPoints'])
            item_description = rest['itemDescription']
            item_status = rest['itemStatus']
            # 获取当前用户名
            username = request.session.get('username')
            # 根据用户名获取用户对象
            cur_user = StudyUser.objects.get(username=username)
            print('根据用户名查询用户对象:' + str(cur_user))
            # 创建者ID,使用 StudyUser 对象赋值
            created_by = cur_user

            # 今天
            # UTC格式当前时区时间
            t = time.localtime()
            work_date = time.strftime("%Y-%m-%d %H:%M:%S", t)
            print('当前日期时间:' + str(work_date))

            # 创建对象并保存到数据库
            studyExchangeItem = StudyExchangeItem(item_name=item_name, item_points=item_points,
                                                  item_description=item_description, item_status=item_status,
                                                  created_time=work_date, update_time=work_date,
                                                  created_by=created_by)
            # 保存到数据库是否成功
            studyExchangeItem.save()
            rsp_dict["result"] = "success"
        except Exception as e:
            rsp_dict["errorMsg"] = "新增兑换物品保存到数据库失败."

    # 成功与否都返回json数据格式
    return JsonResponse(rsp_dict)

 

兑换物品,更新物品状态,同时添加消耗积分流水。

 

def exchangeItem(request):
    '''
    @方法名称: ajax请求, 表单视图,更新兑换物品-已兑换
    @作    者: PandaCode辉
    @weixin公众号: PandaCode辉
    @创建时间: 2023-10-10
    '''
    # 初始化响应容器
    rsp_dict = {"result": "error", "errorMsg": "系统错误"}
    # 是否ajax请求
    if request.is_ajax():
        try:
            rest = request.GET
            item_id = int(rest['itemId'])

            # 获取当前用户名
            username = request.session.get('username')
            # 根据用户名获取用户对象
            cur_user = StudyUser.objects.get(username=username)
            print('根据用户名查询用户对象:' + str(cur_user))
            # 学生用户总积分值,需要取学生用户,关联的属性表的值
            studyUserAttribute = StudyUserAttribute.objects.filter(user_id=cur_user)
            total_points = studyUserAttribute[0].total_points
            print("学生用户总积分值:" + str(total_points))

            # 根据ID查询对象数据, filter 返回的是列表对象,一个对象取list.0
            studyExchangeItem = StudyExchangeItem.objects.filter(item_id=item_id)
            item_name = studyExchangeItem[0].item_name
            item_points = studyExchangeItem[0].item_points
            print("兑换物品所需积分值:" + str(item_points))
            # 比较 用户总积分值 是否大于等于 兑换物品所需积分值
            if int(total_points) >= int(item_points):
                # 今天
                # UTC格式当前时区时间
                t = time.localtime()
                work_date = time.strftime("%Y-%m-%d %H:%M:%S", t)
                print('当前日期时间:' + str(work_date))
                # 兑换积分数
                points_nums = 0 - int(item_points)
                # 插入 积分流水表
                # 积分ID, 使用任务ID或物品ID
                point_id = item_id
                # 用户ID
                user_id = cur_user
                # 积分类型,1-奖励, 0-兑换, 2-处罚
                point_type = 0
                # 积分说明,任务名或兑换物品名
                point_name = item_name
                # 创建对象并保存到数据库
                studyPoint = StudyPoint(point_id=point_id, user_id=user_id,
                                        point_type=point_type, points_nums=points_nums,
                                        point_name=point_name, created_time=work_date)
                # 保存到数据库是否成功
                studyPoint.save()

                # 更新兑换物品表数据状态:1-已兑换
                studyExchangeItem.update(item_status='1', update_time=work_date)

                # 更新属性表,总积分值数
                total_points = int(total_points) - int(item_points)
                studyUserAttribute.update(total_points=total_points, update_time=work_date)

                rsp_dict["result"] = "success"
            else:
                rsp_dict["errorMsg"] = "兑换物品失败,用户总积分值不足!"
        except Exception as e:
            rsp_dict["errorMsg"] = "更新兑换物品,保存到数据库失败."

    # 成功与否都返回json数据格式
    return JsonResponse(rsp_dict)

 

 

4,编辑页面模板代码:

4.1. 兑换物品列表页面
./mysite/study_system/templates/study_system/item/exchangeItemList.html

<script type="text/javascript">
    //兑换物品
    function exchangeItem(itemId) {
        //alert(itemId);
        $.get("/study_system/item/exchangeItem?itemId=" + itemId, function (data) {
            if ("success" == data.result) {
                alert("兑换成功");
                window.location.reload();
            } else {
                alert("兑换失败:" + data.errorMsg);
            }
        });
    }
</script>
{% if request.session.role == 1 or request.session.role == 2  or request.session.role == 4 %}
    {# 【角色 :1-系统管理员 】#}
    {# 【角色 :2-辅导员 】#}
    {# 【角色 :4-自导自学 】#}
    <div>
        <a href="/study_system/item/toNewExchangeItem/" class="btn btn-default btn-lg btn-block btn-a"
           style="color: #EC5F13;">新增兑换物品</a>
    </div>
{% endif %}
<!-- 结果显示区 -->
<div id="dataList">
    {% if data_list %}
        {% for exchangeItem in data_list %}
            <ul class="dataCardList">
                {% if request.session.role == 1 or request.session.role == 2 or request.session.role == 4 %}
                    {# 【角色 :1-系统管理员 】#}
                    {# 【角色 :2-辅导员 】#}
                    {# 【角色 :4-自导自学 】#}
                    <li class="btn-group btn-group-justified">
                        <a href="#"
                           class="btn btn-default btn-lg">修改</a>
                        <a href="#"
                           class="btn btn-default btn-lg">删除</a>
                    </li>
                {% endif %}
                <li>【兑换物品ID :{{ exchangeItem.item_id }}】</li>
                <li>【兑换物品名称 :{{ exchangeItem.item_name }}】</li>
                <li>【兑换积分数 :{{ exchangeItem.item_points }} 积分】</li>
                <li>【兑换物品描述 :{{ exchangeItem.item_description }}】</li>
                <li>【创建用户 :{{ exchangeItem.created_by.username }}】</li>
                <li>【创建时间 :{{ exchangeItem.update_time|date:'Y-m-d H:i:s' }}】</li>
                {% if request.session.role == 1 or request.session.role == 3 or request.session.role == 4 %}
                    {# 【角色 :1-系统管理员 】#}
                    {# 【角色 :3-学生 】#}
                    {# 【角色 :4-自导自学 】#}
                    <li>
                        {% if exchangeItem.item_status == "0" %}
                            <a href="javascript:exchangeItem('{{ exchangeItem.item_id }}')"
                               class="btn btn-default btn-lg btn-block btn-a">可兑换</a>

                        {% elif exchangeItem.item_status == "1" %}
                            <a href="#"
                               class="btn btn-default btn-lg btn-block disabled"
                               style="background-color: #DCDCDC;;font-size: 1.2em;color: #008B45" role="button">已兑换</a>
                        {% endif %}
                    </li>
                {% endif %}
            </ul>
        {% endfor %}
    {% else %}
        <strong>查无记录</strong>
    {% endif %}
</div>


4.2. 新增兑换物品页面
./mysite/study_system/templates/study_system/item/addExchangeItem.html

<script type="text/javascript">

    function addExchangeItem() {
        var itemName = $("input[name='itemName']").val();
        var itemPoints = $("input[name='itemPoints']").val();
        var itemDescription = $("textarea[name='itemDescription']").val();
        var itemStatus = $("select[name='itemStatus']").val();
        var csrf_token = '{{ csrf_token }}';

        $.post("/study_system/item/addExchangeItem/",
            {
                'itemName': itemName,
                'itemPoints': itemPoints,
                'itemDescription': itemDescription,
                'itemStatus': itemStatus,
                // 将token值放到请求数据部分,token的键必须是 csrfmiddlewaretoken
                'csrfmiddlewaretoken': csrf_token,
            }, function (data) {
                if ("success" == data.result) {
                    alert("新增成功");
                    window.location.href = "/study_system/item/getExchangeItemList/";
                } else {
                    alert("新增失败:" + data.errorMsg);
                }
            });
    }
</script>
<div class="container">
    <h1 class="text-center">新增兑换物品</h1>
    <form action="/study_system/item/addExchangeItem/" method="post" class="form-horizontal" role="form">
        {% csrf_token %}
        <div class="form-group">
            <label for="itemName" class="col-sm-2 control-label">任务名称</label>
            <div class="col-sm-10">
                <input type="text" class="form-control" name="itemName" id="itemName" placeholder="请输入兑换物品名称">
            </div>
        </div>
        <div class="form-group">
            <label for="itemDescription" class="col-sm-2 control-label">兑换物品描述</label>
            <div class="col-sm-10">
                <textarea name="itemDescription" id="itemDescription" class="form-control" rows="4"></textarea>
            </div>
        </div>
        <div class="form-group">
            <label for="itemPoints" class="col-sm-2 control-label">兑换积分数</label>
            <div class="col-sm-10">
                <input type="text" class="form-control" name="itemPoints" id="itemPoints" placeholder="请输入兑换积分数">
            </div>
        </div>
        <div class="form-group">
            <label for="itemStatus" class="col-sm-2 control-label">兑换物品状态</label>
            <div class="col-sm-10">
                <select class="form-control" name="itemStatus" id="itemStatus">
                    <option value="0" selected="selected">0-未兑换</option>
                </select>
            </div>
        </div>
        <div class="form-group">
            <div class="col-sm-offset-2 col-sm-10">
                <a href="javascript:addExchangeItem()" class="btn btn-default btn-lg btn-block btn-a">提交保存</a>
            </div>
        </div>
    </form>
</div>


第二步:运行测试-兑换物品管理功能

1,登录用户后,点击查看兑换物品列表页面

 点击可兑换物品,如果用户积分充足,则兑换成功,更新物品状态。

 

 -------------------------------------------------end -------------------------------------------------