User
Django 内置form表单验证(只适用于网页开发,不适用于前后端分离的ajax传输)
request.META request请求头 (包含请求头所有内容)
request.META[‘REMPTE_ADDR’] 访问者IP(可用于IP禁止)
request.META[‘HTTP_USER_AGENT’] 用户代理
头像上传
使用Django内置chunks()分片上传
生产环境下Django不擅长管理静态文件(通常会使用):
使用Nginx 部署静态文件
CDN(内容分发网络)
云存储(亚马逊S3服务,阿里云oss,七牛云)
- 文件上传七牛云
1.在官网新建一个bucket
2.安装pip install qiniu
3.配置文件
celery 异步上传头像(我们可以使用celery异步框架,我们可以把耗时的任务扔到后台,而前端给用户立即返回,待用户需要查看结果时,点击查看即可,并且可以随时看到任务执行的状态。)
celery worker -A tasks --loglevel=info #启动celery
func.delay() #开启异步任务
Social
推荐接口(将所有符合要求的用户显示出来,
建立滑动记录关系表
uid sid mark
1 56 like/superlike
1 88 like/superlike
56 1 like/superlike #互相喜欢加为好友
建立好友关系表
uid fid
1 56
1 88
56 1
88 1
————————————————
uid1 uid2
1 56
1 88
#(uid1,uid2进行比较,小的放前面。
#第二次传进来,也只会有一条记录)
自定义管理器:
Usre.objects objects本身就是一个manager,我们可以自定义个类,继承models.Manager,就可以通过User.objects.方法名,调用里面的函数
#判断类型:
isinstance(a,int) ==>> type(a)==int
True
中间件:MTV
运行流程:
WSGI(封装报文) WSGI
| (产生request对象) |
process_request process_response
| (匹配url) |
process_view process_template_response
| |
view templates
\ /
\ /
process_exception(任意地方报错,皆可捕获)
自定义中间件来捕获错误异常:
自定义一个类,继承MiddlewareMixin,使用process_exception方法会自动捕获出现的异常。便可对异常进行处理。
两种抛出错误的方法:
方法一:定义一个类继承于Except
class LogicException(Exception):
'''
自定义逻辑异常类
调用者通过参数,传递错误码
'''
def __init__(self,code):
self.code = code
方法二:
通过type动态创建类:
Dog(变量) = type(‘类名’,(继承于,),{‘属性’:‘大黄’,‘方法’:‘run’})
实例化: Dog.属性
>>>‘大黄’
Dog.方法
>>>run
#创建一个基类
def LogicError(Except):
code=None
def gen_logic_error(name,code):
return type(name,(LogicError,),{‘code’:code})
实例化:SidError = gen_logic_error(‘SidError’,3001)
Json中文输出Ascall码问题
Json.dumps(d,ensure_ascii=False)#ensur_ascii是否转为Ascall码
反悔接口:
通过创建时间,撤销上一次操作,并删除建立的好友关系
反悔次数:(每日三次)
在缓存中定义一个字段,可以设置有效期,又可以做次数加减
好友列表:
查询Friend表中uid1=我的,或者uid2=我的。如果uid1=我,那sid就是我的好友,反之亦如此。
喜欢过我接口:
再滑动记录表中查找sid=我的,Mark标记为like或者superlike,并排除好友列表现有的好友,显示出来
VIP
RBAC 权限管理模型
会员表
name level price
1 0 0
2 1 5
3 2 10
权限表
id name decription
1 no-ad 去广告
2 superlike 超级喜欢
3 rewind 反悔
会员-权限表
vip_id perission_id
2 1
2 2
3 1
3 2
3 3
利用后台冷启动插入数据
在用户表加入个字段,关联会员等级
装饰器:
1.不带参数的装饰器(两层)
def check(func):
def wapper():
a=fun()
if a<0:
return a
return wapper
@check
def foo():
a = random.randint(-10,10)
return a
2.函数带参数
def check1(func):
def wapper(a):
b=fun(a)
if b<0:
return 0
else:
return b
return wapper
@check1
def foo1(a):
return a
3.装饰器带参数(三层)
def check2(x):
def decorator(func):
def wapper(a):
b=fun(a)
if b<x:
return x
else:
return b
return wapper
return decorator
@check2
def foo2(a):
return a
当用户调用VIP才能使用的superlike,rewind,like-me接口时,检查用户的VIP等级,到VIP-permission表中对应的权限。
日志模块:
通过配置日志文件,在process_exception中间件中捕获之后,使用logging模块将其输出。
通过日志统计DAU:
在用户登录之后,输出日志到info.log中,在linux中使用下命令统计
cat info.log |grep 2019-07-26 | awk -F':' '{print $5}' | sort | uniq |wc -l
grep 2019-07-26 #筛选出当天日志
awk -F':' '{print $5}' #以 : 切片,打印第五列
sort #排序
uniq #去重
wc -l #统计个数
统计出DAU活跃度最高的前五名用户
cat info.log |grep 2019-07-26 | awk -F':' '{print $5}' | uniq -c| sort -r | head -n 5
uniq -c 去重并显示重复次数
sort -r 升序(默认降序)
head -n 5 显示前五个
Linux 三剑客: awk,
缓存:
为个人模块设计缓存,当用户第一次获取个人资料的时候先从缓存获取,如果不存在则访问数据库,从数据库中加入缓存,等第二次第三次获取就可以直接从缓存中获取,从而减少数据库的访问次数。当数据更新时,要立刻更新缓存否则会引发一个问题:
如果缓存中数据还未过期,又更新了数据库的内容,用户获取到的还是更新之前的数据。直到缓存过期,再次从数据库获取。
类的底层架构
In [1]:class A (object):
...: z =789
...: def __init__(self):
...: self.x = 123
...: self.y = 456
...: def foo(self):
...: return self.x+self.y
...:
In [2]: a = A()
In [3]: a.foo()
Out[3]: 579
In [4]: a.y
Out[4]: 456
In [5]: a.x
Out[5]: 123
In [6]: A.z
Out[6]: 789
#类的底层结构
In [7]: a.__dict__
Out[7]: {'x': 123, 'y': 456}
In [8]: A.__dict__
Out[8]:
mappingproxy({'__dict__': <attribute '__dict__' of 'A' objects>,
'__doc__': None,
'__init__': <function __main__.A.__init__(self)>,
'__module__': '__main__',
'__weakref__': <attribute '__weakref__' of 'A' objects>,
'foo': <function __main__.A.foo(self)>,
'z': 789})
[外链图片转存失败(img-9sT1QrJv-1565107026482)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1564821813774.png)]
a是类A的实例,通过a可以调用self所带的属性或方法,通过A可以调用非self绑定的属性。也就是说,self.x/self.y绑定在类的实例里,而z只是包含在类中。
动态添加类属性和方法
#动态添加类属性
In [9]: a.z =321
In [10]: a.z
Out[10]: 321
In [11]: a.__dict__
Out[11]: {'x': 123, 'y': 456,'z':321}
#动态添加类方法
In [16]: def bar(self):
...: return self.x * self.y
...:
In [17]: A.bar=bar
In [18]: A.__dict__
Out[18]:
mappingproxy({'__dict__': <attribute '__dict__' of 'A' objects>,
'__doc__': None,
'__init__': <function __main__.A.__init__(self)>,
'__module__': '__main__',
'__weakref__': <attribute '__weakref__' of 'A' objects>,
'bar': <function __main__.bar(self)>,
'foo': <function __main__.A.foo(self)>,
'z': 789})
In [19]: a.bar()
Out[19]: 56088
朋友圈模块:
1.拉取动态的方式
动态表Dynamics
id | uid | 动态 | time |
---|---|---|---|
1 | 001 | text1 | time |
2 | 001 | text2 | time |
3 | 005 | text3 | time |
4 | 006 | text4 | time |
5 | 007 | text5 | time |
6 | 005 | text6 | time |
7 | 007 | text7 | time |
Friend表
id | uid | fid | |
---|---|---|---|
1 | 001 | 005 | |
2 | 001 | 006 | |
3 | 001 | 007 |
friend_list =Friend .objects.filter(id=user.id)
dynamics =Dynamics.object.filter(Uid__in=friend_list).order_by(‘time’)
2.推送动态的方式
当好友001一发送动态,立刻推送给各个好友(插入一条数据)
005 1
006 1
007 1
friend_list = Friend .objects.filter(id=001)
for id in friend_list:
Pyq.objects.create(uid=id,Dynamics_id=3)
朋友圈内容表
Pyq
id | uid | Dynamics_id | |
---|---|---|---|
1 | 005 | 1 | |
2 | 006 | 1 | |
3 | 007 | 1 | |
4 | 005 | 2 | |
5 | 006 | 2 | |
6 | 007 | 2 |
当005查看朋友圈的时候就有两条动态了