专栏首页零基础使用Django2.0.1打造在线教育网站零基础使用Django2.0.1打造在线教育网站(十七):我要学习配置
原创

零基础使用Django2.0.1打造在线教育网站(十七):我要学习配置

关于博主

努力与运动兼备~~~有任何问题可以加我好友或者关注微信公众号,欢迎交流,我们一起进步!

                 微信公众号:  啃饼思录
                 QQ: 2810706745(啃饼小白)

写在前面

本篇笔记我们将介绍我要学习小页面的配置,为什么需要单独介绍,是因为这个和其他页面的耦合度不是很高,单独写一篇便于今后学习的需要。

本篇笔记对应于第十七篇代码,对应于github的位置是https://github.com/licheetools/eduline

配置我要学习

这就是我要学习的页面,它是通过Ajax来控制的,也就是异步的javascript和xml。它可以在保证当前页面不被重新刷新的条件下,提交表单向后台传送数据。

正如你在前面所学习的那样,但凡涉及到了表单的提交都会有一个form验证。我们仿照前面的逻辑在operation应用下面新建一个forms.py文件,用于此处表单的验证。

然后在里面添加如下代码:

from django import forms


class UserAskForm(forms.Form):
    name = forms.CharField(required=True, min_length=2, max_length=20)
    mobile = forms.CharField(required=True, min_length=11, max_length=11)
    course_name = forms.CharField(required=True, min_length=5, max_length=50)
就是这个样子:

接着打开operation/models.py文件,发现这两个函数定义的字段信息非常相似,连要求都是一样的:

那么我们就有一个疑问,如何让代码重复利用,不需要再次重新造轮子呢?我们可以利用Django自带的ModelForm,这比form强大多了,除了继承现有的字段还可以新增字段!新增代码如下:

# 进阶版的函数
class AnotherUserAskForm(forms.ModelForm):
    # 除了继承现有的字段还可以新增字段
    class Meta:
        model = UserAsk
        # 自定义需要验证的字段
        fields = ["name", "mobile", "course_name"]
就是这个样子:

接下来的一步就是path的配置了,现在有一个疑问,就是我们的项目url文件,已经存放了很多url,如果我们再往里面新增url就很容易造成管理上的混乱:

我们在思考能不能像高考考场一样,有许多分考场,学生在各个分考场的试卷会送到省里,在保证考试有效的情况下,避免人员来往市区的麻烦。Django里面其实也是有的,所以我们就采用include的机制,来达到这个目的:在保证path的有效情况下,将各个app应用的path分开放置,最后将app的path引入项目的path就可以了。下面我们开始在organization应用下面,新建urls.py文件,里面增加如下代码:

from django.urls import path, include, re_path
from .views import OrgView


urlpatterns = [
    # 课程机构列表页url
    path("list/", OrgView.as_view(), name="org_list"),
]

然后回到我们的eduline/urls.py文件,我们将刚才的那行path用下面的一行include代码替换掉:

# 课程机构应用path配置
    path("org/", include('organization.urls', namespace="org")),

注意: namespace是命名空间,可以防止因名字重复而导致发生错误。

就是这个样子:

我们运行一下我们的项目,发现报错了:

Specifying a namespace in include() without providing an app_name ' 
 django.core.exceptions.ImproperlyConfigured: Specifying a namespace in 
 include() without providing an app_name is not supported. Set the app_name 
 attribute in the included module, or pass a 2-tuple containing the list of 
 patterns and app_name instead.

错误上说我们没有写上app的名字,所以我们需要在各个app的urls.py文件里面加上各个app_name:app_name = "organization"就是这个样子:

然后重启我们的项目,在浏览器地址栏输入

http://127.0.0.1:8000/org/list

然后回车,发现和我们之前的页面一样。不知道你注意到没有,现在我们输入的是

http://127.0.0.1:8000/org/list

而不是之前的

http://127.0.0.1:8000/org_list

也就是说,现在我们所有的关于课程机构的url都是在org这个分页面之下的,其实这个org就是我们之前在项目urls中配置的organization的分path的一个总名字。

为了验证我们的操作是否有问题,我们采用点击页面中课程机构列表来查看当前页面是不是没有变化(没有变化是正常的,因为指向同一个url)。首先我们需要打开base.html页面,在里面ctrl+F 搜索授课机构,将所在一行的代码修改如下:
<li class="active" ><a href="{% url 'org:org_list' %}">授课机构</a></li>

然后运行我们的项目,在浏览器地址栏输入

http://127.0.0.1:8000/org/list
然后回车,出现这个页面,再点击页面中课程机构列表,发现还是这个页面,确实是这样,我们的配置没有问题:

继续Ajax配置

前面说到我要学习的页面,它是通过Ajax来控制的,是一种异步加载方式,所以我们此时不能在view里面直接render一个页面回来,应该是给前端返回json数据,而不是页面。这里我们就要用到HttpResponse这个类,它指明了给用户返回哪种类型的数据。

打开organization/views.py文件,在里面添加如下代码:

from operation.forms import AnotherUserAskForm

# 我要学习功能实现
class AddUserAskView(View):
    def post(self, request):
        userask_form = AnotherUserAskForm(request.POST)
        # 判断form是否有效
        if userask_form.is_valid():
            #  注意modelform和form的区别,modelform它有model的属性,而且有个参数commit,当它为真时会把数据存入到数据库
            user_ask = userask_form.save(commit=True)

            # 如果保存成功,则返回json,不过后面必须有content_type用于告诉浏览器返回的类型
            return HttpResponse("{'status': 'success'}", content_type='application/json')
        else:
            # 如果保存失败,则返回json,并将form的错误信息通过msg传递到前端进行显示
            return HttpResponse("{'status': 'fail', 'msg':{0}}".format(userask_form.errors),  content_type='application/json')

