题库

s8day141

内容回顾:
面试题:
1. django和flask区别?

2. django请求生命周期?

3. wsgi?

4. 中间件都有哪些方法?以及执行流程?

5. 中间件的应用?
- 权限
- cors
- csrf
- 缓存(中间件2/4)

6. 视图函数
- FBV
- CBV
FBV和CBV的区别?
- 没什么区别,因为他们的本质都是函数。CBV的.as_view()返回的view函数,view函数中调用类的dispatch方法,在dispatch方法中通过反射执行get/post/delete/put等方法。
- CBV比较简洁,GET/POST等业务功能分别放在不同get/post函数中。FBV自己做判断进行区分。

CBV时的注意事项?
- 装饰器
from django.views import View
from django.utils.decorators import method_decorator

def auth(func):
def inner(*args,**kwargs):
return func(*args,**kwargs)
return inner

class UserView(View):

@method_decorator(auth)
def get(self,request,*args,**kwargs):
return HttpResponse('...')
- csrf的装饰器要加到dispath
from django.views import View
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_exempt,csrf_protect


class UserView(View):

@method_decorator(csrf_exempt)
def dispatch(self, request, *args, **kwargs):
return HttpResponse('...')


from django.views import View
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_exempt,csrf_protect

@method_decorator(csrf_exempt,name='dispatch')
class UserView(View):

def dispatch(self, request, *args, **kwargs):
return HttpResponse('...')

7. ORM操作
models.UserInfo.objects.create()

obj = models.UserInfo(name='xx')
obj.save()

models.UserInfo.objects.bulk_create([models.UserInfo(name='xx'),models.UserInfo(name='xx')])

models.UserInfo.objects.all().delete()
models.UserInfo.objects.all().update(age=18)
models.UserInfo.objects.all().update(salary=F('salary')+1000)

.filter(id__gt=1,)
.exclude()

.values()
.values_list()

.order_by()
.order_by('-id')


.anotate()

.first()
.laste()
.get()
.exsit()

.reverse()
.distinct()

.extra()
.raw()

F和Q

.select_related()

title = models.CharField(max_length=32)

class UserInfo(models.Model):
name = models.CharField(max_length=32)
email = models.CharField(max_length=32)
ut = models.ForeignKey(to='UserType')
ut = models.ForeignKey(to='UserType')
ut = models.ForeignKey(to='UserType')
ut = models.ForeignKey(to='UserType')


# 1次SQL
# select * from userinfo
objs = UserInfo.obejcts.all()
for item in objs:
print(item.name)

# n+1次SQL
# select * from userinfo
objs = UserInfo.obejcts.all()
for item in objs:
# select * from usertype where id = item.id
print(item.name,item.ut.title)


# 1次SQL
# select * from userinfo inner join usertype on userinfo.ut_id = usertype.id
objs = UserInfo.obejcts.all().select_related('ut')
for item in objs:
print(item.name,item.ut.title)

.prefetch_related()
# select * from userinfo where id <= 8
# 计算:[1,2]
# select * from usertype where id in [1,2]
objs = UserInfo.obejcts.filter(id__lte=8).prefetch_related('ut')
for obj in objs:
print(obj.name,obj.ut.title)


补充:
无约束:
class UserType(models.Model):
title = models.CharField(max_length=32)

class UserInfo(models.Model):
name = models.CharField(max_length=32)
email = models.CharField(max_length=32)
# 无数据库约束,但可以进行链表
ut = models.ForeignKey(to='UserType',db_constraint=False)

有约束:
class UserType(models.Model):
title = models.CharField(max_length=32)

class UserInfo(models.Model):
name = models.CharField(max_length=32)
email = models.CharField(max_length=32)
# 有数据库约束,可以进行链表
ut = models.ForeignKey(to='UserType')

.using
.count


.only
.defer

.[1,100]

.aggregate

.fiter(id__in=[1,2])

# 多对多
.add
.set
.remove

8. django的Form组件的作用?
- 对用户请求的数据进行校验
- 生成HTML标签

PS:
- form对象是一个可迭代对象。
- 问题:choice的数据如果从数据库获取可能会造成数据无法实时更新
- 重写构造方法,在构造方法中重新去数据库获取值。
- ModelChoiceField字段
from django.forms import Form
from django.forms import fields
from django.forms.models import ModelChoiceField
class UserForm(Form):
name = fields.CharField(label='用户名',max_length=32)
email = fields.EmailField(label='邮箱')
ut_id = ModelChoiceField(queryset=models.UserType.objects.all())

依赖:
class UserType(models.Model):
title = models.CharField(max_length=32)

def __str__(self):
return self.title

9. 多数据库相关操作

python manage.py makemigraions

python manage.py migrate app名称 --databse=配置文件数据名称的别名

手动操作:
models.UserType.objects.using('db1').create(title='普通用户')
result = models.UserType.objects.all().using('default')

自动操作:
class Router1:
def db_for_read(self, model, **hints):
"""
Attempts to read auth models go to auth_db.
"""
return 'db1'

