代码开发(用的django框架)
django是MTV的架构,分别代表着模型(Model),模板(Template)和视图(View)。适合开发数据库驱动的网站。它强调代码复用,多个组件以插件形式服务于整个框架。
GitHub: https://github.com/z472/RenManSys
代码首先是建立django程序并做一些配置,比如数据库配置,路由配置,资源文件夹的配置,中间件的配置等。
然后大致的工作就是建立一个功能包→在里面写数据库的数据表模型文件→申请更新→写相对应的表单Form类的文件→写视图文件→写半html化的模板→单元测试
下面从一些角度来讲具体实现的逻辑:
以下是在user功能包里写的
用户注册,登录,验证:
表单继承自内置的UserCreationForm写在user/form。它是一个数据表和显示表单对象的过度,有加一些针对部分字段的验证逻辑。
注册成功后会发一封邮件给注册时写的邮箱地址,接着跳转到登录界面。要注意的是把用户输入的密码加密存入数据库中。还有就是针对不同的注册用户,在传入数据库时要分给他们不同的权限。
登录的话在user/view函数中写一些用户密码比对,之后就是将登录用户名和用户类别加密的方式写入cookie,方便之后的确认身份和获取必要的操作信息。
不同类别用户登录后会进入不同的页面
但在那之前要写个和那类用户相关的功能包,建立一些相关东西的数据表和表单。比如客户要出租某样东西,就需要出租物的数据表,我建立的是出租物的长短两张信息表,短的管理物品的简单
信息如名字,创建者id,出租物的状态,出租品id等等。长的表是出租品的描述类信息,必要的一条是创建者的描述。其余的想做类似各种网站好评差评什么的,但我图方便只设置了两个按钮对应着点赞和差评数量。展示如下,由于仅有部分数据是需要用户填写的,一些属性如出租品的状态,出租者的id,还有两个点赞数量按钮都是默认的,所以看上去内容不多。
然后就是用户搜索某样东西的页面
模板文件里仅有一个搜索框,一个复选框,一个数据显示表格
最初进去数据显示的是数据库的全部内容,随着选择不同类(在复选框里点击)和在搜索框中输入内容搜索的信息的提交。网页会改变
筛选出的展示数据。我这里没有写分页,但是它仅仅只是django内置的ListView类的一个参数决定的,但这个参数还要在模板(半html)里写一大串默认的写法,才能实现一个数据分页功能。
就分页和处理逻辑无关。
我还要讲讲这个半html的模板,它可以复用的。在出租功能包中是一个对于出租品的分类,搜索,数据展示的模板,它对于别的功能包比如员工要对自由职业者进行分类,搜索,数据展示;
管理员要对客户进行分类,搜索,数据展示。其中模板接受来自各个功能包下views.py文件传入的上下文。只要把它们规范一套命名就可以实现html的复用。甚至说如果员工不需要对自由职
业者分类,不需要建立复选框所需的上下文categorys,该模板就不会去管这个复选框。
下面看看分类功能的实现:
from django.views.generic import ListView
class RentCategorys(ListView):
categorys = ['a', 'b', 'c', 'd']
template_name = 'getshow.html'
queryset = Rent.objects.all()
extra_context = {'title': '出租物显示', 'categorys': categorys,
'geted_columns': ['name', 'rentabletime', 'creatorname', 'status'],
}
paginate_by = 100
context_object_name = "geted_rows"
# a类的筛选函数
def classify_a(self):
self.queryset = self.queryset.filter(status='cant')
def classify_b(self):
wanttime = datetime(2022, 5, 1)
print(wanttime)
# filter查询函数不支持 < 号,可以用匹配符__lt来实现。
self.queryset = self.queryset.filter(rentabletime__lt=wanttime)
def searchname(self, str):
# filter查询函数匹配符__contains 等价于 sql 中的like '%str%',它上面的是通配符是模糊大小写
# 如果有name='房子a',当输入'子A'的时候前面那条数据也会被搜索到,很符合期望,但我并没有搞懂怎么的
# 查询原理。
self.queryset = self.queryset.filter(name__icontains=str)
self.queryset = self.queryset.filter(name__contains=str)
# 重写父类的get方法,加入搜索和分类功能
def get(self, request, *args, **kwargs):
if request.method == 'GET':
# 'search'是html模板里搜索框的名字
print(request.GET)
if request.GET.get('search'):
self.searchname(request.GET.get('search'))
# html 复选框checkbox 传入选中的值
if request.GET.get('a') == 'on':
self.classify_a()
if request.GET.get('b') == 'on':
self.classify_b()
return ListView.get(self, request, *args, **kwargs)
继承 django 的视图类 ListView,该类主要是避免了数据表转表单再转模板文件,是一个数据表直接到模板的映射功能。该类算是概念上的数据显示视图,它的get方法用于获取
HTTP的GET请求。重写的话就是获取搜索框的信息,复选框的信息并以相应的标准来筛选修改属性queryset。它是该类的查询对象。上面代码实现的是基于出租品状态的标准a,基于
出租品时间的标准b。搜索框是模糊大小写 + sql 的like语句(%str%)的模糊匹配。
和上述类似的就是员工的分类,搜索,找自由职业者联系方式等都可以类似上述的写法来实现。管理员的界面是直接让他登录成功后转到django 的 后台管理系统。
测试
django的单元测试是继承自Python的标准库unittest来开发的。要在各个功能包目录里写test.py然后写各种断言判断语句,但我都是打开某个路由去测试的。
遇到的困难:
遇到的困难是用python的逻辑写到模板里,后来查到了可以自定义django模板的标签tag来让django模板解析器解释的时候按Python的逻辑去做。
自定义了一个标签strattr,感觉那里是整个项目最困难的。它实际上是把模板中的python变量先传给标签函数,然后返回值回送到模板的一个过程。为何要绕这么个过程
是因为django的模板引擎和python环境是不一样的,有很多内容python环境下执行很容易,但是模板引擎根本看不懂。
还有一个相似的概念是模板过滤器,是针对某个字段,调用的过程虽然和标签一样。但它的传参和标签不同,一个是要过滤的变量,后面是一个参数。最坑的是,找的所有资料
(包括django中文的官方文档)里讲的都是“参数”,让人误以为就是python变量。其实该“参数”就只限字符串类型。它只能处理部分逻辑给到html中。最初尝试了好久
用模板过滤器写都失败了。官方文档里面讲到标签的原话是---“它可比过滤器厉害多了,因为它几乎什么都能做。” 我真的完全不懂过滤器存在的意义。
不可重现的bug:
邮箱发送邮件时,不知道是由于网络原因还是怎样,10次(估计)会有1次是报错,但是邮件已经被正确的收到了。当时是测试邮件发送成功后再保存
数据库中注册信息,这么个逻辑。就会导致用户邮箱接受到邮件通知说注册成功,但注册实际是失败的情况。