PrimaryKeyRelatedField

官网解释:

PrimaryKeyRelatedField may be used to represent the target of the relationship using its primary key.

使用主键来呈现关系 目标

https://www.django-rest-framework.org/api-guide/relations/#primarykeyrelatedfield

用主键来呈现,便于保存数据库

*django中related_name作用

一句话总结:在一个对象查询多个对象的场景使用

如,

1,作者和书籍,在书籍外键设置related_name,查询指定作者的所有书籍时使用。

2,商品和图片,在图片外键设置related_name,查询指定商品的所有图片是使用。

两篇文章供参考:

https://www.cnblogs.com/pyspark/p/8638180.html

https://blog.csdn.net/wuliangtianzu/article/details/82656647

*django rest framework serializers小结

一共有两篇文章参考:

《Django rest framework之序列化小结》https://www.cnblogs.com/pyspark/p/8607801.html

《django rest framework serializers小结》https://blog.csdn.net/l_vip/article/details/79156113

引言
  serializers是什么?官网是这样的”Serializers allow complex data such as querysets and model instances to be converted to native Python datatypes that can then be easily rendered into JSON, XML or other content types. “翻译出来就是,将复杂的数据结构变成json或者xml这个格式的。
  
  在最近的学习中,个人看法,serializers有以下几个作用:
   – 将queryset与model实例等进行序列化,转化成json格式,返回给用户(api接口)。
  - 将post与patch/put的上来的数据进行验证。
   – 对post与patch/put数据进行处理。
 (后面的内容,将用patch表示put/patch更新,博主认为patch更贴近更新的说法)
  简单来说,针对get来说,serializers的作用体现在第一条,但如果是其他请求,serializers能够发挥2,3条的作用!

  本文比较长,用张图简单介绍一下主要内容

作者:_气呀呀呀
来源:CSDN
原文:https://blog.csdn.net/l_vip/article/details/79156113
版权声明:本文为博主原创文章,转载请附上博文链接!

django自定义用户验证错误后的提示信息

over

本地存储的3种方式、vuex的比较

localStorage
除非手动删除,否则会永久存储在浏览器中。
存储最大限制一般为5M或更多(不同浏览器不同)。

支持sessionStorage的浏览器最小版本:IE8、Chrome 5
存储内容过多会消耗内存空间,导致页面变卡。
常用方法:

let storage = window.localStorage
storage.setItem(‘key’, ‘value’) // 存储,key-value 为 键-值
storage.getItem(‘key’) // 获取
storage.removeItem(“key”) // 删除某个键的值
storage.clear() // 删除所有localStorage数据
storage.key(index) // 获取第几条数据的键名。index为数据索引

sessionStorage
只在当前所在窗口关闭前有效。窗口关闭后其存储数据也就会被自动清除。除了生命周期这一点,其他特性方法与localStorage基本一致。

cookie
存储限期可以自定义,默认是7天。超过存储期限后,数据会被自动清除。
存储大小不能超过4K。
在遵循同源策略的http请求中,会把cookie数据放在请求头中自动传给服务期。多用来传递当前用户身份信息,对账号登录状况作校验。

共性
cookie、localStorage、sessionStorage
这个三个都是浏览器本地存储,都遵循同源策略。
这三个都是只能存储string类型数据。(如果是非string类型,会直接转化为string类型存储进去)

vuex
vuex与以上三种方式不同。vuex是vue库中用于状态管理的工具,全局存储 主要是用于组件之间的通信。可监听数据状态的变更。当vuex数值发生变化时,其他组件处可以响应式地监听到该数据的变化。
vuex数据在当前vue实例被创建后,销毁前是生效的。创建一个新的vue,vuex数据就是初始化的数据状态。

部分摘自:

《localStorage使用总结》

作者: 老孙
来源:CSDN
原文:https://blog.csdn.net/laos1/article/details/86533079
版权声明:本文为博主原创文章,转载请附上博文链接!

Django Serializer序列化使用方法详解

1. 定义方法

Django REST framework中的Serializer使用类来定义,须继承自rest_framework.serializers.Serializer。