def db_for_write(self, model, **hints):
"""
Attempts to write auth models go to auth_db.
"""
return 'default'

配置:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
},
'db1': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db1.sqlite3'),
},
}
DATABASE_ROUTERS = ['db_router.Router1',]

使用:
models.UserType.objects.create(title='VVIP')

result = models.UserType.objects.all()
print(result)

补充:粒度更细
class Router1:
def db_for_read(self, model, **hints):
"""
Attempts to read auth models go to auth_db.
"""
if model._meta.model_name == 'usertype':
return 'db1'
else:
return 'default'

def db_for_write(self, model, **hints):
"""
Attempts to write auth models go to auth_db.
"""
return 'default'
问题:
app01中的表在default数据库创建
app02中的表在db1数据库创建

# 第一步:
python manage.py makemigraions

# 第二步:
app01中的表在default数据库创建
python manage.py migrate app01 --database=default

# 第三步:
app02中的表在db1数据库创建
python manage.py migrate app02 --database=db1

# 手动操作:
m1.UserType.objects.using('default').create(title='VVIP')
m2.Users.objects.using('db1').create(name='VVIP',email='xxx')
# 自动操作:
配置:
class Router1:
def db_for_read(self, model, **hints):
"""
Attempts to read auth models go to auth_db.
"""
if model._meta.app_label == 'app01':
return 'default'
else:
return 'db1'

def db_for_write(self, model, **hints):
"""
Attempts to write auth models go to auth_db.
"""
if model._meta.app_label == 'app01':
return 'default'
else:
return 'db1'

DATABASE_ROUTERS = ['db_router.Router1',]

使用:
m1.UserType.objects.using('default').create(title='VVIP')
m2.Users.objects.using('db1').create(name='VVIP',email='xxx')
其他:
数据库迁移时进行约束:
class Router1:
def allow_migrate(self, db, app_label, model_name=None, **hints):
"""
All non-auth models end up in this pool.
"""
if db=='db1' and app_label == 'app02':
return True
elif db == 'default' and app_label == 'app01':
return True
else:
return False

# 如果返回None,那么表示交给后续的router,如果后续没有router,则相当于返回True

def db_for_read(self, model, **hints):
"""
Attempts to read auth models go to auth_db.
"""
if model._meta.app_label == 'app01':
return 'default'
else:
return 'db1'

def db_for_write(self, model, **hints):
"""
Attempts to write auth models go to auth_db.
"""
if model._meta.app_label == 'app01':
return 'default'
else:
return 'db1'


今日内容:
1. websocket
2. tornado
3. redis

内容详细:
1. websocket
回顾:
- 什么是轮训?
- 通过定时器让程序每隔n秒执行一次操作。
- 什么是长轮训?
- 浏览器向后端发起请求,后端会将请求 hang 住,最多hang 30s。
如果一直不返回数据:则最多等待30s,紧接着用户立即再发送请求。
如果有数据返回:则操作数据并立即再发送请求。
PS:后台可以使用队列或redis的列表来hang主请求。

- 轮训和长轮训目的?
由于Http请求是无状态、短连接所以服务端无法向客户端实时推送消息,
所以,我们就是可以使用:轮训和长轮训去服务端获取实时数据。

作业:基于redis和长轮询实现投票。


websocket是什么?
websocket是一套类似于http的协议。
扩展:
http协议:\r\n分割、请求头和请求体\r\n分割、无状态、短连接。
websocket协议:\r\n分割、创建连接后不断开、 验证+数据加密;

websocket本质:
- 就是一个创建连接后不断开的socket
- 当连接成功之后:
- 客户端(浏览器)会自动向服务端发送消息,包含: Sec-WebSocket-Key: iyRe1KMHi4S4QXzcoboMmw==
- 服务端接收之后,会对于该数据进行加密:
base64(sha1(swk + magic_string))

- 构造响应头:
HTTP/1.1 101 Switching Protocols\r\n
Upgrade:websocket\r\n
Connection: Upgrade\r\n
Sec-WebSocket-Accept: 加密后的值\r\n
WebSocket-Location: ws://127.0.0.1:8002\r\n\r\n

- 发给客户端(浏览器)
- 建立:双工通道,接下来就可以进行收发数据
- 发送的数据是加密,解密,根据payload_len的值进行处理:
- payload_len <=125
- payload_len ==126
- payload_len ==127
- 获取内容:
- mask_key
- 数据
根据mask_key和数据进行位运算,就可以把值解析出来。


面试:
a. 什么是websocket?
websocket是给浏览器新建一套协议。协议规定:浏览器和服务端连接之后不断开,以此可以完成:服务端向客户端主动推送消息。
websocket协议额外做的一些前天操作:
- 握手,连接前进行校验
- 发送数据加密

b. websocket本质
- socket
- 握手,魔法字符串+加密
- 加密,payload_len=127/126/<=125 -> mask key



在项目中使用:
- django: channel
- flask: gevent-websocket
- tornado: 内置





































posted @ 2018-05-17 17:58  saintdingtheGreat  阅读(146)  评论(0编辑  收藏  举报