零基础使用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 条评论
登录 后参与评论

相关文章

来自专栏FreeBuf

我们来“劫持”个GitHub自定义域名玩吧!

作为一个国内外项目都不怎么挖的我,比较喜欢拿自己正在使用的服务入手挖洞,毕竟拥有需求又了解业务才能长期跟进,更好的去发现各种流程上出现的毛病。

1913
来自专栏FreeBuf

记我在HackerOne上参与的一次漏洞众测邀请项目

这是一件关于我参与Hackerone平台某漏洞邀请项目的事,在此我要感谢该项目发起公司,他们友善的态度、及时的漏洞修复和奖金发放效率,让所有存在的提交漏洞都能在...

4054
来自专栏AI科技评论

干货 | 马蜂窝数据被扒光, 用 Python 爬取网页信息 4 分钟就能搞定

图片来自https://www.freestock.com/free-photos/illustration-english-window-blue-sky-c...

1933
来自专栏喵了个咪的博客空间

[Golang软件推荐] Frp内网穿透

在一个IP紧缺的时代,连电信也不分配固定IP给到你用,一条专网专用线路贵的不行,那么作为软件开发人员常常要使用到外网,比如和微信调试程序,给到不在同一网段的朋友...

8594
来自专栏恰童鞋骚年

操作系统核心原理-3.进程原理(上):进程概要

进程管理、内存管理和文件管理是操作系统的三大核心功能,那么什么是进程呢?顾名思义,进程就是进展中的程序,或者说进程是执行中的程序。当一个程序被加载到内存之后就变...

1982
来自专栏Timhbw博客

关于网站后期速度优化的一些坑

2016-06-0109:12:42 发表评论 231℃热度 由于网站已经迁移完成,所以昨天在优化服务器和WP,加快读者们的访问速度,毕竟有强迫症的我不能忍受...

2914
来自专栏高性能服务器开发

(八)高性能服务器架构设计总结1——以flamigo服务器代码为例

这篇文章算是对这个系列的一个系统性地总结。我们将介绍服务器的开发,并从多个方面探究如何开发一款高性能高并发的服务器程序。

1632
来自专栏FreeBuf

手机没Root?你照样可以渗透路由器

和Metasploit差不多,RouterSploit是一个强大的漏洞利用框架,用于快速识别和利用路由器中的普通漏洞,它还有个亮点,就是可以在绝大多数安卓设备上...

5234
来自专栏AI研习社

马蜂窝数据被扒光, 用 Python 爬取网页信息 4 分钟就能搞定

图片来自https://www.freestock.com/free-photos/illustration-english-window-blue-sky-c...

1421
来自专栏数据和云

故障恢复:从未知错误ORA-600 [3712]以猜测推理达成恢复

李真旭 Oracle ACE,云和恩墨技术专家 个人博客:www.killdb.com 在Oracle数据库的日常维护中,我们可能经常会遇到一些从未见过的错误,...

2986

扫码关注云+社区

领取腾讯云代金券