前言:一点题外话

我发现,不更新博客的时候,不是非常忙,就是效率非常低。最近没怎么更新博客,原因是第二种= =。惭愧惭愧。

今天效率出奇的高,一天时间把PassNote后端的接口全部写完了,Django很好用,不过实际项目中还是有些框架不能实现的功能需要解决的,我比较喜欢造轮子,不过为了保证效率,还是尽量用现成的工具,减少不必要的折腾。

关于PassNote

之前应该在博客有说过,这是一个密码管理器,用于加密保存各种网站帐号和密码,还可以生成高强度的密码。

项目主页:https://deali-axy.github.io/PassNote/ 了解一下。

不过这个只是一个桌面版软件,也没有云备份功能,所以一直想找时间开发一个跨平台的版本,一直拖延着,等到今天才开始写。

Django的session处理

session简单说就是把cookie拿到服务器端去保存,然后客户端通过服务器返回的id作为session标识。

session框架让你存储和获取访问者的数据信息,这些信息保存在服务器上(默认是数据库中),以 cookies 的方式发送和获取一个包含 session ID的值,并不是用cookies传递数据本身。

Django中使用session

启用session

编辑settings.py

MIDDLEWARE_CLASSES中添加:

'django.contrib.sessions.middleware.SessionMiddleware',

INSTALLED_APPS中添加:

'django.contrib.sessions',

在view中使用

# 创建或修改 session:
request.session[key] = value
# 获取 session:
request.session.get(key,default=None)
# 删除 session
del request.session[key] # 不存在时报错

更多session的用法可以参考官方文档:https://docs.djangoproject.com/en/2.0/topics/http/sessions/

关于复杂对象序列化

对于序列化 Django 数据的解决方案已经有以下几种:

django.core.serializers

Django内建序列化器, 它可以序列化Django model query set 但无法直接序列化单独的Django model数据。如果你的model里含有混合数据 , 这个序列化器同样无法使用(如果你想直接使用序列化数据). 除此之外, 如果你想直接把序列化数据返回给用户,显然它包含了很多敏感及对用户无用对信息。

QuerySet.values()

和上面一样, QuerySet.values() 同样没法工作如果你的model里有 DateTimeField 或者其他特殊的 Field 以及额外数据。

django-rest-framework serializers

django-rest-framework 是一个可以帮助你快速构建 REST API 的强力框架。 他拥有完善的序列化器,但在使用之前你需要花费一些时间入门, 并学习 cbv 的开发方式, 对于有时间需求的项目显然这不是最好的解决方案。

简单说就是Django里面的几种现成方案不是功能不够强大就是学习成本高,正当我要自己造轮子的时候,我找到一个方便的解决方案,所以为了节省时间,立刻放弃了自己造轮子的计划。

项目地址:https://github.com/bluedazzle/django-simple-serializer 了解一下。

不过在实际使用的时候又有一个问题,就是序列化QuerySet的时候,如果包含AutoField的话就报错:'AutoField' object has no attribute 'rel'

有点坑啊,好不容易找到个好用的工具不用自己造轮子,突然发现这工具有问题,我还要帮它填坑??

好吧,没办法,只能出手了,由于代码没有注释,我也没那么多时间去研究具体问题出在哪里,所以就哪里出错改哪里。刚才也在github上给作者发了issue了。

修改了 Serializer 文件的data_inspect函数。

代码如下,加了一个rel属性判断。

def data_inspect(self, data, extra=None):
if isinstance(data, (QuerySet, Page, list)):
convert_data = []
if extra:
for i, obj in enumerate(data):
convert_data.append(self.data_inspect(obj, extra.get(
**{self.through_fields[0]: obj, self.through_fields[1]: self.source_field})))
else:
for obj in data:
convert_data.append(self.data_inspect(obj))
return convert_data
elif isinstance(data, models.Model):
obj_dict = {}
concrete_model = data._meta.concrete_model
for field in concrete_model._meta.local_fields:
# 检查 field 是否存在 rel 这个属性,为'AutoField' object has no attribute 'rel'错误填坑
if hasattr(field, 'rel'):
if field.rel is None:
if self.check_attr(field.name) and hasattr(data, field.name):
obj_dict[field.name] = self.data_inspect(getattr(data, field.name))
else:
if self.check_attr(field.name) and self.foreign:
obj_dict[field.name] = self.data_inspect(getattr(data, field.name))
else:
if self.check_attr(field.name) and hasattr(data, field.name):
obj_dict[field.name] = self.data_inspect(getattr(data, field.name))
for field in concrete_model._meta.many_to_many:
if self.check_attr(field.name) and self.many:
obj_dict[field.name] = self.data_inspect(getattr(data, field.name))
for k, v in data.__dict__.items():
if not str(k).startswith('_') and k not in obj_dict.keys() and self.check_attr(k):
obj_dict[k] = self.data_inspect(v)
if extra:
for field in extra._meta.concrete_model._meta.local_fields:
if field.name not in obj_dict.keys() and field.name not in self.through_fields:
if field.rel is None:
if self.check_attr(field.name) and hasattr(extra, field.name):
obj_dict[field.name] = self.data_inspect(getattr(extra, field.name))
else:
if self.check_attr(field.name) and self.foreign:
obj_dict[field.name] = self.data_inspect(getattr(extra, field.name))
return obj_dict
elif isinstance(data, manager.Manager):
through_list = data.through._meta.concrete_model._meta.local_fields
through_data = data.through._default_manager
self.through_fields = [data.target_field.name, data.source_field.name]
self.source_field = data.instance
if len(through_list) > 3 and self.through:
return self.data_inspect(data.all(), through_data)
else:
return self.data_inspect(data.all())
elif isinstance(data, (datetime.datetime, datetime.date, datetime.time)):
return self.time_func(data)
elif isinstance(data, (ImageFieldFile, FileField)):
return data.url if data.url else data.path
elif isinstance(data, Decimal):
return float(data)
elif isinstance(data, dict):
obj_dict = {}
if self._dict_check:
for k, v in data.items():
obj_dict[k] = self.data_inspect(v)
else:
for k, v in data.items():
if self.check_attr(k):
obj_dict[k] = self.data_inspect(v)
return obj_dict
elif isinstance(data, (str, bool, float, int)):
return data
else:
return None

