test: 博客美化中……

电话面试总结

今天接到一个电话面试,主要问了一些项目上的知识。有些答得不好,故写写博客,算总结下吧。

  1. django框架,MVC?不是,是MTV.
  2. 了解queryset吗?
  3. group表管理,friend表如何管理的?
  4. web聊天室聊天记录如何保存?没完成。
  5. session管理;django登陆后关闭浏览器,再次打开浏览器,进入项目,发现还是已经登陆到项目中了。这是一个BUG.

记性挺一般的,现在就只记起6个问题。
第一个问题,问我对django框架的理解,当时我随口就说框架基于MVC模式。M表示models,models模块用来做数据库的表结构设计;V表示views,views模块用来写处理前端的POST/GET请求。C表示Control,用来…… so, 懵比了。面试后再想想,其实django是基于MTV模式~_~,竟然出如此低级的错误……

第二个问题是问我了解django的queryset吗? 听到queryset很熟悉,但就是想不起来? 然后我问面试官queryset是python的一个模块吗? 面试官给了点提示: 数据操作。恍然大悟,不就是django的ORM操作嘛。之前过滤数据时,打印出数据对象,其实数据对象就是一个queryset的集合。

第三个问题是问我web聊天室的内容。先问我有没有用开源的一些框架,开源框架??又懵比了,还好,突然想起上次写web聊天室总结时,有园友评论 “AJax这种方式不好。推荐一个PHP后端框架的workerman” 才反应过来,就回答没有,从底层数据表结构开始设计开发。

接下来问我如何管理好友还有Group表的。这个问题当时没准备好,项目创建的表结构忘记了……所以,回答得很差(自我感觉)。回来重新看了下表结构。

管理好友,其实我是在UserProfile用户表里面创建一个friends字段,这样你在admin后台就可以选择好友了。但你的好友其实也是在UserProfile表里面的(也是用户),所以这里用到了自关联,UserProfile表与UserProfile表关联。

    # for web qq
    # 一个用户可以有多个好友(自关联), 可以为空
    # 你是我的好友,那我就是你的好友(django默认),如:QQ ;你是我的粉丝,但我不是你是粉丝,可上openstack搜解决方案,如:webo
    friends = models.ManyToManyField("self", related_name="my_friends", blank=True)

前端可通过如下代码展示当前登陆用户的好友列表

{% for friend in request.user.userprofile.friends.select_related %}
    <span class="contact-name">{{ friend.name }}</span>
{% endfor %}

至于管理群的话,额,群有群主,管理员和群成员,它们都是用户,所以都要与UserProfile表关联。WebGroup群表如下。一个群有多个管理员,一个管理员用户可对应多个群,所以是多对多关联。其它略……

# 群聊的表
class WebGroup(models.Model):
    name = models.CharField(max_length=64)  # 群名
    brief = models.CharField(max_length=255, blank=True)  # 群介绍,可为空
    owner = models.ForeignKey(UserProfile)  # 群主
    # 下面这句代码如果再加上null=True,会曝错
    # webchat.WebGroup.admins: (fields.W340) null has no effect on ManyToManyField.
    admins = models.ManyToManyField(UserProfile, blank=True, related_name="group_admins")
    # 'WebGroup.admins' clashes with reverse accessor for 'WebGroup.members'.
    # HINT: Add or change a related_name argument to the definition for 'WebGroup.admins' or 'WebGroup.members'.
    # 只要涉及到同一张表的多个字段关联同一张表,就需要加个related_name
    members = models.ManyToManyField(UserProfile, blank=True, related_name="group_members")  # 群成员
    max_members = models.IntegerField(default=200)  # 默认最大群人数为200

    def __str__(self):
        return self.name

前端展示群列表,看到没有,前面给群表的related_name="group_members"用处大大的。这样用户表通过related_name就可以反向关联查出所属的群组。

{% for group in request.user.userprofile.group_members.select_related %}
    <span class="contact-name">{{ group.name }}</span>
{% endfor %}

第四个问题问聊天室的聊天记录如何保存。还没实现这个功能,尴尬。目前一刷新,聊天数据就没了,嗯,没了……

最后一个问题,是问我如何管理session. session有听过,浏览器与服务端是短连接,用户通过session与服务端保持会话跟踪。但是说到session管理,就……不会了。面试官也是挺好人的,跟我讲了一下session管理,比如用户多了,后台的session肯定也很多,so,  what should you do?? 当时对django的session管理机制不明白。只说了一个现象: 我在浏览器登陆A用户,登陆成功后,不退出,此时关闭浏览器。当我再次打开浏览器,进入项目界面时,what the fuck!! A用户已经登陆了。so, 肯定是之前登陆的session浏览器没有清除。

 