接着打开organization/urls.py文件,我们配置path,在里面添加如下代码:

from .views import AddUserAskView

# 用户咨询配置url
    path("add_ask/", AddUserAskView.as_view(), name="add_ask"),

然后打开org-list.html页面,在最底下新添加如下Ajax代码:

{% block custom_js %}
    <script>
    $(function(){
        $('#jsStayBtn').on('click', function(){
            $.ajax({
                cache: false,
                type: "POST",
                url:"{% url 'org:add_ask' %}",
                data:$('#jsStayForm').serialize(),
                async: true,
                success: function(data) {
                    if (data.status == 'success'){
                        $('#jsStayForm')[0].reset();
                        alert("提交成功")
                    }else if (data.status == 'fail'){
                        $('#jsCompanyTips').html(data.msg)
                    }
                },
            });
        });
    })

</script>
{% endblock %}

这个是Ajax代码,熟悉javascript的小伙伴们肯定很好理解,$(function(){})是程序入口,这里面其实就是通过DOM(文本对象模型)来控制节点,从而达到控制节点树的目的。我们是通过监听id为jsStayBtn的按钮来实现对数据的控制,当用户点击了这个按钮,就会触发url跳转,如果成功则继续调用data函数,它有两个状态:成功和失败,分别对应不同的提示信息。这里就不详细介绍了。别忘记在form表单提交加上{% csrf_token %}

现在我们测试一下我们的项目,在图示位置打上断点,开启DeBug模式:

在前端页面输入信息:

再打开数据库,查看operation_userask这个数据表,发现数据已经保存成功了:

不知道细心地你发现没有,我刚才电话号码输了:12306,页面提示是手机号,所以必须是11位,因此这里必须加上手机号码的合法性验证。

打开我们的operation/forms.py文件,里面加上如下代码:

import re

# 验证手机号码是否合法
    def clean_mobile(self):
        mobile = self.cleaned_data["mobile"]
        REGEX_MOBILE = "^1[358]\d{9}$|^147\d{8}$|^176\d{8}$"
        p = re.compile(REGEX_MOBILE)
        if p.match(mobile):
            return mobile
        else:
            raise forms.ValidationError("手机号码非法", code="mobile_invalid")

关于正则表达式的用法,大家可以关注我的另一个专题《趣玩Python爬虫》,我目前在筹划中,预计9月份就会更新了。

接下来你可以重复刚才的测试操作,看手机号码验证是否生效了,这里就不一一演示了。

至此,我们关于我要学习的小页面的配置就到此为止了,感谢你的赏阅。下一篇笔记,我们就介绍课程机构的详情页面的配置了。

本篇笔记对应于第十七篇代码,对应于github的位置是https://github.com/licheetools/eduline

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 零基础使用Django2.0.1打造在线教育网站(十五):模板继承应用

    努力与运动兼备~~~有任何问题可以加我好友或者关注微信公众号,欢迎交流,我们一起进步!

    编程思录
  • 零基础使用Django2.0.1打造在线教育网站(二十三):个人信息相关页面配置

    努力与运动兼备~~~有任何问题可以加我好友或者关注微信公众号,欢迎交流,我们一起进步!

    编程思录
  • 零基础使用Django2.0.1打造在线教育网站(十一):登录页面实现

    努力与运动兼备~~~有任何问题可以加我好友或者关注微信公众号,欢迎交流,我们一起进步!

    编程思录
  • 一网打进Linux下那些查找命令

    查找是我们每天都在做的事情,早上醒来找下手机,出门之前查下公交,坐下之后查下资料,分析数据查下模式。 查找文件,查找信息,查找错误是应用起来更为具体的一些工作,...

    生信宝典
  • 【置顶】Python开发中常见问题参考资料:问题汇总:

    如果我们在outside.py文件中调用hub.py时,就会打印出this message should not be shown out of this fi...

    keloli
  • 玩转WiFi Pineapple之看我如何优雅的盗取CMCC账号

    感谢趋势科技的欣姐给我寄了一个Pineapple,于是就自己摸索开始玩了起来,国内pineapple的资料不太多,于是去国外论坛去逛逛,渣渣英语不好看着甚是不舒...

    FB客服
  • caffe c++示例(mnist 多层感知机c++训练,测试)

    caffe训练网络模型一般直接使用的caffe.bin: caffe train -solver solver.prototxt,其实这个命令的本质也是调用c+...

    bear_fish
  • 解决树莓派下载django的TypeE

    进日, 玩起了树莓派3B+, 对我这种新手来说, 不搭服务器怎么可以, So, 选择Python的Django库, 尝试各种方法, 失败N次 报错为:

    py3study
  • java中高级大公司多线程面试题

    lock接口在多线程和并发编程中最大的优势是它们为读和写分别提供了锁,它能满足你写像ConcurrentHashMap这样的高性能数据结构和有条件的阻塞。Jav...

    好好学java
  • 腾讯抗黑灰产——自监督发现行话黑词识别一词多义

    ? 本文作者:lorenzwang ,腾讯 TEG 安全工程师 常见的中文 NLP 下游任务一般都是以分词作为起点(以 transformer 为核心的算法除...

    腾讯技术工程官方号

扫码关注云+社区

领取腾讯云代金券