例如,我们已有了一个数据库模型类BookInfo

我们想为这个模型类提供一个序列化器,可以定义如下:

注意:serializer不是只能为数据库模型类定义,也可以为非数据库模型类的数据定义。serializer是独立于数据库之外的存在。

2. 字段与选项

常用字段类型:

字段字段构造方式
BooleanFieldBooleanField()
NullBooleanFieldNullBooleanField()
CharFieldCharField(max_length=None, min_length=None, allow_blank=False, trim_whitespace=True)
EmailFieldEmailField(max_length=None, min_length=None, allow_blank=False)
RegexFieldRegexField(regex, max_length=None, min_length=None, allow_blank=False)
SlugFieldSlugField(maxlength=50, min_length=None, allow_blank=False) 
正则字段,验证正则模式 [a-zA-Z0-9-]+
URLFieldURLField(max_length=200, min_length=None, allow_blank=False)
UUIDFieldUUIDField(format=’hex_verbose’) 
format: 
1) ‘hex_verbose’ 如”5ce0e9a5-5ffa-654b-cee0-1238041fb31a” 
2) ‘hex’ 如 “5ce0e9a55ffa654bcee01238041fb31a” 
3)’int’ – 如: “123456789012312313134124512351145145114” 
4)’urn’ 如: “urn:uuid:5ce0e9a5-5ffa-654b-cee0-1238041fb31a”
IPAddressFieldIPAddressField(protocol=’both’, unpack_ipv4=False, **options)
IntegerFieldIntegerField(max_value=None, min_value=None)
FloatFieldFloatField(max_value=None, min_value=None)
DecimalFieldDecimalField(max_digits, decimal_places, coerce_to_string=None, max_value=None, min_value=None)
max_digits: 最多位数
decimal_palces: 小数点位置
DateTimeFieldDateTimeField(format=api_settings.DATETIME_FORMAT, input_formats=None)
DateFieldDateField(format=api_settings.DATE_FORMAT, input_formats=None)
TimeFieldTimeField(format=api_settings.TIME_FORMAT, input_formats=None)
DurationFieldDurationField()
ChoiceFieldChoiceField(choices)
choices与Django的用法相同
MultipleChoiceFieldMultipleChoiceField(choices)
FileFieldFileField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL)
ImageFieldImageField(max_length=None, allow_empty_file=False, use_url=UPLOADED_FILES_USE_URL)
ListFieldListField(child=, min_length=None, max_length=None)
DictFieldDictField(child=)

选项参数:

参数名称作用
max_length最大长度
min_lenght最小长度
allow_blank是否允许为空
trim_whitespace是否截断空白字符
max_value最小值
min_value最大值

通用参数:

参数名称说明
read_only表明该字段仅用于序列化输出,默认False
write_only表明该字段仅用于反序列化输入,默认False
required表明该字段在反序列化时必须输入,默认True
default反序列化时使用的默认值
allow_null表明该字段是否允许传入None,默认False
validators该字段使用的验证器
error_messages包含错误编号与错误信息的字典
label用于HTML展示API页面时,显示的字段名称
help_text用于HTML展示API页面时,显示的字段帮助提示信息

3. 创建Serializer对象

定义好Serializer类后,就可以创建Serializer对象了。

Serializer的构造方法为:

1Serializer(instance=None, data=empty, **kwarg)

说明:

1)用于序列化时,将模型类对象传入instance参数

2)用于反序列化时,将要被反序列化的数据传入data参数

3)除了instance和data参数外,在构造Serializer对象时,还可通过context参数额外添加数据,如

1serializer = AccountSerializer(account, context={'request': request})

通过context参数附加的数据,可以通过Serializer对象的context属性获取。

序列化使用

1 基本使用

1) 先查询出一个图书对象

12from booktest.models import BookInfobook = BookInfo.objects.get(id=2)

2) 构造序列化器对象

12from booktest.serializers import BookInfoSerializerserializer = BookInfoSerializer(book)

3)获取序列化数据

通过data属性可以获取序列化后的数据