所以晚上回来专门去查了下django的session管理。

其实服务器是不会知道浏览器关闭了没有(当然,你可以在关闭的时候去通知服务器,但一般都不会这样做),所以关闭浏览器时服务器是不会删除Session的,也正是这个原因服务器才会设置一个Session失效时间的,不然服务器早晚会被撑爆的。等距离上一次使用该Session的时间达到设置的失效时间时,服务器就会认为客户端已停止活动,便会将相应的Session删除。
当然,我们可以在登陆时点击下次自动登录,比如说CSDN的“记住我一周”,或者我们的购物车信息可以在切换不同浏览器时依然可用。这就要用到我们上文提到的另一种Cookie了——硬盘中Cookie,这时Session id将长期保存在硬盘上的Cookie中,直到失效为止。
 

存取cookies

读取cookies很简单,因为读取cookies可以使用HttpResquest,每一个HttpResquest对象都有一个COOKIES对象,可以用它读取任何浏览器发送给视图的cookies。

因为每个视图函数的第一个参数都是request,其实它就是一个HtppResquest对象,所以直接使用request.COOKIES读取cookies就好。

写COOKIES就使用HttpResquest对象的set_cookie()方法,set_cookie有一些可选参数来指定一些特殊操作。

 

session操作

开启session(他是通过一个中间件和一个模型来实现的)。

1.编辑MIDDLEWARE_CLASSES,确保里面已经包含了django.contrib.sessions.middleware.SessionMiddleware。

2.确认INSTALLED_APPS,确保里面已经含有一个叫django.contrib.sessions的鬼畜。

其实这两项,一般默认就有了,前提是你的项目是用python manage.py startproject mysite来创建的。

视图中使用session

SessionMiddleware被激活以后,每个视图函数的第一个参数request(也就是HttpResquest对象)都有一个session属性,它和cookie一样,也是个字典型的对象,可以像使用普通字典那样使用。

如果SESSION_EXPIRE_AT_BROWSER_CLOSE设置为false,那么cookie在浏览器中保存周期是SESSION_COOKIE_AGE秒。如果设置为true,那么关闭浏览器时候,就会失效。

 

django有四中session实现方式

1、数据库(database-backed sessions)
2、缓存(cached sessions)
3、文件系统(file-based sessions)
4、cookie(cookie-based sessions)
 
其中数据库方式是默认的也是默认就启用的,其实现方式实际上是通过django中间件实现的,配置在INSTALLED_APPS中的django.contrib.sessions。目前先使用数据库方式的session,其他以后继续补充,首先考虑改进为“缓存”。

 

Djangosession存储在哪里?

Session在服务器存储的地点可以设置,分别有:数据库、缓存、文件、cookie

 

Session什么时候被保存?

默认情况下,Session被修改的时候才会被保存到数据库。除非我们将 SESSION_SAVE_EVERY_REQUEST设置为True,这样每一次请求Django都会保存session

 

保存在数据库中的Session什么时候会被清除?

Django不做清除的工作,开发人员得自己干。意味着必须有某种机制保证数据库中超时的Session会被删除。

 

如何让浏览器在关闭时删除session

我们希望浏览器关闭时删除session,这样用户重新打开浏览器的时候就要重新登录。Django官方文档的作法是将SESSION_EXPIRE_AT_BROWSER_CLOSE设置为True可以修改Djangosession的过期时间(SESSION_COOKIE_AGE,默认为2周),将其修改为半小时或其它时间,每当用户访问网站的时候,重新设置过期时间为SESSION_COOKIE_AGE(可以在中间件中实现),例如:

request.session.set_expiry(10)

这样当用户每次访问网站,session过期时间都会重新设置,当用户超过该时间没有访问网站时,session就过期了。

另外,考虑在客户端加入javascript脚本,使得用户在关闭浏览器的同时,向服务器发送注销请求,服务器端将session也同时注销掉。

 

数据库的Session什么时候被删除?

Django并不会删除数据库的sission数据。得开发人员自己来删除。

 

目前只是将SESSION_EXPIRE_AT_BROWSER_CLOSE设置为True,这样浏览器关闭时删除session。

接下来会学习中间件的知识……

更多关于session管理: https://docs.djangoproject.com/en/1.11/topics/http/sessions/,英文看起来挺吃力~_~

posted @ 2017-06-02 13:41  前程明亮  阅读(1207)  评论(0编辑  收藏  举报