时间:2020.4.26-2020.5.4
唉,其实v1.0.0在五一假期的时候就已经发布了,发布之前还一度改代码改到喷鼻血,结果发布之后就懒了,拖到现在才写日志┑( ̄Д  ̄)┍
不bb了,讲正事。
1.任务设计
这周主要是新增股票查询和个人主页功能,股票查询可以搜索到与用户输入的字符串相关的股票名称,用户可以查看股票的详细页面,获取股票价格以及k线图。而个人中心可以管理用户关注的文章、板块、股票等等,还可以管理自己的文章和板块。(这里其实又多了一个隐形的需求,就是设置关注。)
经过上一周的学习组员应该也了解了Django的设计套路,于是我设计了第一阶段的任务让组员们试试水。
大家完成的情况都很不错,有问题也及时交流了,于是设计了第二阶段的任务。
组员也很快就完成了,质量很高。 只是到这个时候我想开始偷懒了[狗头],我感觉设计任务还是一件蛮不容易的事情。嘴上跟组员说着会有第三阶段的任务,结果自己一拖就拖到了五一假期。那懒就懒到底吧,于是五一开搞,单人solo。
2.整合任务
(1)股票查询功能
首先定义了查询视图和查询结果视图,查询功能调用了Lu同学写的接口
@login_required
def get_stock(request):
'''查询股票视图'''
if request.method != 'POST':
form = GetstockForm()
else:
form = GetstockForm(data=request.POST)
if form.is_valid():
stock_name = form.cleaned_data['stock_name']
return HttpResponseRedirect(reverse('forum:get_stock_result', args=[stock_name]))
context = {'form': form}
return render(request, 'forum/get_stock.html', context)
@login_required
def get_stock_result(request,stock_name):
'''查询结果页面'''
refer=GetPrice()
results=refer.get_related(stock_name)
context={'results':results}
return render(request,'forum/get_stock_result.html',context)
然后设计了股票详情页面,显示股票价格同时显示一个默认的k线图,再提供一个表单获取用户输入的时间区间,返回一个用户自定义的k线图。
这里第一个问题就来了。一开始我想的是k线图化成功之后生成一个独有的文件名,写到静态文件目录中去。但是,如果用户重复画图,k线图的html文件可能会有命名冲突。这还不是主要问题,如果画图画的多了,静态文件目录会爆满,还要设计一个定期删除html文件的脚本,啊啊啊啊啊…
于是我想了一个办法,就是把所有画完的k线图都命名为同一个名字,叫temp_custom_date.html,每次前端要加载k线图就加载这个文件。
同时,在画k线图之前,还要检查这个文件是否存在,如果存在,就先把它删掉,通过这种方法来更新temp_custom_date.html的内容。
看起来比较蠢是不是,但这是我能想到的最省事的办法了。
接下来的难点就是怎么在一个页面里卖获取用户输入的日期区间显示自定义k线图了。无非就是页面的嵌套嘛。这个我已经让前端的Zhang同学做好了,是这样写的。
<div>
<iframe name="htmlContent" class="bodyHtml" src="{% url 'forum:custom_kline' stock_name %}" width="900" height="450"></iframe>
</div>
然后跑起来就傻眼了。
于是看看浏览器报什么错。
于是一顿查询,发现需要在被嵌套的页面视图函数前加上这个装饰器
需要从外部import这个装饰器
from django.views.decorators.clickjacking import xframe_options_exempt
然后就好了
(2)用户个人空间
首先需要扩展用户关联的信息,扩展Django自带的User类有点麻烦,所以直接创建一个UerProfile类来关联用户的信息
class UserProfile(models.Model):
owner = models.OneToOneField(User,on_delete=models.CASCADE)
following_post = models.ManyToManyField(Post)
following_plate = models.ManyToManyField(Plate)
def __str__(self):
return self.auth.username
然后又出问题了,用户关注的股票要怎么存呢?建立股票model,把每一个股票对象都存在数据库里?感觉没必要。要是有列表字段就好了,于是查了查。嗯,还真有ArrayField,而且竟然还有JSONField,但是数据库要用PostgreSQL,虽然看起来很好用,但是自己又懒得改数据库配置,唉还是想其他办法吧。
干脆就将股票列表以CharField的形式存储吧,逗号作为分隔符,于是我又创建了一个与UserProfile关联的类,然后定义添加、删除、查找方法,使之成为一个股票名的列表类(好像比之前考虑的方法没好到哪里去)
class FollowingStocks(models.Model):
'''
用来储存用户关注的股票名称列表
'''
stocks=models.CharField(max_length=200)
owner=models.OneToOneField(UserProfile,on_delete=models.CASCADE,null=True)
def get_stock_list(self):
if self.stocks=='':
return []
else:
return self.stocks.split(',')
def stock_exist(self,stock):
'''检查股票是否在用户关注的股票列表里'''
stocklist=self.get_stock_list()
if stock in stocklist:
return True
else:
return False
def add_stock(self,stock):
'''添加关注的股票'''
stocklist=self.get_stock_list()
if stock not in stocklist:
stocklist.append(stock)
self.stocks=','.join(stocklist)
return True
else:
return False
def remove_stock(self,stock):
'''取消关注某股票'''
stocklist=self.get_stock_list()
if stock in stocklist:
stocklist.remove(stock)
self.stocks=','.join(stocklist)
return True
else:
return False
我觉得有时间的画还是可以直接改成调用json的包来处理,或者改一下数据库配置,用上ArrayField或者JSONField,毕竟用字符串这样搞来搞去感觉有点low了。
用户关注总算暂时搞好了,于是开始写用户关注的视图,一般的套路就是在HTML上设置一个按钮之类的,点了之后就可以关注当前的文章/板块/股票之类的,但是怎么将关注信息返回给用户,同时关注功能的视图函数又能将用户的请求重定向到用户原来停留的页面呢?
先一个个来,首先是返回操作后的提示信息,这里使用的是django的message模块
操作成功后需要以对话框的形式向用户返回信息就这样用
messages模块还给各种消息定了级别,什么debug、error、info、success、warning之类的,我还没有弄清楚。总之先这样用。
在有可能显示反馈信息的模板里添加这几行django控制语句
{% if messages %}
{% for msg in messages %}
<script>
alert('{{ msg.message }}');
</script>
{% endfor %}
{% endif %}
{% endblock header%}
大致的意思就是如果当前全局的messages队列里有消息,就在这个页面里全部显示出来。这样子可能会有一点点问题,如果某个新加的页面添加了某个可以反馈信息的功能,但是模板里面又忘记写了这几行,那用户跳到其他页面之后会看到莫名其妙的消息。。。所以这一点要多注意一下。
回来再说操作完之后怎么把用户重新定向到原来的页面,我上网查过之后发现最简单的是这样,执行完功能之后return这样一段
return HttpResponseRedirect(request.META.get('HTTP_REFERER'))
具体优缺点我还不知道,总之可以用。
啊总算弄的差不多了,将前后端整合之后应该没问题了,跑起来!点击我的板块里的板块链接试一试。
看起来是忘记加之前那个装饰器了,加上之后。。我人都傻了
怎么就套娃了!?应该是点击子页面的链接之后只有子页面跳转,而没有使整个页面跳转,一顿查询之后发现,只需要在连接标签里面加一个target="_top"就好了
<a href="{% url 'forum:plate' plate.id %}" target="_top">{{ plate }}</a>
跳转成功的效果就不展示了。
到这里整合的任务基本上就算是完成了,然后就是发布,更新服务器的代码,上线测试一下下。
3. 一点点感想
果然还是不要轻易一个人solo,慢点都没关系。主要是之前懒得继续设计下去,导致放假了任务就堆成一堆,看来平时还是不能偷懒。。。
(虽然又偷懒到现在才写上周的日志
不过这一个周期的收获还是蛮多的,虽然看起来都不是什么很厉害的技术。设想和实践之间还是有很大的差距,这个自己不动手是不知道的。
就是服务器那边总是pull来pull去的,有时候更新一下之前的配置都没有了,比较麻烦,看来是时候学习一下Docker了,争取搞个自动化部署啥的(立个flag而已)