12serializer.data# {'id': 2, 'btitle': '天龙八部', 'bpub_date': '1986-07-24', 'bread': 36, 'bcomment': 40, 'image': None}

4)如果要被序列化的是包含多条数据的查询集QuerySet,可以通过添加many=True参数补充说明

1234book_qs = BookInfo.objects.all()serializer = BookInfoSerializer(book_qs, many=True)serializer.data# [OrderedDict([('id', 2), ('btitle', '天龙八部'), ('bpub_date', '1986-07-24'), ('bread', 36), ('bcomment', 40), ('image', N]), OrderedDict([('id', 3), ('btitle', '笑傲江湖'), ('bpub_date', '1995-12-24'), ('bread', 20), ('bcomment', 80), ('image'ne)]), OrderedDict([('id', 4), ('btitle', '雪山飞狐'), ('bpub_date', '1987-11-11'), ('bread', 58), ('bcomment', 24), ('ima None)]), OrderedDict([('id', 5), ('btitle', '西游记'), ('bpub_date', '1988-01-01'), ('bread', 10), ('bcomment', 10), ('im', 'booktest/xiyouji.png')])]

2 关联对象嵌套序列化

如果需要序列化的数据中包含有其他关联对象,则对关联对象数据的序列化需要指明。

例如,在定义英雄数据的序列化器时,外键hbook(即所属的图书)字段如何序列化?

我们先定义HeroInfoSerialzier除外键字段外的其他部分

12345678910class HeroInfoSerializer(serializers.Serializer):"""英雄数据序列化器"""GENDER_CHOICES = ((0, 'male'),(1, 'female'))id = serializers.IntegerField(label='ID', read_only=True)hname = serializers.CharField(label='名字', max_length=20)hgender = serializers.ChoiceField(choices=GENDER_CHOICES, label='性别', required=False)hcomment = serializers.CharField(label='描述信息', max_length=200, required=False, allow_null=True)

对于关联字段,可以采用以下几种方式:

1) PrimaryKeyRelatedField

此字段将被序列化为关联对象的主键。

123hbook = serializers.PrimaryKeyRelatedField(label='图书', read_only=True)hbook = serializers.PrimaryKeyRelatedField(label='图书', queryset=BookInfo.objects.all())

指明字段时需要包含read_only=True或者queryset参数:

  • 包含read_only=True参数时,该字段将不能用作反序列化使用
  • 包含queryset参数时,将被用作反序列化时参数校验使用

使用效果:

123456from booktest.serializers import HeroInfoSerializerfrom booktest.models import HeroInfohero = HeroInfo.objects.get(id=6)serializer = HeroInfoSerializer(hero)serializer.data# {'id': 6, 'hname': '乔峰', 'hgender': 1, 'hcomment': '降龙十八掌', 'hbook': 2}

2) StringRelatedField

此字段将被序列化为关联对象的字符串表示方式(即__str__方法的返回值)

1hbook = serializers.StringRelatedField(label='图书')

使用效果

{‘id’: 6, ‘hname’: ‘乔峰’, ‘hgender’: 1, ‘hcomment’: ‘降龙十八掌’, ‘hbook’: ‘天龙八部’}

3)HyperlinkedRelatedField

此字段将被序列化为获取关联对象数据的接口链接

1hbook = serializers.HyperlinkedRelatedField(label='图书', read_only=True, view_name='books-detail')

必须指明view_name参数,以便DRF根据视图名称寻找路由,进而拼接成完整URL。

使用效果

{‘id’: 6, ‘hname’: ‘乔峰’, ‘hgender’: 1, ‘hcomment’: ‘降龙十八掌’, ‘hbook’: ‘http://127.0.0.1:8000/books/2/’}

我们暂时还没有定义视图,此方式不再演示。

4)SlugRelatedField

此字段将被序列化为关联对象的指定字段数据

1hbook = serializers.SlugRelatedField(label='图书', read_only=True, slug_field='bpub_date')

slug_field指明使用关联对象的哪个字段

使用效果

