软件工程团队项目,第3、4周——v1.2.0
时间:2020.5.5-2020.5.17
最近真的是越来越懒了,博客都凑到两周一起写。。。
1.任务
第3周我的任务主要是和Xu同学一起完善用户个人空间的设计,主要是添加一个用户个人日志的功能,同时可以让用户访问到其他用户的个人空间。由于刚放完五一,上一个版本发布完之后就没多少时间了,加上自己懒,让Xu同学写了内置用户日志板块的函数之后自己就没怎么管了,然后换了一下新的登陆和注册页面,这周就结束了。。
第4周Xu同学去开发股票价格预测和推荐系统了,所以我打算把之前的坑填上,完成用户日志,同时可以让其他用户访问个人空间(设置修改权限),让用户可以编辑自己的资料,设计搜索框。
2.用户个人日志
这个功能技术上倒是没有什么难点,就是设置一个个人日志隐藏板块,而且不能在板块界面看到。但是有很多细节需要注意。
第一个坑就是个人日志板块的创建,由于懒得创建新的个人日志模型(因为创建了之后要新写视图和模板),所以个人日志设计为一个普通的文章类,所有用户的日志放在同一个__private__板块中。那问题来了,如何让django自动创建这个板块呢?
我的方案是,每次用户写个人日志的时候,都检查一下有没有这个板块,没有就创建它。
def private_post(request):
'''将用户编辑个人日志的请求重定向到文章编辑页面'''
private_plate=None
try:
private_plate=Plate.object.get(text='__private__')
except:
private_plate=Plate()
private_plate.text='__private__'
private_plate.save()
return HttpResponseRedirect(reverse('forum:new_post',
args=[private_plate.id]))
然后用户就可以写自己的个人日志了,当用户要查看自己写的日志时,就展示plate=__private__且owner=user的页面即可。
这时候第2个问题就来了,文章动态区和板块区都展示出了用户的个人日志,这时候就需要在文章和板块列表的筛选上下功夫了。
显示板块时,需要筛选出名字不是__private__的板块
plates=Plate.objects.all().exclude(text='__private__')
同样,显示文章动态时也如此
posts=Post.objects.all().exclude(plate__text='__private__').order_by('-date_added')
然后基本上没啥问题了。
3.搜索框
搜索框功能是在全站搜索板块、文章(不包括用户的个人日志)和股票。
就是这样
这里的难点主要是按照用户点的不同按钮来执行不同的搜索功能。如何辨别用户按的是哪个按钮呢?为每个button设置name属性就好了
<form action="{% url 'forum:index' %}" method="POST" name="search">
{% csrf_token %}
<input id="search-box" type="search" placeholder="请输入..." name="search_item" required/> 
<button type="submit" name="search_plate"><i>进板块</i></button>
<button type="submit" name="search_post"><i>查文章</i></button>
<button type="submit" name="search_stock"><i>搜股票</i></button>
</form>
这里不要忘记在搜索框的<input>标签里加入required,不然搜个空的东西就会出bug
在视图函数中检查request.POST中是否有某个button的name来执行相应的搜索操作。
if request.method == 'POST':
if 'search_plate' in request.POST:
plate_name=request.POST['search_item']
return HttpResponseRedirect(reverse('forum:search_plate',args=[plate_name]))
elif 'search_post' in request.POST:
post_name=request.POST['search_item']
return HttpResponseRedirect(reverse('forum:search_post_all',args=[post_name]))
elif 'search_stock' in request.POST:
stock_name=request.POST['search_item']
return HttpResponseRedirect(reverse('forum:get_stock_result',args=[stock_name]))
具体的搜索类似于这样
def search_plate(request,plate_name):
'''查询板块'''
results=Plate.objects.exclude(text='__private__').filter(text__icontains=plate_name)
context={'results':results}
return render(request,'forum/search_plate.html',context)
不要忘记排除__private__板块。
4.用户编辑个人资料
这里我参考的是django基础教程中的一个练习。主要思路是设计一个UserProfileForm表单,字段可以为空,用户查看个人资料时可以编辑这个表单,并更新个人资料。
class UserProfileForm(forms.ModelForm):
''' 定义用户编辑个人资料的表单 '''
#工作
job=forms.CharField(max_length=10,required=False,label='职业')
#性别 0是female,1是male,可以为空
#gender=forms.IntegerField(required=False,label='性别')
gender=forms.fields.TypedChoiceField(required=False,label='性别',coerce=lambda x: int(x),choices=((2,'无'),(0,'女'),(1,'男')))
#头像
picture=forms.ImageField(required=False,label='头像')
class Meta:
model=UserProfile
fields=['job','gender','picture']
需要在class Meta中的fields里指出可供编辑的UserProfile字段,然后在表单里重新定义这些字段,方便设计样式。
在模型里面,这些字段可以为空,用户可以选择补充或者不补充
#工作
job=models.CharField(max_length=10,blank=True,null=True)
#性别 0是female,1是male,可以为空
gender=models.IntegerField(null=True,blank=True,choices=((0,'女'),(1,'男'),(2,'无')))
#头像
picture=models.ImageField(upload_to='profile_images',blank=True,null=True)
然后只要在用户个人信息页面中把这个表单展示出来就好了,视图函数处理一下用户提交表单的POST请求,将合法内容存到当前用户关联的UserProfile对象中即可
将表单和对象关联的方法是添加一个instance参数,像这样
form=UserProfileForm(request.POST,request.FILES,instance=userprofile)
然后进行检查有效性,保存数据等操作即可。
这里有点坑的可能就是用户头像的展示。首先如果用户上传头像的html表单中要加上属性enctype=“multipart/form-data”,至于为什么我也不知道
<form action="{% url 'users:user_information' user.id %}" method="POST" enctype="multipart/form-data"></form>
然后就是导航栏里的用户头像展示,由于base.html没有关联的视图函数,无法向其传送UserProfile对象。但是可以通过User类来反向查询,需要获得与user对象关联的UserProfile类时,通过user.userprofile来访问。是的,就是把反向查询的类小写。然后就可以得到关联的对象了。
这是导航栏中展示用户头像的代码
{% if user.userprofile.picture %}
<img src="{{ MEDIA_URL }}{{ user.userprofile.picture }}" alt="{% static 'images/default_user.jpg' %}" width="33" height="33"/>
{% else %}
<img src="{% static 'images/default_user.jpg' %}" alt="{% static 'images/default_user.jpg' %}" width="33" height="33"/>
{% endif %}
如果用户头像字段不为空则展示用户头像,如果为空则加载静态文件夹里的一张图片。
5.访问其他用户的个人中心
这里主要是做好权限的管理,我的逻辑是,对于内容,当前拥有者和其他用户都可见,但是只有拥有者可以编辑。
最最重要的就是检查当前发送请求的用户request.user是否与个人中心的拥有者selecteduser一致。
需要在视图函数里根据url请求中的user_id获得selecteduser对象,然后传到模板。
模板再根据selecteduser与request.user是否一致来显示内容
<ul>
{% for plate in plates %}
<li>
<a href="{% url 'forum:plate' plate.id %}" target="_top">{{ plate }}</a>
{% if selecteduser == user %}
<div class="divButton"><a href="{% url 'forum:del_plate' plate.id %}"><button type="submit">删除板块</button></a></div>
{% else %}
{% endif %}
</li>
{% empty %}
<li>你还没有创建任何板块</li>
{% endfor %}
</ul>
6.一点点感想
啊上上周和上周的博客终于写完了。看着我们的论坛正在逐渐完善还是蛮欣慰的,但是又感觉自己的技术太差,做不出别人那种高大上的东西。emmm,总之尽力了。