测试了一下,可以正常使用,那就暂时这样吧,虽然有点“hack编程”的感觉,hhh

End

以上就是项目笔记的全部内容了,新版的PassNote和之前一样,在开发完成之后,会全部开源,这次是准备做移动、桌面、小程序多端跨平台的啦,有兴趣的朋友可以关注一下哈~

国际惯例,附截图一张。

About


了解更多有趣的操作请关注我的微信公众号:DealiAxy

每一篇文章都在我的博客有收录:blog.deali.cn

Django项目笔记:sessions处理以及复杂对象序列化的更多相关文章

  1. Django 项目笔记

    Django 环境的搭建 Django 安装 pip install django==2.1.4 Django 创建项目 django-admin startproject mysite Django ...

  2. 笔记:I/O流-对象序列化

    Java 语言支持一种称为对象序列化(Object Serialization)的非常通用的机制,可以将任何对象写入到流中,并在之后将其读回,首先需要支持对象序列化的类,必须继承与 Serializa ...

  3. 吴裕雄--天生自然JAVAIO操作学习笔记:字符编码与对象序列化

    public class CharSetDemo01{ public static void main(String args[]){ System.out.println("系统默认编码: ...

  4. Django商城项目笔记No.2项目准备工作

    Django商城项目笔记No.2项目准备工作 接着上篇开始,创建好工程之后,随之而来的是怎么配置工程,这篇文章记录如何进行相关的配置 1.pycharm打开工程,进行相关的配置 通过pycharm打开 ...

  5. Django 创建项目笔记

    基本命令 mkdir mysite # 创建项目目录,常取名mysite cd mysite virtualenv env # env\Scripts\activate.bat # Win pip i ...

  6. Django商城项目笔记No.12用户部分-QQ登录2获取QQ用户openid

    Django商城项目笔记No.12用户部分-QQ登录2获取QQ用户openid 上一步获取QQ登录网址之后,测试登录之后本该跳转到这个界面 但是报错了: 新建oauth_callback.html & ...

  7. Django商城项目笔记No.5用户部分-注册接口-短信验证码

    Django商城项目笔记No.4用户部分-注册接口-短信验证码 短信验证码也保存在redis里(sms_code_15101234567) 在views中新增SMSCodeView类视图,并且写出步骤 ...

  8. Django商城项目笔记No.4用户部分-注册接口-图片验证码

    Django商城项目笔记No.4用户部分-注册接口-图片验证码 1.首先分析注册业务接口 1.1.分析可得,至少这么几个接口 图片验证码 短信验证码 用户名是否存在 手机号是否存在 整体注册接口 图片 ...

  9. Django商城项目笔记No.3用户部分-用户模型类

    Django商城项目笔记No.3用户部分-用户模型类 Django提供了认证系统,文档资料https://yiyibooks.cn/xx/Django_1.11.6/topics/auth/index ...

随机推荐

  1. Scala快学笔记(二)

    一,基本概念 1,映射 Map与HashMap与TreeMap,SotredMap等区别: 1.HashMap键无序,它根据键的HashCode值存储数据,根据键可以直接获取它的值,具有很快的访问速度 ...

  2. leetcode268:Missing Number

    描写叙述 Given an array containing n distinct numbers taken from 0, 1, 2, -, n, find the one that is mis ...

  3. MySQL 创建数据库及数据表

    1.创建数据库 (1) 命令行创建 [root@host]# mysqladmin -u root -p create RUNOOB Enter password:****** (2) php创建 语 ...

  4. pngCanvas 是一个使用纯Python代码的生成png图像的工具

    #!/usr/bin/env python """Simple PNG Canvas for Python - updated for bytearray()" ...

  5. libevent2源码分析之四:libevent2的消息泵

    Dispatch类似于一个消息泵,在一个死循环中,不停地检查IO的状态(可以想像成不断从消息队列中读取消息),将状态的改变变成事件,再进行事件的响应. 主要代码如下: [event.c] int ev ...

  6. CStdioFile类学习笔记<转>

    本文转自:http://www.cnblogs.com/JiMuStudio/archive/2011/07/17/2108496.html   CStdioFile类的声明保存再afx.h头文件中. ...

  7. ImageBox Control with Zoom/Pan Capability

    Download source files - 10.8 Kb Download demo project - 6.81 Kb Introduction This control extends th ...

  8. 在连接mysql数据库时出错:The server time zone value '�й���׼ʱ��' is unrecognized or represents more than one time zone

    这个错误是时区导致的,所以需要在配置连接url后面加上时区: url=jdbc:mysql://localhost:3309/test?serverTimezone=UTC 其中UTC是统一标准世界时 ...

  9. Atitit. 木马病毒的外部class自动加载机制------加载class的方法总结

    Atitit. 木马病毒的外部class自动加载机制------加载class的方法总结 Atitit.java load class methods 1. 动态加载jar文件和class文件. 1 ...

  10. 浅谈C语言中断处理机制

    一.中断机制 1.实现中断响应和中断返回 当CPU收到中断请求后,能根据具体情况决定是否响应中断,如果CPU没有更急.更重要的工作,则在执行完当前指令后响应这一中断请求.CPU中断响应过程如下:首先, ...