{‘id’: 6, ‘hname’: ‘乔峰’, ‘hgender’: 1, ‘hcomment’: ‘降龙十八掌’, ‘hbook’: datetime.date(1986, 7, 24)}

5)使用关联对象的序列化器

1hbook = BookInfoSerializer()

使用效果

{‘id’: 6, ‘hname’: ‘乔峰’, ‘hgender’: 1, ‘hcomment’: ‘降龙十八掌’, ‘hbook’: OrderedDict([(‘id’, 2), (‘btitle’, ‘天龙八部’)te’, ‘1986-07-24’), (‘bread’, 36), (‘bcomment’, 40), (‘image’, None)])}

6) 重写to_representation方法

序列化器的每个字段实际都是由该字段类型的to_representation方法决定格式的,可以通过重写该方法来决定格式。

注意,to_representations方法不仅局限在控制关联对象格式上,适用于各个序列化器字段类型。

自定义一个新的关联字段:

1234class BookRelateField(serializers.RelatedField):"""自定义用于处理图书的字段"""def to_representation(self, value):return 'Book: %d %s' % (value.id, value.btitle)

指明hbook为BookRelateField类型

1hbook = BookRelateField(read_only=True)

使用效果

{‘id’: 6, ‘hname’: ‘乔峰’, ‘hgender’: 1, ‘hcomment’: ‘降龙十八掌’, ‘hbook’: ‘Book: 2 天龙八部’}

many参数

如果关联的对象数据不是只有一个,而是包含多个数据,如想序列化图书BookInfo数据,每个BookInfo对象关联的英雄HeroInfo对象可能有多个,此时关联字段类型的指明仍可使用上述几种方式,只是在声明关联字段时,多补充一个many=True参数即可。

此处仅拿PrimaryKeyRelatedField类型来举例,其他相同。

在BookInfoSerializer中添加关联字段:

123456789class BookInfoSerializer(serializers.Serializer):"""图书数据序列化器"""id = serializers.IntegerField(label='ID', read_only=True)btitle = serializers.CharField(label='名称', max_length=20)bpub_date = serializers.DateField(label='发布日期', required=False)bread = serializers.IntegerField(label='阅读量', required=False)bcomment = serializers.IntegerField(label='评论量', required=False)image = serializers.ImageField(label='图片', required=False)heroinfo_set = serializers.PrimaryKeyRelatedField(read_only=True, many=True) # 新增

使用效果:

123456from booktest.serializers import BookInfoSerializerfrom booktest.models import BookInfobook = BookInfo.objects.get(id=2)serializer = BookInfoSerializer(book)serializer.data# {'id': 2, 'btitle': '天龙八部', 'bpub_date': '1986-07-24', 'bread': 36, 'bcomment': 40, 'image': Non

TypeError: can’t compare offset-naive and offset-aware datetimes

起因:正常的dateime.now()得到的日期不能和Django数据库里面存储的日期数据做对比,两个解决办法:

1、是把Django配置里面的USE_TZ设置成False,这样Django的数据就没有时区信息了。

2、是在这个对比情景下,不要用datetime.now()来得当前数据,用以下代码:

*django rest framework apiview、viewset总结分析

引言

  官方文档:http://www.django-rest-framework.org/
  drf为我们提供强大的通用view的功能,本博客对这些view进行简要的总结分析。
  首先,我们看一下主要的几种view以及他们之间的关系。

view
mixins

    这其中,还涉及了mixins,主要也分为5类: 下面我们以课程(course)作为一个例子,对view进行一个总结。

1. django View

  首先,我们使用django自带的view,获取一个课程的列表:

2. APIView

接下来,我们用APIView来实现

  在APIView这个例子中,调用了drf本身的serializer以及Response方法。
  APIView对django本身的View进行封装,从上述的代码,这样分析,两者的差别看起来不是很大,但实际中APIView做了很多东西,它定义了很多属性与方法,举几个例子

  到这里,可能还不能体现drf通过view的强大之处,那么接下来的GenericAPIView就展示了它强大的功能。

3. GenericAPIView

在这个例子中,继承了mixins中的ListModelMixin,在get( )方法中,调用了它的list()方法,list方法会返回queryset的json数据。这里对mixins不进行过多的介绍。 GenericAPIView对APIView再次封装,实现了强大功能:

  • 加入queryset属性,可以直接设置这个属性,不必再将实例化的courses,再次传给seriliazer,系统会自动检测到。除此之外,可以重载get_queryset(),这样就不必设置’queryset=*’,这样就变得更加灵活,可以进行完全的自定义。
  • 加入serializer_class属性与实现get_serializer_class()方法。两者的存在一个即可,通过这个,在返回时,不必去指定某个serilizer
  • 设置过滤器模板:filter_backends
  • 设置分页模板:pagination_class
  • 加入 lookup_field=”pk”,以及实现了get_object方法:这个用得场景不多,但十分重要。它们两者的关系同1,要么设置属性,要么重载方法。它们的功能在于获取某一个实例时,指定传进来的后缀是什么。
       举个例子,获取具体的某个课程,假设传进来的ulr为:http://127.0.0.1:8000/course/1/,系统会默认这个1指的是course的id。那么,现在面临一个问题,假设我定义了一个用户收藏的model,我想要知道我id为1的课程是否收藏了,我传进来的url为:http://127.0.0.1:8000/userfav/1/,系统会默认获取userfav的id=1的实例,这个逻辑明显是错的,我们需要获取course的id=1的收藏记录,所以我们就需要用到这个属性或者重载这个方法 lookup_field=”course_id”。
       在generics除了GenericAPIView还包括了其他几个View: CreateAPIView、ListAPIView、RetrieveAPIView、ListCreateAPIView···等等,其实他们都只是继承了相应一个或多个mixins和GenericAPIView,这样,有什么好处?我们看一下同样一个例子的代码:

  这样,就完成了和刚刚一模一样的功能!

4.GenericViewSet

  • GenericAPIView的不足之处

  既然GenericAPIView以及它相关的View已经完成了许许多多的功能,那么还要ViewSet干嘛!
  首先,我们思考一个问题,同样上面的例子,我们在功能上,要获取课程的列表,也要获取某个课程的具体信息。那么怎么实现,按照GenericAPIView,我们可以这样实现:

  但这样实现有一个问题,关于serialize_class,显然,当获取课程列表时,只需要传回去所有课程的简要信息,如课程名字,老师,封面等等,但当获取课程的具体信息,我们还要将他们的章节以及相关下载资料(很明显,章节是另外一个model,有一个外键指向course),这些信息会很多,在获取课程列表,将这些传回去显然是不理智的。那么,还需要再定义一个CourseDetailSerializer,在get /courses/的时候,使用CourseSerializer,在get /courses/id/的时候,使用CourseDetailSerializer。
  那么,问题来了,我们怎么获取到是哪个action方法?这个时候,viewset就出场了!

  • viewset的功能
      GenericViewSet继承了GenericAPIView,依然有get_queryset,get_serialize_class相关属性与方法,GenericViewSet重写了as_view方法,可以获取到HTTP的请求方法。 解决刚刚的问题:
  • http请求方法与mixins的方法进行绑定
      但GenericViewSet本身依然不存在list, create方法,需要我们与mixins一起混合使用,那么新问题来了?我们依然需要自己写get、post方法,然后再return list或者create等方法吗?当然不!重写as_view的方法为我们提供了绑定的功能,我们在设置url的时候:

  这样,我们就将http请求方法与mixins方法进行了关联。那么还有更简洁的方法吗?很明显,当然有,这个时候,route就登场了!

  • route方法注册与绑定

  route中使用的一定要是ViewSet,用router.register的方法注册url不仅可以很好的管理url,不会导致url过多而混乱,而且还能实现http方法与mixins中的相关方法进行连接。
  在viewset中,还提供了两个以及与mixins绑定好的ViewSet,当然,这两个ViewSet完全可以自己实现:


作者:__奇犽犽
链接:https://juejin.im/post/5a66d262f265da3e317e4cc5
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。