django rest framework serializers序列化

 

serializers是将复杂的数据结构变成json或者xml这个格式的

serializers有以下几个作用:
- 将queryset与model实例等进行序列化,转化成json格式,返回给用户(api接口)。
- 将post与patch/put的上来的数据进行验证。
- 对post与patch/put数据进行处理。

实现序列化二个类:Serializer与ModelSerializer 比较

ModelSerializer(Serializer) 即 ModelSerializer继承了Serializer的相关功能,是对model实现序列化的封装

一、serializers.fieild

我们知道在django中,form也有许多field,那serializers其实也是drf中发挥着这样的功能。我们先简单了解常用的几个field。

1. 常用的field

CharField、BooleanField、IntegerField、DateTimeField这几个用得比较多

# 举例子
mobile = serializers.CharField(max_length=11, min_length=11)
age = serializers.IntegerField(min_value=1, max_value=100)
# format可以设置时间的格式,下面例子会输出如:2018-1-24 12:10
pay_time = serializers.DateTimeField(read_only=True,format='%Y-%m-%d %H:%M')
is_hot = serializers.BooleanField()

serializer的field不仅在进行数据验证时起着至关重要的作用,在将数据进行序列化后返回也发挥着重要作用

2. Core arguments参数

read_only:True表示不允许用户自己上传,只能用于api的输出。如果某个字段设置了read_only=True,那么就不需要进行数据验证,只会在返回时,将这个字段序列化后返回 
举个简单的例子:在用户进行购物的时候,用户post订单时,肯定会产生一个订单号,而这个订单号应该由后台逻辑完成,而不应该由用户post过来,如果不设置read_only=True,那么验证的时候就会报错。

order_sn = serializers.CharField(readonly=True)

write_only: 与read_only对应 
required: 顾名思义,就是这个字段是否必填。 
allow_null/allow_blank:是否允许为NULL/空 。 
error_messages:出错时,信息提示。

name = serializers.CharField(required=True, min_length=6,
error_messages={
'min_length': '名字不能小于6个字符',
'required': '请填写名字'})

label: 字段显示设置,如 label=’验证码’ 
help_text: 在指定字段增加一些提示文字,这两个字段作用于api页面比较有用 
style: 说明字段的类型,这样看可能比较抽象,看下面例子:

# 在api页面,输入密码就会以*显示
password = serializers.CharField(
style={'input_type': 'password'})
# 会显示选项框
color_channel = serializers.ChoiceField(
choices=['red', 'green', 'blue'],
style={'base_template': 'radio.html'})

3. HiddenField

HiddenField的值不依靠输入,而需要设置默认的值,不需要用户自己post数据过来,也不会显式返回给用户,最常用的就是user!! 
我们在登录情况下,进行一些操作,假设一个用户去收藏了某一门课,那么后台应该自动识别这个用户,然后用户只需要将课程的id post过来,那么这样的功能,我们配合CurrentUserDefault()实现。

# 这样就可以直接获取到当前用户
user = serializers.HiddenField(
default=serializers.CurrentUserDefault())
4 多对多
class BookSerializers(serializers.ModelSerializer):
class Meta:
model=Book
fields="__all__"
depth=1

备注:

1.定义一个depth=1  会将特殊字段  FK和M2M中每个对象的所有字段全部取出来。

2.对于FK字段,显示的是主键值,对于多对多字段,默认显示方式为:[pk1,pk2,...],一个列表中,包含所有字段对象的主键值。如果我们不想显示主键值,可以重写对应字段属性。

class BookModelSerializers(ModelSerializer):
class Meta:
model=Book
fields="__all__" authors=serializers.SerializerMethodField()
def get_authors(self,obj):
temp=[]
for obj in obj.authors.all():
temp.append(obj.name)
return temp

3.对于含有choices的字段,我们可以通过指定字段的source来显示展示的值

  比如:course_class = models.Integerfield(choices=((1,'初级'),(2,'中级')))

course_class = serializers.CharField(source='get_course_class_display')

二、save instance

save instance这是为post和patch所设置的。

post请求对应create方法,而patch请求对应update方法,这里提到的create方法与update方法,是指mixins中特定类中的方法。我们看一下源代码:

# 只截取一部分
class CreateModelMixin(object):
def create(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers) def perform_create(self, serializer):
serializer.save() class UpdateModelMixin(object):
def update(self, request, *args, **kwargs):
partial = kwargs.pop('partial', False)
instance = self.get_object()
serializer = self.get_serializer(instance, data=request.data, partial=partial)
serializer.is_valid(raise_exception=True)
self.perform_update(serializer) if getattr(instance, '_prefetched_objects_cache', None):
# If 'prefetch_related' has been applied to a queryset, we need to
# forcibly invalidate the prefetch cache on the instance.
instance._prefetched_objects_cache = {} return Response(serializer.data) def perform_update(self, serializer):
serializer.save()

可以看出,无论是create与update都写了一行:serializer.save( ),那么,这一行,到底做了什么事情,分析一下源码。

# serializer.py
def save(self, **kwargs):
# 略去一些稍微无关的内容
···
if self.instance is not None:
self.instance = self.update(self.instance, validated_data)
···
else:
self.instance = self.create(validated_data)
···
return self.instance

显然,serializer.save的操作,它去调用了serializer的create或update方法,不是mixins中的!!!我们看一下流程图(以post为例)

aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAk0AAAEoCAIAAADKSVJ7AAAgAElEQVR4nOydd1yTx//AA1htXd9WXHX7axUXToaoaLVV6x51tyruvVmuKk7qQEQRUFEQUFARFFAU2ciSIQiEhCQkIZOE7L3u98dTnwZwoAhJ4N6v5w/y5HLP5XnCvZ+7+9w9GACBQCAQSMsFY+gCQCAQCATShEDPQSAQCKQlAz0HgUAgkJYM9BwEAoFAWjLQcxAIBAJpyUDPQSAQCKQlAz0HgUAgkJYM9BwEAoFAWjLQc58Nl8t9+/atoUsBgUAgkAYBPffZ/Prrr7NmzTJ0KVodYrG4oKBArVZjsdj4+Hi5XA4AUCqV0dHRt27dKi8v109cVlZ269atu3fvVlZWAgDUanVhYaFUKhUIBCEhIRERERwORz+9SqV6/vx5YGDgs2fPlEolslOn05WVlXG5XKVSGRUVFRoaWl1drf+pjIyMwMDAqKgoLpeL7iQSiTdv3oyOjpZKpU1zJiAQyOfRKjynVqtZLBYAQKPR5OTkvH79WqvV1kmDw+HS0tJKSkrq7Gez2Wlpafn5+TKZTKfTsVisn3/+ecqUKXQ6ncfjNdMXgACQl5fXrl27nTt39u/fv2/fvmKxuLy8fPDgwX379h00aFDHjh0vXryIpPz77787d+78008/DRgwYNGiRQAAFovVqVOnDRs2TJgwwcrKqnPnzj179szOzkbSZ2VlWVlZ9e7de9CgQd9///2oUaMIBAIAQKfTjRkz5vfff1+4cOGoUaPatm07YMAARKgKhWLNmjXdunX7+eefLS0t//77bySrq1evdurU6f/+7//69ev3008/VVRUGOBMQSCQ2rQKz2Gx2L59+164cGHWrFm9evWysLCYMGECnU5H3qXRaL/99luPHj26du3auXPnOXPmoLfn586d69mzZ9euXS0tLQ8cOMDhcEaMGPHNN9+0a9euX79+R44cMdx3anXk5eVhMBgrK6ucnBwGgyGVSq2srObNm6dWqwEAfn5+GAwGh8NVV1ebmZldvnwZAKDVapH2HJPJtLCw6N69+8uXLwEAbDbb2tp6wIABKpVKKpX26tVr2rRpyEUnEomDBg2ytrbWaDQAgNGjR1tYWDx+/Bh5q127dmvWrAEABAUFWVhYFBUVAQA4HA7is8TERHNz89u3bwMA1Gr1hAkTJk2aZJBzBYFA9GkVnisuLsZgMN27d4+NjRWJRJmZmd26dZs5cyYAQKlUjhw5ctiwYcXFxWKxODMzs3379r///jsAoKSkxNzc3MfHRyaTUSiUgoIClUpVUFAwaNAgBweHnJwcEolk6G/WikA8FxQUhLyMjIw0MzMrLCzk8/lcLreqqgqDwVy7do3P52MwmK1bt4pEIvSzTCbTzMzs5MmT6J7Hjx+bmZlVVFQ8fPjQ3Nwc0SFCQkKCmZlZQUEBAGDIkCHz5s1D31q1apW1tTUA4P79+2ZmZj4+PvolnDNnjpWVlVQq5XA4QqHQ39/f3NycyWQ2yemAQCANplV47u3btxgMxtPTE91z+fJlMzMzgUDw5MkTDAaD3JgjhIWFWVhYIGLDYDCBgYF1chszZsz8+fObqeiQdyCee/78OfLSz8/PzMxswIABffv27dOnT58+fczNzc+dOwcAuHz58rffftujRw93d3c+nw8AoNFo5ubmUVFRaG7l5eUYDCYpKenixYtdu3bVP1BpaSkGg4mJiQEAWFlZOTk5oW9t3Lhx1KhRAACtVuvs7GxmZmZlZeXv74+86+jo2KFDhwEDBvTp06dfv349evRo3749Dodr2vMCgUA+RavwHNKee/XqFbonKSkJ6eY6f/68paWl/nBdWVkZUs2pVKq1a9e2adNm4sSJ9+/fRxOMGjVq9uzZzfoFIO88FxcXh7z09fU1MzNLTEzMzc3NycnJzc0tLi5GO5wrKyvPnDnTrl27iRMnKhQKNpttZmamfxGzsrLMzc3fvn3r7e3dvn17iURS50DJyckAACsrq7/++gt9a926daNHj0ZflpSUODk5WVhYuLu7AwBsbGwcHBzevHmDFCkvL6+0tBSJl4FAIAakFXkuMzMT3RMZGYnBYOh0+rlz5zp16qRfGRUWFurXpy9evFi6dKmZmdnOnTt1Oh0AwNraes6cOc38FSB1PJeeno7BYJ4+fVonGTJch3D//n1zc3McDicWi83MzFauXIm+5eTk1LlzZ61Wm5SUZGZmdvfuXfQtFxeXtm3bCoVC8GHP6R9l7dq1nTp1AgBs27atW7du9UOcIBCIYWkVnkP6LU+cOIHucXJy6tSpk1KpjI2NNTMzQ8ITEM6cOWNhYcFms/VzOHLkCDrWYm9vDz3X/GRnZ2MwmOjoaHTP/Pnz27Zte/LkyUePHh0/fnzBggUqlSo3N3fOnDm3b98OCwubNGnSoEGDxGIxl8vt0KGDpaXlli1bIiIitm7digzmAQC0Wu2mTZssLCwOHTqEvGVubn7nzh3kED169Fi4cCF6xGXLlg0cOBAAcOPGjT///DM8PDwwMHDgwIHLly8HAJDJ5K5du44ePfr69euhoaHLli07ffp0s54jCATyPlqL57755psuXbr4+PhkZmYeP37c3Nzcy8sLAKDVamfPnt25c+fAwMD8/Hxvb29zc/OzZ88CAF68eOHs7JyZmZmRkfHbb7/1798fmRG1fPny9u3bx8bGYrFYA3+x1gSRSFy6dCkSHoIgkUiOHTs2YsSI4cOHT548OTg4GABQXV29dOnSYcOGjRgxYv369UiACZ1Ob9OmzZkzZ3bt2jV06FAbG5uQkBD9zM+dOzd27Nhhw4ZNnjxZX6V79uy5cuUK+vLatWsuLi4AgLy8vIkTJw4ePNjGxubAgQMKhQJJUFZWtmzZsiFDhlhbW69YsaKsrKwJzwgEAmkYrcJzxcXF33zzjaen56xZs/r06dO3b99Lly6h7wqFwm3btvXq1atfv36DBw9G67U3b95YW1v37dt3wIAB8+bNKy0tRfZjsdhx48Z169ZNP7AFYkBUKlWdPRqNBpkYgMBgMDAYzM2bN9+b+CP5fBxUb/WPDnsvIRDjobV4Dg3VYzAY6IIX+ohEoqqqKmQETh8Gg1Fn7QwAgEajYTKZsC4zFRDP+fr6GrogEAjEALQiz+n3R32IKr6KWvP+m3SI6UKn0zEYTJ3pbhAIpJXQKjyHhFA+ePDgkylLGVIsU/LJZBDTQqFQxMTEIKt5QSCQ1kar8ByXy/Xx8cHj8Z9MiWVKcSy4/C4EAoG0HFqF5xoO9BwEAoG0MKDnagE915ohVssUahhbBIG0NKDnalHOlOLZ0HMmA61Gnk8WfTpdA1CotXvCCdlEwVfJDQKBGA/Qc7UgsGWldLGhSwFpEDKlxu0R+VRs5VfJLaG0Zku06Phj+AwKCKSlAT1Xiwq27G3V12kfQJoUtUbnlVC1+RH/wP0KlaaxnY1ylW7XXZxTKHVdGDXvKzUQIRCIkQA9V4sKtqyEBttzxo5Gp/NPoW17InUKpfwViGXwGzvl8UUpzymU8teN0nVhlBMxlWpt3eUCIBCI6QI9VwvoOZNAq9MVUMR3stgH7hO2h1OSsLxGZlgjUbHFmmfFXCJHzhQqoeYgkJYE9FwtoOdMiEquvIIt5Uk1bNHnrUv5IXKIQrkKxltCIC0N6LlaQM+ZEK8qBDzJ1zEcmqFQrvl0OggEYlJAz9UCes5UUGl0uSRh/XW3GwP0HATSIoGeqwX0nKlQLVKV0L7ySqTQcxBIiwR6rhbQc6ZCMU381Z8sAT0HgbRIoOdqAT1nKqTi+BLFV3YS9BwE0iKBnqsF9JxJIFZoUnH8r54t9BwE0iKBnqsFpUZeAddxNnoqOV9tWUt9oOcgkBYJ9FwtqDwF9JzxU1wlZgqUXz1b6DkIpEUCPVcL6DnjRwdAHlmk0nz9NUug5yCQFgn0XC2g54wfgUydSWiSp+dAz0EgLRLouVpAzxk/5Uzp2689cw4Beg4CaZFAz9UCes74eVUhYAm//uAcgJ6DQFoo0HO1gJ4zcjRakITlqRv9wLn3Aj0HgbRIoOdqAT1n5PCk6rzKpnoOKvQcBNIigZ6rBfSckUNgyyhceRNlDj0HgbRIoOdqAT1n5LyuFApl6ibKHHoOAmmRQM/VgspTENjQc0aKQqVNaYLlvlCg5yCQFgn0XC3INfISepPErEMaD42nyCEJmy5/6DkIpEUCPVeLSq78dZOFOUAaSSFVTKhuqsE5AD0HgbRQoOdqUcmV5zXBAsGQr0JepVD6tZ/Fow/0HATSIoGeqwVbDkqqm2RuFqTxYKubVkIFNCW0HATS8sCkp6c/hSDExd2Lehr08FlcbKyhiwKpTWxM1PO0mw9ePI2NabpDXHuQHBX74mlcXFMd4gMkJyVxuVxDVwUQSIsFM/3XX/39/ODm7+fn5+vr7Xvdy+/2NV9fgxcGbvqb31Wfv33CfG6G+flebapD+F454Xffx/+W37Xmvvrbt259+OCBoasCCKTFgtmwbp2hy2BEcFSglPP1H/gCaTx5NFVTH6KQ3uSHeC8PHzy4d/euQQ4NgbQGMOvWrjV0GYwIGIdinAhk6oyKJnkWjz6GikMJDQmJCA9v/uNCIK0E6LlaQM8ZJ5VceTmzyefvQ89BIC0S6LlaQM8ZJ8U0cY2kqZb7QoGeg0BaJNBztSBx5a+h54wMrU6XTRQ2zaN4agE9B4G0SKDnakHjK95QoeeMi2qRKovQhMt9oUDPQSAtEui5WnBEKiwDrm9pXJTQJdimH5wD0HMQSAsFeq4W1SJVGfSckZFRIeCKmyPiH3oOAmmRQM/VAnrO2FBpdK8rhbpmmdMIPQeBtEig52ohVWjITfa4asgXwBWrmu1JSdBzEEiLBHruX+QqbUwR995rzs00+uNiQSVHZugSQQAAoIQuabY7D+g5CKRFAj33LxqtzuNJ5dYnkg0RrDVBBIZAaegSQQAAIBXHFzfls3j0gZ6DQFok0HP/QayWrQmq2BjBDs9lG7osEAAAkCg1KTh+sx0Oeg4CaZFAz9XiamLV1jCiqhnmJEMaALl5l6eBnoM0hnKWLKZE9Ci/Gm5ffYt6w0su52u/NCDt63iOwJa9IknT8ALT3nD8m+mMg5GEVwRDl6TRW3qFMK9SqNKY9rMXiqrEzdmBDD0HaQz+KbSUalAItybYirjA9SFBpf7CFsjX8dzpOHIcCTzDyU19iy0RPimqMXgxGr/F41UHo6voPEXjL66h0OnA60qhshlVDT0HaQy3Mhg1sCeoyfB6UaVUfuG/59fxnPfLqsZnAvm6+CbRKBwTniMhkKmziM2x3BcK9BykMdzKYNBM+B/O2LnwnGp4z8EwfGPD52UVxZTnAuKY0re0Zp2zDz0HaQzQc00K9BzkPZi657IIAmbzzu6AnoM0Bui5JgV6DvIeTNpzWh1IwvKaOfAVeg7SGKDnmhToOch7MGnP8aTq3MpmHZwD0HOQxgE916RAz0Heg0l7rpIjJzf70mvQc5DGAD3XpEDPQd6DSXsujyziS9XNfFDoOUhjgJ5rUqDnIO/BdD2nVGuTy3nN8ywefaDnII0Beq5JMVXPBQcHP3v2DAAgFApPnTpVXV398fSFhYVq9cfu8fPz8q7fuKHVNih4ITc3F4fDoS8fP3587969hnzQVDBdzzH4yhxScw/OAeg5SOMwrOdiY2OLi4sNdvhPkZKSkp+fr78nJycnOTm54TmYkudkMhmPx+NyuVwud926dcePH+dyuSUlJT///DMWi+Vyubdv305NTQUAEAiEy5cvHzx4MCgoKCgoaP/+/UuWLKHT6R/JPDQ0dPny5TqdDgCQlJQUGRmZmJiYmJgYGxvr7ubGZDL1E1Op1Dlz5jx//hx5OWnSpJMnT37RtzdSTNdzRVXiCrYBOgig5yCNoUk9JxKJbG1t7969+6EEAwcOdHVxAQB4enrOnj1b1/z9IR9GIpH069cvNjZWf2dsbGy/fv2Ewobe0ZqS51JTUwMCAkJDQ0NDQ3///fetW7aEhoZevnx5wIABwcHBoaGhLi4uN2/eBACo1er09PSFCxZoNBqNRrN9+/aUlJTbt2+HhoZGREQ8ePBgxYoVcXFx+pk/ePDg6JEjyN9HjhxxcnLKzs7Ozs5+9uzZiBEj6rcXHz58uG7dOgBAXl6eq6srslMub9RP9fXr169evfrQu35+fitWrAAAsNns2NhYqVTamGN9HNP1XD5ZJGmuZ/HoAz0HaQxN6jmZTHb69OnXr19/KMGoUaP+PnoUAPDixYsrV64YleeCgoNHjRxZf//wYcNu3brVwExMyXMAAPQC3Lt3701hIQBALBb7+fnVT1laWrrkjz+oVCqVSt22bRudTn8cHZ2QkMBkMslk8uDBg7OyspCULBaLQqH4+/vv3rWrpKQkLCzM3c3N29sbPeLixYuRv5VK5dOnT588eRITExMZGXnt2rWHDx9u3779xo0bcXFxAQEBM2bM0O/P/Fz+/PPPKVOmfOhdZ2fnwYMHAwDi4+M7depUUVHxxQf6JCbqOblK05zPKNAHeg7SGD7Lc8gdf4FeV15hYWFAQMDTp0/RPWlpaSKR6OnTp8gNfX5+PpfLBQDI5fKXL1/6+/tHR0drNP/+YlHPUSiUN2/eAAAKCgr8/f39/f3v3buXnpGBJMPj8QEBAY8ePULHdzIyMphM5qtXr8Lv3dNq/vv9x8fHBwQElJeXIy+pVGpoaGhAQACSOZPJfPLkCVqZV1ZWon1jaWlpAQEB6WlpaFbTp0/fu3dv/ZOwc+fO2bNnN/CMmZjn8vLyXr16Ra2qWrx4MR6PBwDweLzAwMCsrKyQkBCN3okuKyv7ddq0hw8fPnz4cNmyZRKplEAgJCYmAgAKCwtnzJiBnGWdToek2bBhw6JFi+7fv+/n53fq1KkdO3akp6enp6fHxMTMnDkTua4ajSYnJ6eoqKikpASLxRYXFw8bNiw9PR2Hw5WUlJSWluJwOD7/y595JpVKJZIPrlZ1+PDh0aNHI8UQCARNes9lop6j1MgLqWKDHBp6DtJwNNq6/7wN99zhw4eHDh26ePFiW1tbLBYLADhz5kzfvn3/+OMPa2vrP/74A6kGhw0damdrazV48KpVq2QyWceOHW/fvg0A2Lx5s4ODw4oVK/7v//5v/vz5SGLUc/v27kVuph89erRkyZJ169ZhMJg5c+YAAIKCgvr27Tt//nxbW9vJkycLBAIAwPTp021tbYcPHz5j+nQejwcA0Gq1W7ZsGT169MKFCx0dHQUCAZPJHD169O8zZy5evLhLly537twhkUhmZmY5OTnIN1q2bNm0adMAADt37hw4cOCCBQv69OmDuE2hUPTv3z/8fdEPYWFhvXr1UqlUDTlpJuY5AICzs/OIESPQOxcmizVq1CihUDhz5kz9YJDCwsJNGzcif7u7uzNZLAGf7+/vDwC4dOnSgQMH6mT7559/LnrXbgsNDd22bVt9z9VBJpPNmDHjvX2VNTU1O3futLe3X7BgQUlJCbLz/PnzkyZNcnBw8PHxQfZcu3bt5MmTbq6u1tbWVCo1ICDAxcUFAIDH452cnCZNmmRna3vCwwP5LaKeKysrmzd3rlwup1Kpjo6Ojo6OU6ZMmTJlSk1NDQAgKCjI0dHRxsbm8OHDSqUSABAREXHgwIFLly5ZWVklJSU15CSbqOdySEJqjWGKDT0HaThCufpkTOU/z6vuZDJj3/LfUMW3Mhi0htWD33//PdJfJ5VKRSJRcXFx+/bt0W6kHj16PHr0CADQp0+fcePGIaMbCoXC0tIyODgYAFBJIiEp2Ww2BoN5W1wM9Dzn5uo6ZswY9FiVlZU//PBDfn6+QCCw7NIFCf0DAAwdOtTz7FkAwPTp03v27MlgMAAASCXJ4/HatGmDBInweDy5XC6RSNDYCFcXl5EjRwIAJkyYsGXLFuRbdO/e/cWLF6mpqT/88INYLAYAkMnkDh06lJaWcqqr//e//723xzUzM7PLDz+Q3n2dj2NKnquuro6Li7t58+Y6JycWi1VdXc1kMgsKCiZNmsTj8cLCwv7888+QO3cQK5SWls6cMSM+Pj4+Pn7VqlXIAJu3t7dUKl25cmWaXrsYACAUCrv88MOSJUtWrliRnp5+9+7da9euIW/pdLoFCxYgefL5fKYeRUVFv/76K4VCQfdcu3YtIiICALB///4xY8a8evXqwvnziJIPHz5sNXhwcnLy06dPf/zxRyR/FxcXDAazbt26e/fu8fj8tWvX2tjYAABiY2NdXFwyMjLi4uK+a9/+VmAg0PNccnIyBoNhMBgKhSIzM7OgoGDWrFk//fSTUqm8c+dOly5dHj58mJycPGTIkJ07dwIAfHx8MBjMwoULb9++jdwAfhIT9VxKOU+uMszTTaDnIJ/F0WjS5ke8jQ84Gx9wsonCkCxmAz3n6urao3t3Dw8PpB/y6pUrHdq3P+ju7ubmdvjw4Y4dO3p6egIAevXqdePGDeQjKpWqa9euiOcAADExMUePHt2+fbuFhUVmZibQ85y7m9vYsWPRY9nZ2e3YsQMAkJSUZG5uvn//fjc3tyNHjvTq1WvVqlUAAMdJk3bu2KFfPLVa/eeqVf3797944YJM9u9X4vF4vr6+7u7ujpMmIR4N8Pe3tLQEAMTFxfXq1QsA4O7u3rNnz7///tvNzc3d3R2DwTx5/JjJZH7zzTdoU0Gf4uLijh07FhUVNeSkmZLnCAQCmUwGAKxbt27r1q0hISERERH+/v5WgwefPHkyJibG29vby8sLObklJSXz580rKCgoKirauHEjcptw586ds2fPbtq0qU77LCAgYPz48QEBAc+ePQsLC4uKitq5cycShxIfH4+252JiYoKDgyPecfbs2VGjRp04ceLhw4fInlOnTiGDhTt37hw+fDibzUbyF/D5P/zwQ1BQkEqlUqvVzs7Oo0aNAgAcOHBgwIABaDHWrVtXZ3xOoVBMnDhx48aNQM9z6enp3377LY1GQ9IwGAxLS8uMjAwAwJAhQ9zd3TUajUqlun79eldLSwCAn5/f999/3/DYJGCanhPJNWn4L+80biTQc5CGIJCpS2iSXJIwJJO5/h59TVBFOp4PALj9OeNzkZGRU6dOHThgAA6H87t2raul5aFDh1xdXV1dXU+dOlVaWgoA6N27Nxq4gHguNDQUALB8+fJBgwbt379/7969bdq0yc7OBh/w3PXr13/88UdkJOXp06dt2rRxcXFBjnLixAlEkJMdHbdv21a/hKGhoTY2NsOGDWMwGGQy+aeffpo5c6abm9vUqVPHjRsHAOBwOB06dMjLy9u0adOGDRsAALt37x4wYADyRdzc3M6cOcNgMEgk0rfffvveOQ+FhYWdOnV6+/ZtQ86YKXkOwc/Pb+aMGRvf9UlWVFTMmztXfwAWgUgkbtqwAQCgVqvXr19/JziYRCLV1NT0+vHHyMhI/ZQsFmvPnj1Bt28fPnQI2RMSErJlyxZkXsGjR49mzJjx3n7L06dPX7hwIS42lv5OOfp5rlixolevXhs2bODxeCwWq23btiNHjrSzs7O3t//555+XLFkCANi9e/f48ePRT61fvx7xHIfLXbduna2NjY2NTYcOHZCu6jqeQ7sCpk2b9tdffwEA5HL5//3f//388892dnZ2dnYjRoywtbUFAFzx8UH63BuOKXqukiPHMpowBvXjQM9BPoJQrimlS9JwvDQ8H8uUylVarli1/S4ppZyHJGjg+JxKpUKjEAYPHuzh4fH69euOHTvWr6B69+6NdkohnouIiBCJRGZmZshcNC6X+5H2XHV1dd++fdHwkLKyMnNzc0K92LfJjo7btm799zsKhTqdTqX87zkhXbp0uX//vq+v748//ojsOXrkyJAhQ5C/58+fP2/ePGtra2Qw5cqVK3379q2TP5vN7t6tW0JCQv1TERsba9mlCzJY80lMyXNsNjsgICAoKIjD4fz111/IwNidO3c8PDwePnyI3MUg0On0M2fODB8+/Jqv7+3bt+fPn5+YmCiTyQgEQrfu3c+dO6efbUBAQHFR0dO4OGQGCQDA19f30qVLyN8ymQztt9SHQCDY2trW1NRUVFTsqN1yRykpKRk1cqSTk5NKqezUqdPDhw85HA6LxRKLxcjvcteuXYiKENavX//LL78AAFatWjVq1KjSkhI+n+/o6Pje9hziuYiICMsuXZDgF5VK1bdv33/++YfL5bJYLIFAoNZoAACXvLx++umn+l/hI5ii597SJFxJcy/3hQI9B6mPUK7BMqXpeH4qnl/KkApk//0+tVpdZfV/NV8DPcdkMqdOnbp79+69e/b06NEDMcTcuXOtrKxcXFycnZ3nzp1LIBAAAO3bt/fy8kI+pVKpzM3Nb9++rdFoxo0bN2nSJBcXFzs7OwwGk56eDgDo37+/84EDAIDdu3b99NNPAIC9e/diMJjTp08fPXoU6f/cv39/7969XVxc/v777zlz5qSkpAAARo0cuWb1agBAcXFxu3btXjx/TqPRHBwcDh48uGPHjn59+5JIpJycnI4dO+7YsWPXzp2WlpbDhg1DShUVFWVmZjZs2DCkMhQKhTY2NjY2NseOHduzZ8+SP/5AAlvQscA6nD9/Hs3qk5iM53Q6XV5eHjLqKBAI5s2bh3RFrl69Ojc3F4vF7t2zB02ckJAwe/bsJ0+eIJ17bm5uEolEJpNt3LgxISFhzpw5h9413SgUysuXLwEA4eHhbu+mwR07dszDw0OtVqvVaiaTOXfu3DqSkEqlf/zxx4P795GXHh4edVQXHh6Ow+GUSuXq1aunTp0KAJg5c+aMGTPYbLZKpSotLUUibrdt24aoC2HNmjUTJ04EAEz95ZcFCxbI5fLs7Owffvhh69atAAB3d/fhw4cDAFJTU83NzTkcDpfL7dat24WLFxUKhUgkAgBs3bp12LBhZDJZrVZX4PHIjduF8+f79evXsj2n04EcklBdL4yt2YCeg6CI5OpShjSjQpBeIShlSBuy2gqQwbIAACAASURBVGoDPafT6eLj47dv375r167c3Fxkp1qtvn379rZt23bt2hUcHKxQKAAA3t7e6BoiOp3uwoULSBcfg8E4evTo7t27U1JSAgICkBr12rVriLcSExORYL3IyEg3N7cdO3Zs27btn3/+QfKJiIjYunXrrl27bty4gdxb3woMROYtsNnsQ4cO4XE4JIJ9x44dbm5u6LyC5KSkrVu3nj59OjU1FZ30JpPJjhw5EhMTg347sVjs5eW1bdu2AwcOPH78GKmytm/f7ujoWP9UTJs2rX444YcwGc8hICFG8fHxS/74AwBw+/btXbt2IW/t27dv165dSLSrPiql8o/Fi4kkkvelS3GxsQAANps9btw4BweH4uJiNFry7t27+/ftQ/4+4eExb948ZC2VK1euWFtbI05FwONwO3fsQOJNEHQ63dq1a3/55ZfCwkLk3sTV1XXQoEEjR450cHBARkqpVOqc2bOHDh1qa2trbW2NrE3g7u7+22+/ofns3r173rx5AIC8vLzhw4dbW1tPnz598uTJbm5uAIBTp05NmjQJAJCTk/Pjjz/KZbKMjIy2bdva29vb2tra2NiUl5cjUTaDBg2yt7e3HjECGZH29/MbNWpUA5c0QzA5z9VI1JmEupe+OYGeg0gUGhxL+qpC8KpCgGVKhbLP6F2A61t+iIKCgo4dO9aZl0wgEL7//vsGBqEAk/MckUjcsnmzlZVVdHR0ZGTk6dOn0QlnYrF45syZCxYsQFq7KHKZ7K+//vLz80OmKCIIhcIHDx7oSzEyMvLsmTPI3xcvXkS7tnk8nqurK6LD6urqx9HR58+d088Kxd3dvWPHjocOHULupxgMRkVFRR27UKlUPB6PhoSIxWL9+Xb6LxUKBYFAUCqVyGw5AIBEIkEirNRqNae6GklDp9MJBAIej8fj8aiz6XQ6Ho9Hz4NMJuNwOA09xQAAE/RcCV1SSv/g1MNmAHqu1YLoLR3PTynnldAlvC96Vgb03EfYtWvX/XedZwhhYWHvnTz+IUzMcwAAMplcVFRUWVmJTjNE0el0dDq9jlq0Wi2fz//kilxSqRRNI5VK6/fyabXazMzMOsuJ1iE7K4tEIhnVqjlfhsl57hVBUGO4wTkAPdf6kCg0BLYslyRMx/PfUMVccYMmLH8I6LkmxfQ8B2kGTMtzKo0ut1KkNejtBfRcK0Gm1OBZsnS8IKNCUPqlrbf6QM81KdBzkPdgWp7jiJRvaYZZ7gsFeq5lI1NpSRx5DkmUXM4voIjYoka13uoDPdekQM9B3oNpea6MLiFzDPwjgp5rkchVWhJHnkUQpuP5xTRJ9dfWGwr0XJMCPQd5D6bluTQ8X2QIx+gDPdeSUKq1lRx5FkGQUs4rpIhYQuWnP9M4oOeaFOg5yHswIc/JlNoUnMGW+0KBnmsBKFTaSo48t1KUguPnkUVMgaLZxnyh55oU6DnIezAhz1FrFIZ65pw+0HOmi0qjq+IpsoiClHJePkXEFCibP6bpVgaDY8h44RaO1wsj8By8vsbG1UST8dwbqriKpzB0KaDnTA+1RkflKXJJwlQcv4AiYguVBgzY9UuhFUkATW4imwxQRIYuQ4M3ugIcekRSfemTTL6O5zyfUWoAkLSITaQxfBkav0kBuJjINhXPva4UKdSGeRaPPtBzpoJWB2h8RS5JmITl5ZCENL7CcKvF/UdupejOa0FgOsMkNv8U+smYSoMXo4HbrSzOg7zqL77KX8dzD/Orr6ZxL7+sMvXN6wX1+JNKgxej8ZtPEt07oUooM3BkR0MQytVZBl3uCwV6zsjRaHU0nqKAIsrA8/PJImqN3ICrobYAXlcafrCgefg6nmsx6HTAsEsstkLwLGlxlYFnziFAzxknOh2g8xU5JOHLspoCioghUKo1UG+NRarUZlS0lroOeq4WMlUruvZGQhZBwBAYfnAOQM8ZGVqdjsFXFFLEaXh+JkFQyZGroN6+HtBzrZdWde2NAa1Wl1zOVxrB4ByAnjMaWEJlAUWUUs7PI4soXLmR/DxaGK2qroOeq0WruvbGgECqziEJDV2Kf4GeMyyo3rKJQhJHZgyhSS2YVlXXQc/VolVde2OAUC2r5BhLUCj0XPOjA4AlVBZSxSk4fiZBSKyWyb80dhzyWbSqug56rhat6tobA5kEAc+gz+LRB3quOakWKYurxKk4QTZRQOLIZV86BRjyZbSqug56rhat6tobHJVGl1zOM+yzePSBnmsGOGLVG6o4Dc/PIggIbJkCtt4MRKuq66DnatGqrr3BYQiUWUQjOtvQc00HT6oqoUuSsbw0PL+cKZFBvRmaVlXXQc/VolVde4PzpkqMZxnRwqjQc18drkRVQpe8IghyiEI8Syo29CMpICitqq6DnqtFq7r2BieXJBTJjWVwDkDPfT0EMvVbmiS5nJeK41ewZVI49mZ8tKq6DnquFq3q2hsWhVprDM8o0Ad6rpGI5JoyhjSjQvCqgl/GkAplRnQTA6lDq6rroOdq0aquvWGh8xWFVKNY7gsFeu7LEMjUZQxpBl6QUSEoZ0oN/rxcSENoVXUd9FwtWtW1NyyvySJqjVEs94UCPfdZiBWaMoYkDc9Pw/PLGBKBFLbeTIlWVddBz9WiVV17w5JSzje2YRvouYYglGuwDGlGhSANLyihS/hQb6ZJq6rroOdq0aquvQERyzVpOL6hS1EX6LmPIJZr8CxpFlGYUs4vpUt4UpWhSwRpFK2qroOeq0WruvYGhMyVl9Ilhi5FXaDn6iNVasuZ0jQcPx3PL6FLaiRQby2EVlXXQc/VolVdewPyli7hiI2uxoSeQ5GptCSOPJsoTC7nF1JERnixII2kVdV10HO1aFXX3lBodbpsosAIF6OHnpMqNXiWNIckfEUQlBjlvQjka9Gq6jrouVq0qmtvKKpFSuM8ya3Wcwq1rpIjz6gQJGF5sPXWSmhVdR30XC3g88SbgTKGxAgH50Dr85xSo6PUyHNJwjQ8v5AiZguh3loRraqug56rhVKtzSIKAQBGs4Z+CySLKOQaZYuhlXhOodaSufJskjClnJdPFrGFSvhjb4W0qroOeu4/7uawziWwDkYSLiRVPy3mGro4LRO1VpdbKdQa5b9Wy/acSqOjcOVZREFyOb+AImIIFMbzRCRIMxOWzfy3rkusjmsFdR303H88L6nZ/IjvFEpZf49RxjDGjrUWAFesKq4yruW+UFqk59RaHZkrzyEJU3H8vEoRnQ/1BgEJpa2rroOe+w+1Ruf+kLA5SnA5gWrosrRYsEwpmSM3dCneT0vynEqjo9bIX5OEaXj+60ohQ6DUGGcjGmIINFotUtd5t466DnquFvlk0fb7tGqRMY4etQzS8XyjXca+BXhOqwNVPEUWUZBYxsutFNL5CrUG6g3yHvIpou336a2krmtWz2m0IA3Pj3vLjy3iGuf2IK96fzgurtjwJXnv9rSEn14hMN37cplKm1LOM3QpPojpek6j1TEEijdUUTqen0UUUrhyten+SgwNlil9jhUb/J+96es69r7w8qfGWtd9xS0Jy2tWzwkkKuf7FdlMkE030i2zSpNGEGfRdAYvyXu3HCZwfUCQGtOzST+LKp4ilyQ0dCk+iMl5TqsDdL4ilyRKw/MLKGJqjVwFW2+NxiuBmsIy/D97c9R1FSKjreu+4ubypLpZPccTKS+/rGq2w7VILr+skpjsCvFvqGJKjZEOzgHT8ZxOB1hCZSFVnITlZRIEZC7U29fkWjLNuJ4XBWkcR6JJze05rxetYtiz6fB6QTVdz+VVihRGuN7XO4zfc9UiZVGVOB0vyCEKKzkyYz6Zpsu1ZFqNqf6HQd7DoUdE6DkTw3Q9J5CpjXz9BaP1HFuoLKSIU8r5WUQhoVqmVMPWWxMCPdfCgJ4zPb6u57gS9ek4slcCzesFtam3s0/JJ2PIzXAg77SaRwXVX3A2jM1zHLGqkCpOLudlEgQkjlyugq235gB6roUBPWd6NNBzGk2t+lqrfX8VSaiWX03j6ABohk0LgKZZDlQNwJVE2hecWyPxXI1EVUqXpOP5ryoEFWyZzMieut7igZ5rYUDPmR4N9NzOnTunTJmiVCoBAM+ePXNxcXlvMiJH7pvc0iKDajTAP4X+BR80lOfuhQSH3w3ly3VvqOKMCkE2SVjBlspg681AQM+1MKDnTI8Gem7jxo0WFhYXL14EAISFha1YseK9yYgc+dWklua5apUpeU6o0PrfizsTGPO6SoFjSqWw9WZooOdaGCbmOR1cl6/Bntu6dev58+dtbW1ramqePHmyZs2a9yaDntOnOT3Hk6rLGJJXBEERU33pZviDR0+a57iQTwI918IwUs8plcqSkhL0ZTWbffTIES6HI5VIjh49SqO9Z+jl+PHjb968+Xi2IpEIAECj0U6ePCmXyzkcjkqlysrKOnrkSJ3RLAAAiUQ6deqUWCzWarXpaWlv3rwpeEdqampOdjaaUqvVqtVqiVjMZrPRnSdPnMjJyamT54cGyfS/+McTgAZ7bs2aNVlZWSdPnnR2dk5MTISeawjN4Dm+VP2WJknF8VJxfCxDIlZoAADhYXciwu816XEhDafhnuPxeNnvqgKJRKJUKtXqfz+pVqtFIhGXw0ET19TUqFQqtVqtnwahpKSkoqLia34HiB5G6jmtVuvj47Nz507kB0Gj0aZOnSqVSnk83mRHR4Ggbmz6kydPJk6cWFVVJZFInjx58uTJk5iYmJiYmJs3b65du5bz7qf28uXLc+fOvS0uXjB/vlAoXL5sGZVKPXr06PLly+u3FAsLCsaNHYuIZ+aMGXfDwl68Y8/u3RvWr0eSJSQkhIWFhYaGHjhwYPmyZUg+VVVVAwcOjI2JqZNnVnb2zZs3NRoNk8mMiopCCvno0aPo6OiYmJhdu3Zt2rTpk6pruOeeP38uk8kcHBycnZ23bdv23mQf8RybzQ4PDw8ICPD39/f393/58uUnD/oFqFQq9Cbj9evXbm5uyO1IYzBCz4nkaixDmo4XpOH5ZQypqPZRDP48cYg+DfecQqHYs3v30aNHAQD37t3btWtXUFDQ8ePHjx8/HhwcfODAgZUrV6KJjxw+7OLiEhQUFBQU5O3tvWXLlqB3/Prrr15eXk30dQAASqXykzfZxoxCoVAoas3dl0qlDf+4kXoOAMDlcu3t7Wk0mkQiIZPJO3bsEIvFBAJh6dKlJBIpPj4erRyJROKWLVv4fD4AQKFQZGdnFxcXl5SUlJSUlJaWYrFY/TOy+q+/XiYkHNi/PyUl5cWLFwCAtWvXkkgk5F19x+BxuMWLFwMANBrNsqVLqRQK+tb1gADkl4185E5wMIvFunPnzpkzZ5Cdhw8fvn79+r27d5lMpv6XUigUM2bMiIuLEwgEWVlZSCGXL1/u6elZUlKCxWKJRGL9lmUdGui5lStXRkVFAQCCgoLatGmzefPm9yb7iOdCQ0MxGMySJUtWrFixZMmSS5cuffKgX8C8efPQnOPi4hwcHDh6t8BfhvF4TiTXlDOlGRWClHIeliEVfGABa+g5o+Kz+i1JJNKff/4JALhx48Zlb28AgK+v7wkPDwBAZGTkpk2b0JQeHh6BgYHI33l5eXPmzEHf2r9/f1hY2BcXWCgUBgYG0unv/80rlUobG5uYmBgAQGJiYmxs7BcfyCCwWSwHBwc8Hq+/c+XKlTeuX29gDsbrOQCAUqmk0+lXr1718/ObMWNGcHDw1atXx48ff/nyZXc3N25NDQCAw+HcuHGDRqPRqqqQ39aHYDKZd+/eDQkJOXbs2Pjx4+/fv3/y5MmbN28uXbLk0aNH9+/fv3L1qpOTEw6HY7PZEffvX7xwwWH8+DNnzpw/f37x4sWXvb3v3Lnz4MGDiPv3N2/a9M8//6A5T5s2raqqytPTMygoCABQVFTk5OQEAHj9+rWrq2udYvD5fB6v1kLGbm5u0dHRDTwnoMGe2717NyJyrVY7Y8aMPXv2oG9JFP9V5R/xXFBQUPfu3fX3SKVSip7vGQwG2vYiEAh1pE6hUMhkMvpSIBAgNxxkMrmmpgbZSaPRBg4cuH79ejweL5PJAAASSa1HYVVUVFRV/Vc8iUSCZEIikdBM6mNwz4nkGixT+qpCkIbjv6WJaySfWBIees6o+LLxuaCgoBMeHtHR0Rs2bFi1cuXZs2d9fHz279+PJjh9+nRERATyNx6PR+yIcPDgwTt37nxxgUkkUu/evRMTE9/7rkQi6dChA5L/n6tWLViw4IsP9NXZvn371atXP57m5MmTDg4OdXZeu3ZtxIgRDYzYMEbPKRQKFotVWVmZlZWFtLUlEsm+ffsAAHw+f/myZfqJORwO0o25bt263bt3s9lsJpPJZDJramokEgmTyXz69GlwcLBWqxWLxVgstqSkZMCAAVaDB3t5eVVUVPj7+2/ZvJlKpWZlZY20tiZXVsrlcqlUSiAQ4p89mzp1anV1NdLDWV1dDQC4Exycm5MjFovRlh+Hw0FCGffu3fvi+XO5XH7w4EEikYi8u23btsWLF2OxWK1WKxQKmUxmYWEhUlMzmcyioiIAgIuz84MHDxp+DhvoOZWqVt2q/4N49rbmnxfMfIoYAMATqT7iuZ49e+rvodFolpaW169fBwBkZGT06N6dSCKRSKSpU6eOHDly2LBhiNfFYvHKlStHjRo1dOjQZcuWicViAICHh8fy5cv37t07duzYPn363Lx5EwCwYcOGb7/9tmfPnra2tsXFxZmZmQMHDEDSFxQUjB8/fuTIkUOGDFm4cCFy/i9fvjxz5szt27ePGDGid69ewcHB7y25oTwnUWjKmdI0vCAFxy9lSD7UeqsP9JxR0UDPlZeXP3361MvL625YGAAgMDDQ+9IlFot1/PjxI0eO0Gi0oKAg/fvLs2fPOjs7x8fHx8fH+/r6Tp48Of4df/zxB6pABOS27yN70P9o5A+ZTKb/P67fiSWVSrt27Yq0F5VKJVIzqFQqqVQqlUrVavWHPgj0QgrQMUUUuVyOvov+od8dVf8r1MlfqVQOGzbMyclJKpXqf7BOGUYMH37lypU6+XC5XEtLyyy9OImPYIyeI5PJgYGBnp6ekydPRvpkxWKxvufqdzQ/evRo8eLFEokkMDDw7t27ERERJzw8Fi1aFBER4eXldenSJURLfD7/8OHDfn5+G9av9/T0dD5wIDAwMCAgAABQVlb2x+LF+nmWY7GLFy+m0+mvX79ev349nU6Xy+UrV6wIDQ1Vq9U5OTlcLhf54I4dOwAA27Ztw+PxSUlJp06dioiIuHv37o0bN9avX//br7/u379fLpcnJiZev3597JgxxcXFAIDY2FgkNsTVxQXpSRCLRA3pQ7+UQFWr31MXa3U6rQ5odECj1ak0Oi0AcrVOotDIlBqZGvBl2hqJmidVV4tUoVmszY/4a0PIxx5X3slk+iW/f0p1WFhY+/btfXx8/Pz8/Pz8kO5ET0/Pzp07UyiUcePGHT58GADg4OAwf/78mpoaLBaL9NyuW7du2rRpEolELBY7TpqEDA2eOHHC3Nz8/PnzXC43ICDAzMysvLxcJpONGDFi//79SLxPdHT0t99+K5PJJBJJv379tm/fzuPxiETi4MGDlyxZAgC4fOkSBoPx9PSsZrPPnDnToUMH5CrUoZk9J1VqiNWyLKLwFUFQXCXmff5qNdBzRkUDPUcgELKzszdt2oR0V4aEhGzbuvXhw4eHDx8+cuTI+QsXNm/erN+j4+np6eHhgcSy3bt3b/r06Who2+rVq+/d+zcQ6dmzZ5MmThw9evT69esRVWRmZk6ePHn06NGOkyalp6cDAKqrq+fPm+fr62tlZbVz506xWOzg4FBQUAAAuHr16sQJE+zs7MaMGRMaGgoAkMlkXbt2vXv3LgDg0KFD27dtAwCcPn3axsZm4sSJgwYNOnXqFACgtLR01qxZNjY29nZ2SCenTqdbvXr1hQsXbG1t58yZg6pIIBBs3LhxzJgx9vb23t7eAIDNmzefOXNmzuzZ1tbWSqWSRqMtXrx4zJgxdra2ISEhyKf++eefKVOm2NjYjBs3Lj4+HgCwffv29u3bd+/e3c7OLikpCQAQEBAwfvz4sWPHrli+HIk3xOFwXX74QT8sEWX8+PFHjxxpyAU1Rs8hlJWVeXh4CAQCPB6fl5e3du1aHA6XlZU16/ffsVisr68vGs1IIhIHDxq0dOlS/Y+/eP68zh4ymXz9+vWysrLKykpkdC02NrasrOzevXtCoTAmJmbdu9AShJycnL59+169cqW8vHzRokW3bt0KCgqaNm2am5tbUFDQvn37kB/cw4cPZ8yYER0dvXTp0lOnTmVkZMjlcmxZGZfLrampQW6X0Dx1Ot3KFSuQqjkuLg6Z3Obq6uru5hYdHT137txbt2598syci6e8qhC8pUleEQQ5JGFRlbiQIk7B8XNIwgKKKJMgSMXxMyr46XhBRoUgo0JQSBW/rhSl4vjZRGEpQ1pUJb6VwVgXRt0Qztx8B3fhOeVDSggPD2/Xrt2SJUuWLVu2cuVKKpWKfIWZM2f2799/ypQpOp2usrKyTZs2SMMUQSQUfv+//504cSI9PT0jI2Pr1q39+/cHABw+fHjIkCFoMktLSx8fHwDA6NGjDx06hOx8/Phx586dAQDP4uO/+/ZbpGEHAHj06BGy3+vixUGDBiE7mSyWpaVlXl5e/ZI3j+ckSm05U5qB56fh+W9pEo74y59XCT1nVHxWv6WXlxdSR9++ffvsmTM5ublv377NycnJzMwMCwvbtWsXmtLN1RUdG6NQKKtXr0bfOnr0KNI5IRQKu3fr5ufnh8fjL1++zOVyKRRKjx49zp07RyAQTpw40a1bNy6Xy+Px2rZtO3DgwPDw8MKCgsrKyjYWFskpKQCACxcuREVFUanUCxcuIDeCWq0W9dyyZct+mTIFAMBkMnE43KtXr8zNzSMjI+Vy+ZAhQ5wPHKisrAwKCurSpUtpaSkAwMrKqmPHjkFBQdnZ2WhVtnTp0rFjxxYXFz9//nzPnj06nW7G9OkWFhZeXl4pyckSicTe3n79+vUVFRWPHj3q2LEjUlWePXMmISGBQqEcOXKka9euYrGYRqNZW1uvXr0aj8dLJJKIiAhLS8uXL18SicSFCxdOnz4dABDz5Em3bt3qDGcgODk5zZo1qyHXyHg9l5+ff/LkSSwWGx4eHhIS8ssvv0RHRwcHB0+cMOHhw4f+fn5IOC+VQvnH0/PKlSv6nd0AgLjY2Dozo/F4fFVVlUKh2Lljx6FDh4RCIQ6HAwCEhoTk5eX5+vqiQ25MJvPkyZOTJk50cHDQ6XRYLHb9unXIW7t37UpLS9PPlkwm5+bmUqlUgUDw+++/h4SEEInEN2/eREdFAQCwWOz8+fOFwn+fuCaVSpctXYp0wT179uzcuXMAABcXFx8fHzweT6FQkLc+zsXnVBpHzpeq+VK1WKGRq7QylVam1Ki1Oi2yfarPOg3P3xxBv/2KKZSpeUKl7wfac/X7LRG8vb0xGMxBd3cAQGFhYdu2bREFIrDZ7Pbt29vZ2U2bNm3atGm//PLLgQMHAAAHDx4cM2YMmgy9ixw1apS7uzuyE/Xc3bt3f+zZUy7/9wk+6enp3377LQDAy8tr6NChyE4Wi9WzZ8/6kzdAE3tOodaSOLIsoiAJyy+qapTeUKDnjIrP8tw///yDtE5u3759KzDQw8PjypUr3t7emzdtevbsmb7ntmzZcvLkycTERKRr55dffkl8x9KlS8PDwwEAIpGo148/7tmzB63ZT5061b9/fyaTSaPRSCRSx44do6KiFArFd999h4auEInEzp06paamosdiMBjpaWmdOnbMz88HAKCeW7169e8zZ6LJ1qxZg4TDPHjwoHPnzkglyWKx+vXr5+npCQDo27cv0m2Dwmazv23Xrk709eTJkxe96w9LTU395ptvCgsLaTQau7ra2tpaP9ibwWA8f/7cwsICmUfh4OCA9NUBACZOnLh8+XI2m02n0yMjIzt27KhUKoOCgnr16vXeM79v3z5bW9uGXCOj9hx6ft++fbtz506ADPzo2Uuj0WSkp3O53IyMjKVLluh/vL7nqqqqbty4cfXqVRsbm+vXrx86dGju3LkAgIKCglOnTi1fvhz9leTn569atSouLg7pK7t3756bm1tubm5hYeHcOXOuXbuWkZFR5zITicSysrJly5YRiUQ3Nzcqlbp06VI+n3/nzp21a9ag7X2pVLp0yRKBQKDT6Z48eXL+/HkAgLOzMxIY2UC8XlAVikbNYq3iKUicf7vOPxKHEhwc3KNHj7qfrar6+eefnZ2dLS0tyWQyl8tt166dvvulUmm3rl0fPnxY54OHDh0aOHAgmqZdu3bIP/bw4cOPHTuG7I+OjkY8l5iYaGFhgUaa+Pv7d+vWDQBw8cKFIUOGIMMJDAajZ8+eubm59UveFJ6Tq7TEalkOUZhRISiqEleLPj3TseFAzxkVn+U5T0/P1NRUrVZ78eLF6Kiow4cPk8lkGo12+tSply9fIhUXwvJly/yuXcvOzs7Ozg4JCfntt9+y37Fq1arwdz+AzMxMR0fHfv36nTp1SqfTubq6du7c2d7e3s7Ozs7ObtCgQRnp6RKJpMsPP6CBJyQSqXOnTqlpaQCABw8ejB071t7e3tra2szM7COee/ny5XfffVdZWQkA8PHxadu2rYODg52dnb29vZWVFTJe2K9fP19fX/3vW1paamlpWacj0dHRcfe7kciIiAgLC4vxelkhPTc3b94cOXLk+PHjhw8f/t133xEIBACAvb09eisw0tp64MCB9vb29vb2Y8eMcXBwUKvVN2/e7N2793vP/P79+8eNG9eQa2S8nispKfn777+Rvw8cOID0DDAZjKVLlqC3+ejw6bNnz5bV7qWs7zmEq1eunD51CgCwZ88etHb+9ddfZ0yfXicltqxszuzZAABnZ+fY2Nh58+ZFRkY+ffo0Pj5+9+7dFj7EJQAAIABJREFUSJ+DRCLZvGnTli1bgm7fzs3NXbt2rVardXJyio6OXr16dXh4+OlTp/Rnr0skkrVr1pSVlb18+TImJubChQtI/k0Rh9JAPuK5W7dumZubp6SkZGVlZWRk4HA4nU43bepU5P5gwYIFY8aO1el0CxcuHDFiRFJSUkhICDJ7wcXFpXevXpGRkTk5OdevX0f6as6cOYPBYDZt2pSUlLR0yZLevXsjcadz5swZP378s2fPGAxGTEwMxsxMKpXK5fLhw4dPmzYtOTk5PDz8f//738ULFwAAJzw8+vTpg1x3Op3eoUOHrKys+iX/ip5TqLWVXHkWQZCE5eWThSzh19QbCvScUfFZnvPx8QkICIiKinJ1ccHh8fv27bt48aKXl9dBd/fExETUcwqFYsmSJeitW3l5+apVq9BM3N3d68RbJiUlffPNNykpKefPnRtpbQ0A0Gg0aI3HoNN/+P57pB0J3nkuJzdXIBBYWFhcv35dpVJRqdROnTohHR71PadSqaysrJDRNQBAcHBw9+7dkdASNEpAp9P169cPTYNAJpPbtm2bkZGhv9PR0XHb9u3I37GxsW3btkX6S9Fb/LKysm+++SYsLEyr1RYXF7dt2xZpz40bNw7p7wEAjB0zxtnZGdQOZgkJCenatWudyXMIW7ZscXR0/Ni1eYfxei4wMHD16tVsNjs1NRWNRGIxGHNmz64TSQgAiI+Pr+O5lwkJy5cvr59tcXHxk8ePZ8+ePWDAAORSCYXCcePGTZs2rc7ENWxZ2eLFiykUyt69e5EAQvStiPDw48ePAwCUSmXUo0fI1D0KhYLEgu7fv//atWsxMTFPnjypEyakVCimTJmyfPny6urqjIwMZGZoE80raCAf8Vx6ejoyUj1p0qQJEyYcO3aMRCI5OjoiN4AUCsXezq6goEAsFm/ZssXe3n769OnIuLdGozl79uzEiRMdHR1nzZr1/PlzAMCRI0eGDh165vRpe3v733//HYvFIkcpLS2dOnXqxIkT8Xh8cXHx7NmzkbH3qqqqNWvWjB8/ftq0aUhwJgDg7t27aO1QXV09d+5cpPO5Do3xHLJ6slqrI3PlOSRhGp7/hvqVW2/1gZ4zKj7Lc/v27Rs4cGB+fv6hQ4dUKpWHh0d0dHRGRkZScnJSUhISpAYAePPmDdpBBwAoLCxcphc6jnqOQCBcunSJTCaXlZV16tQpISGBQCB89913165do9PpOBzu/v37MpmMzWJ9265dXFwc8nECgfBNmzZZ2dk8Hg+Dwdy6dYtKpR44cACDwbx+/RoAgM4rWL58+dSpUwEAR48e7dO7N4VCoVAoXC6XyWR269YN6Ysik8nR0dHI6k7dunVDbsfLy8t37txJo9F0Ot2kSZMmTpxIIBAyMzOPHj2q0+kmODhsfDdTkM/nDxw4cNu2bRQKhUqlIoOFOBzOwsLi8ePHFRUVGzduxGAwiOdmzZo1depULBbL4XB8fHz+97//JSQkMJnM3Nzcp0+fAgDy8/M7d+pUZ/IcwowZM9DT+3GM0XNSqdTV1RUZnNu7d++hQ4eQ2eJarVYkEvn6+spkMoFAQKFQ0PuOZ8+eodGSRCLx7du3Af7+deJQEGg02sWLFz09PRMSEjZs2ICMo8bHxx87dmzChAmpqalSqVSr1eJwuMjIyIULFvj4+GRmZQEA5s+fn5mZiczs9jh+HG1rAgCKiori4+N37NiBNMAZDAYSmpienp6SkkKhUNA2vlqtHjt27K1bt/B4vI+Pz44dO/TniWdkZBw4cIDFYn38/DSb5+pTPxy04YssODs7Dx8+/DNK1gga47lSujSfIkrF8XNJQqZA2TxLqkLPGRWf228ZFRWVlJSE3I4jMfFcLrewsPDvv//esmULkszb2xuZz4qAzhOvqKgoKyubPXs2co9Io9Fmz549ZsyYcePGHT9+HAn9iIyMHDN69Lhx48aOGbN8+XKpVCoUCEaOHIn2SNFotBHDh+e+fg0AuHnz5rBhw2xtbNavXz9hwoTioiIAgI2NDdKtsm/fvnVOTgCApUuXDhkyxMHBYezYsYiA09LSJk+ePGrUqDGjR/8+cyYy6O7o6BgcFAQASEhI6Ny5MxJxRiGT586dO3LkSBsbm5MnTwIAVq5YceTd0hkAgOLi4l9++WXkyJF2trbTpk1DQlo8PT0HDx5sZ2e3cePGyZMnI/2W2dnZQ4cOtba2Rr7Lsb//HjFihI2NzahRo06cOAEAUCqVvXv3RoNRURQKxY8//tjAFoIxeo5IJG7fvh25wDwe7/Tp04sWLVq8ePG8uXPnzJmzcOHCCRMmTHZ0jI+PR+N/4uLi0PZWWVnZwYMH27dvX2f6YVVVVXR09PWAgMLCQmTPixcvzp8/j3/XIHB1cbGztS3HYnU6HXKdNmzY8OTJEwCAUCCYNGlSREQEslLX7l27kKuLUF1dvWfPHhsbGxaLFRsbe+fOndDQ0KCgoNOnTwcGBrq6urq6uKBFZTKZfD7/3r170dHRyNJf6Lpfjx49unnzpv606PdiQM81hmPHjtnb2TXDgcDne06p1pK58txK4fVUekaFgC5QarTNumI49JxR8bnzxLVabWRkpP5qSgKBICEhwd7eHpEfnU739/fXvynE4XDIuFdRUdE6J6cO7dujPRwAAB6PV39dq5qaGjQCWafTKRQK/Qz1XyqVSmRWsUajQXai636pVCqkP0ypVIrF4pqaGv1skUMjHVRoVmi2dToPeTweOoSkv7CnfoI6azRKpVLkWGq1Wn9mHhqph5SwpqZG/1gbNmxYtGhRnczj4+N79OjRwDUCjdFz9dFoNDQaDVtWlp+fX1BQ8ObNG3QiNgKbzUY601CyMjPr9ENyuVz9BaUIBEL9ORn6PaIikQg9iWKxODk5GX1LIBDUaXXpdDrkszKZDLnkyFVvijXlTNRzAoGAVXvBlKajgZ7T6gCdr8gmCZPL+XlkEUuoTMcLlBoDPBMDes6o+FzP1ZlqjYJW1mwWS78qr4NYLEZvviH1KSoq6tu3b53l+xctWrRv794G5mAanoPo89U955fyJY/eNmZE4GOe02h1NL6igCJKw/MLKGIaX4E23jKN43niEMMCn8tjbBQUFNRZ5+/169cSvWbox4GeMz2+rudIHPn5ZB5JAkjilrO9EQPvhLqNVK0OVPEU2URhIrbmdaWQWiNXaeq2tg31PHHoOaMCeq6FAT1nenxdz0kUmns5rDtZ7DuZzBaz3csX5lb+202kA4AlVBZSxWl4fhZRQOUp1B/umYSegwDouRYH9Jzp8XU914JhCpT5ZFEKjv+6UkjhypXqT4+VQs9BAPRciwN6zvSAnvsIOp2OJVQiY2/ZRCGJI5OrPiMUCHoOAqDnWhzQc6YH9Nx74YpVhVRxRoUgiyggN6z1Vh/oOQiAnmtxGMBz3gnQc43COwF67j+qxaqiKnEqjv+KIMSzPq/1Vh/oOQgA4FoyraGRfBBT4HBUM3tOrDoSReKoQbXKSDeWHLDkhi/GhzaOGhyJIkoa/ADPlkq1SFVIEaXiBVlEIaFaJlV+HTlBz0EAABdfUImG/k9vjk0JWDJDl6FZtiPPuM3qOYVKG/SKGZDO8k+hG+fm+Yz8zzOywYvxoe16Ojski/WRiMGWDV+qLqFLkst5ryoEBHZjW2/1gZ6DAAASsbyb2XyD/7M39XY1iebxpNLgxWiGLSCV3qyeM34quXJKjdzQpYDUgitRldIlGRWCTIIAx5JKlV9/lRkE6DlIqyKX9MFVWloY0HO1wDKlOFbdleUgBoEvVRdViVPK+Wl4Pp4lFSua3EDQc5DWg1SpzagQfDpdiwB6rhbQcwZHJNdgGZJ0PP9VhQDHkkqaXm8o0HOQ1gP0XOsFes5QCKTqEpokFcdPw/HLmRKRIXwDPQdpPUDPtV6g55oZkVyDZUhfVQgyKvildInAoKGk0HOQ1gP03P+3d95xTV3947d9nq/avmptbatW2zrqqLZWW/eoE7e/qigO3LipG0Wttq4qiriligOtgqCgoqIVwQWEKRtlJYGEkD3uzM3NHef3x9U8FNTaGgwk5/06f9ycnNz7uTdw3znnnuG6QM+9GUiaK1KR8UUmUQlSoCQdUnurDvQcxHWAnnNdoOdqFNzCFqlJUQmSUIzklON63Pr3n3mDQM9BXAfoOdcFeq4mwC1soYpMLEHji015CsJA1NJx7tBzENcBes51gZ6zI5SVk2jNohLkQaEpT0EYa/10ZdBzENcBes51qe45o9F46tQpjuMAABqNJjg4mOdddDqSV8RMcyUac5IYiS8y5ZTjWox2dESvCvQcxHWAnnNdqnuOoqi+ffuGhIQAANasWTMHXq4XQFk5qY5KLDHdLzRlyXFN3dGbDeg5iOsAPee6PLfdMjY2dujQoTKZ7LvvvpPL4XoLf4Fm+DI9lSJFE4qR3HJCVwf1ZgN6DuI6QM+5Li96Pjdz5sxu3bpt2bLljUdUS7EwXKmOSpYg9wqMj8owDUY7QWsu9BzEdYCec11e5LnY2NiPPvrIaDS++ZBqFVaWkxssKRIkoRjJluMqxBn0ZgN6DuI6QM+5Li/yXE5OzoABA4TeKC4Iw/HlRkuqFL1XYMyS42q0DjdOvgToOYjrAD3nurzIc6mpqZ07d6Zp57y/vwgry8sMVHop+qDIlFaKKYwWlnOi6ls1oOcgrgP0nOvyIs/p9fro6GgXqc+xHC/TUykS9GGR6VEZqjBZXGRlV+g5iOsAPee6uPI4cR4AFUpnyvCHRaZUKVphsjh15e05QM9BXAfoOdfFBT3H86DCZEkvRe8XGFMkiNxAWVmXqLZWB3oO4jpAz7kuRWpzicbs6CjeBDwAapTOlGGJJUh6KVqqM1tdo3HyJUDPQVwH6DlXhOMAx/NPlEShiuB43omfSKkRS6YMu/vEmCpF5QYK6s0G9BzEdTBbeRH0nKuhQekt10p9L0t9I6W/RJWW6p2qVsfzvBqls+X4vUKjqAQRa8yU1UUbJ18C9BzEdWBYPlWKOjqKNwT03FM4HuyMLlsYqV8Qofv1mtRpOtBrMWuWHH9YZEovxUp1FNTbS4Ceg7gIF9PUB+9rf7kqOfxA+2ee3tHh1DjQc/9DrDHPPiuee77scQXh6FheFz1uzS3HHxQZRSUorL29ItBzEBfhVq5+8VV0bohs/kV1rgJ3dDg1DvTcXzhwR7b7Vpmjo/j3aDE6pxyPL0ZEJUix2kzQDrhr112g5yAuAsPx6y6VLLxs3Bcjc3Qsb4La5bkUKRqRhYSnqR2UNLtvle28WXYxXeOoGC6ma69n62nmn7WaGknmcQXxsBhJEiMlGjNJw9rbvwF6DuI6JJYgC8IqyvQWRwfyJqhdnvO7VZaDgQKTw1Kehs1Tsw4MoBABW29WqJFXmmDMRFofK8mEYkQkRko0pBk2Tr4e0HOQKqBm5kCs/PC9ikNx5U6WAmJkS889OezoMGoiHU0wZsqwyt9j7fLc4bvl8FZ99J5CZXqZ5xAz87iCeFBkjC82PVESmCNuzU4J9BykCnIDtTdOTQJAOF3COWAycwTv+EjsntIMIPKRpvL3WOs8hztJP8d/z6G48ud6DjGzBUoySYwkS9AiNYmamTcfm3MDPQepgtxAHblb7ugoIP+MXB24mqmtnAM9V+uo4jncwhYoyQdFpnsFxkIViVtg7a2mgJ6DVEFuoA7FQc/VMTI10HO1nsNx5UbMilvYQhUpEiOiEiRPQRgJq6Pjcn6g5yBVgJ6ri0DP1QEO3624kaUTiZECFYnAxsk3CPQcpArQc3UR6Lk6wMG48kKla62ZUEuAnoNUAXquLgI9Vwc4FFeue7VxBRD7Aj0HqQL0XF0Eeu7fYLW+0WdjL+pvCalpoOcgVYCeq4s4red++umnBw8emEwmHMexZ6hUKqlU+tzyhYWFc2bPxvFXmtgtODj42LFjHPfCoX2HDh06fPjwc98KDQ3NzMx8laP8b2/Qcw4Ceg5ShZrzHIqitvsPx3Evub0AACwWi9lch1dQoWkaRVGef0OVGOf0XGlp6ddff11RUbFmzZqdO3eee8bs2bPnPDs7iqIeP36cn5+fn5//5MkTX1/fTp06ZWRk5D9jx44d/nv2sOxzbnMYhrVu3bqkpORFAQwdMmTPnj35+fllZWUFBQXh4eGhoaHCW7Nmzbp08eI/Oh3oOUcBPQepQs157ty5cwsXLhS2EQTx8PDIz89/UeHFixfv2rWrSibP848ePXrFH+v2xWq1JiQkCHfLixcvHjlyJCwsLPj06cjIyODg4MjIyG3btkVFRdnKR0VFTZ06VSh/7ty548ePR0ZGRkZG+vn5bd++3e7hOafnbBdr7pw5IpHIlh8QELB7925h22QyXbx48caNGzdu3Lh69Wr79u2DgoJu3boVHR0dHR1969at8PDwS5cu0fRTwZw7d+7PP/+8d+9eXFxcXFzcypUrr1+/HhMTc/v27bi4uJ9++ikvL08oKZFIPCZPLigoiI6OHjx48O7du8PDw69du1ZWWkrT9LKffoq9c+cfnQ70nKOAnoNUoeY8FxQU5OvrK2ybTKaBP/wgkz1/SuU7d+5MmTJFq9UCAC5evHjq1KmzZ8+ePXv29OnTc+bMSUhIqInwXg7P80eOHJkxYwbP8/7+/tu3b4+4dGmKh4dMJps2bZpUKv3pp58OHjxoK79y5cozZ85wHMey7JIlS4KCgnQ6nU6n++2335YtW2b38JzQczRNT5gwQfgTWTB//qNHj/63t8OHbZ6rzPXr1728vKpkkuT/ujgmJye7u7tnZmZevXo1NTU1Pz//+vXre/fuTU1NzczMPHbs2Ndff20T6qFDhzb9/LOwPXXKFNtORo4cmZ+Xt3bt2pjbt//RGUHPOQroOUgVasJzVquVoqjAwMDNmzdLpVIURQEAMz09hQ2L5S8TK0skkrVr1xoMBpZleZ4nCMJisTAMwzDMcxufXh+WZUtKSiiKenkxjUYzaNAghmHOnDlz8eLFvNxc33XrAADr1q0DAOzfv//y5csAgMTExFOnTn3//ffBwcHbt28PDQ1du3btnj17MjIyMjIyfHx8tm7davdTcELPXbhwoXmzZnqdDgAwfdq0HTt2XL16NSQkJCoqatq0aX5+flXKFxUVTZw48erVq8LPopCQkLCwMA8Pj169ehmNRqHMwoULt2zZAgBIT0sbPXp0RUVFdHR0z549hXeTkpIw7OkkoRzL9u3Tx9PTEwCQnJw8bNiw6OjoVatWRUdHT58+HcfxVatWQc/VFaDnIFWwu+esVmvw6dNnz5718vKaPHny9u3bt2/blpKSMnDgwLALF06eODHFw8PWqkQQREREhMFgoGl66NChL6rw2ReKopo1a/Yq1UShg96OHTvmz59/8ODBqVOmCHfdK1euTJw48fz58wAAg8Hwxx9/zJ07Ny0tTaVSAQB27dp19OjRtLS0tLS0AwcOVG7etBfO5jmVUrl27doJEyYYDAYAwPFjx0Qi0Z07dwYMGFBSUvLnn38+fvy4ykfGjx+/f98+20uLxRIfH+/v7y8uKbH9PkJRFEVRk8kEAPDx8bl9+/aFCxdmzZpVPYCYmJjp06fv378fAOC3a1dUVFRhYWHPnj1TUlJmzJiBYRj0XB0Ceg5ShZqozzEMAwA4derUjh07AABpqamPHj0aOWJETk5O1NWrcyrdkG2Vto0bN65evTo1NTUuLu7u3bt37969f//+3bt3Q0NDp0yZIvgDACAWi6OionJzcwEALMtmZ2czDCMSiWxd4fLz86OiooqKimyHQBAkNjY2KipK6LJnNptDQkLefeedjRs33rx5U+j8QpLkzejo2NhYobMMz/MIghgMhuLiYgRBIiMjIyIipFJp//79z549azQalUplTExMQUGBcIi1a9fGxsYuXrw4Py8vMzPz0qVLDx48EDyXmJh4+/bt9b6+crncjlfYqTxntVqvXbsmkUiWL1umUqlslqqoqJg+fbqwbbFYsrOzbf18YmJiGjduXLkD5G4/v4ULFlTfOYZhy5cvDzx6VHi5c+dOoVZeGRRFw8PD79+/7+/vbzabPTw8lEqlUqmcMGECAGDSpEnQc3UL6DlIFWru+VxYWJi3t3dCfLxgqZkzZwIAYmNjhZakyty8efOrr76iKCojI+Phw4cpKSlxcXFdu3a9fv16cnKySCQSGjwDAgI+++wzNze3tm3bHj58mGGYzp07jxw5sm2bNgsWLAAA+Pr6dmjf3s3N7fPPP9+7dy8AQCaTff/99/379x8yZMjHH38cFRVlNBpHjBjx9ttvd+vWberUqRiGPX78uEuXLv379+/Ro0fv3r2VSiVN08HBwefOnevdu/f9+/eFIH/77beePXsmJiY+fvw4NTX1wYMHQv6jR4969+6dnJw8bdq0/fv379mzx9vbe/369YmJiYmJiatWrZo3b15iYqLRYLDjtXUqzwl9VQEAS5cuffDgwcmTJ8+ePRsWFjZ69Oh27doFBAScP3/+8OHDK1asEGp7SSLRunXrpk+fficmRqFQyGQymUy2eNGitWvXyuXy3Nzc3X5+er3etn+pVNr9+++FWt3SpUuDgoJsbyUnJ5vNZhzHKYpKTU318/O7e/dudHT06tWrt23btm3bNgDAxIkTYbtl3QJ6DlKFmvAcy7JJSUmenp7Dhg1LTU3NysqKiYkRegxERET8+uuvlQsXPHniMXnyN998o1QqbZlWq3XUqFGGSm4oLCz8v//+9/r16wAAsVh8584dkiTfe++9gQMHIgjCcdyVK1c++OAD4f6Wlpb2/vvvSyQSk8kkVP4AAMuWLevTpw8AAMOwj5o0iYmJAQDwPN+zR48NGzYIZYYMGVK5Z4Onp2dpaSkA4Pz585MnT05LS4uNjX348OHgwYOFRzkAgKysrCNHjty5c2fEiBFBQUH5+fkH9u9funSp0N9ywYIFAQEB9r28wMk8Z2O+l1dFRYVQp36UkfH5559PmjTp8uXLggUFMh492hcQgOO4r6/vxfDwS5cuCRfa3d191qxZkZGRoaGhu3fvFovFDMOEhoaeOXMmPDx8586dp0+fvnDhQq9evX799dfz58+fO3fu999/Hzx48I0bN4Q9JyQkbN68WfgrvHfv3oABA4RmgdGjRxsMhtWrV0PP1RWg5yBVsLvnOJadMWPGlClT5syZ4+/vDwCQyWQrVqzo3LlzRUVFbGysTSoAAJVKdfDgwdzc3DFjxlT+CY4gyIgRIxQKhS0nMDCwZcuWlQ9kMBjee++9W7duCS8XLFjQunXrwMDA/fv3+/v716tX7+bNmwAAjuMiIyMPHDgwZsyYb7t0AQAYjcaPmjSJjo4GAJSXlzdo0GCNj8/BgwePHDkyePDgzp072w7h6ekpEYvj4uIOHDiwceNG4ZaYlpY2dOhQQ7X6mbe3t9Fo5Hl+w/r1gUePCkOc9+3bB8cVvCrzvbw0Gg0AwErT06ZOPXXq1PLly3NycoS6OQCA47jHjx8LzeJLly69ExNj++zWLVsq938FAPA8r1arTSYThmE0TZvN5oyMjC+++CIpKUnYg9ATSdgGACQkJNi+qsuXL69auVLYyaRJk4QhfdBzdQXoOUgVaqI+l5mZyfN8WFjYpk2bhJx9+/Z5enr+MGDAnj17Vq5YAQCwWq0Mw8hkMhzHaZoeNGiQTqez7aG65/bv39+mTZvKRzEajY0aNbL9HPecPr1NmzZeXl5z586dO3fusmXL5HK5VCrt1q1b//79586d27Nnz++6dQMA6PX6j5o0ET5YVFRUv379SZMmCZ9avHjxmTNnbIeYOXNmVlaWWCwGAKSnpe3bty8zM3O4m1t2VlaVUy4oKBg2bJifn19KSsqmn39euHBhSEhISEjI3Llz9+zZY7cr+wzn9NyC+fOFwSV+u3adCApSqVQeHh4AgPXr1+/cubPKRANz5869U2lA25Zff33u2AMbDMMMHTrUx8fn4MGDM2bMCA0NrTKqPyEhQXieLJfL58yZI7S28zwv9N5cvnw59FxdAXoOUoWaez534sSJzZs3AwB0Op27uzsA4PLly35+fkLDYGJiok1jCIIMHjz45Z67efNmw4YNbXU+kiAEzwktmQCATZs2denSpUoMGzZsaNGihbDt7+/foX17AIBer2/03nv37t0TDvTOO+9UrhhUZuzYsZW7gIaFhU2bNs3WECpw5cqVYcOGeXt7//DDD8JA+M2bNh0/dgwAwLLsoUOHfH19T58+XVhY+E8u3t/ghJ7jOO7HH39UqlRXr1499vvvAIDCwkL3SZMAAARBuA0bNm3qVNuAAQDAxIkThaZnjUaTlZk5b+7cnTt3vmjnIpFowoQJPj4+wstbt2517dq1S5cuwk8YgYcPH/r4+KjV6h07dti6GAlHR1F07ty5t27e/EdnBD3nKKDnIFWoOc+FhoYK9bkdO3ZU/va9vb2vXr0aHBxsG7xU3XMAgBEjRlTuo2g2m3v27NmjR4+jR496TJ68fds2lmXr1at3OTLy6YnI5a2++GLs2LFHjx7dtm3b4sWLWZaNjo5u0KDBzp07t2/f/vHHH7f78ksAAMMwnTp1cnNz27t3L0mS/v7+zZo1++2334KCghYsWHDhwgVhb0ePHPFdty4kJEShUDx58uTMmTMhISHVTzM/P19oO12xYsWdO3dCQ0O3bt164sSJpKSk9PT0lStWTJ8+/ejRozk5OXa8tk7oOZIkR4wYcfPmTVFiopCTn58/adIkYRvH8ezsbFtXTJ7nPT09haEhFQrFurVrm37yiSgpqfIOGYZRKBR3794NCAjw8fGxdSgSMJvNI0aMEHqaCFy/fn2Kh8e9e/eqdI3Nzc1duXJl27ZtXzTH5ouAnnMU0HOQKtSE5xQKRWRExMSJE/337s3IyDhw4EDld6VSaceOHbt37257MoIgSJ8+fYQmK4lEEhwcvHXr1u+//94mQluxDevXe3hvz1awAAAgAElEQVR4bNq0qby8nOM4Hx+fynOJlZeX+/r6enh4zJo16+zZs0K7VERExKRJk9auXRsZGen/rAkxNzd31qxZa9asEQatCxW1qVOn/rxxY3FxMcuynp6eQjNYWlra3DlzPD09Dx48KBKJ7t27FxsXFx0dffbs2fPnz9ue0vE8P3PmzOzsbJuthWa2wMBA+HzulbBarU+ePKk8eh/DsOJKA0Qqw3FcaWmp7Q8IAFB91kqKotLS0jIyMip3cKpyRLVabXv5ktmidXp99QF8fwv0nKOAnoNUoSY8h2FYaGhon969Iy5dunXrVuXbkUBWVtbChQsrKiqEl0aj0cvLS+hVR5KkSCTq2bPnS1qh3gAIgti2CYK4ceOGn5+ft7f3xAkThgwZMnDgwB49epw4ccJ2W2ZZdsGCBZWbwQSCg4MPHTpk9/Cc0HPOR3XPcW9qnm8XB3oOUoWaa7cUJvF6SQFbxwKWZassDfbGJv63FxzHVe79boMkySrznNkF6Lk6wMFYuRaxAgBIms2S42dSDJczdX/7KcjrAz0HqQJcf64uAj1XBwi8ryhRkccfKJZeEM85V7r0OhmepnF0UC4B9BykCtBzdRHouTrA4bsKLUKnSlHvMOn8i+o556Tnk1UpEjRThuWU4xKtWYXQuMUBt2OnB3oOUgXouboI9Fwd4FBcuRqxAgAMuPX3h+q552USHUUznIGwlumpPAWRXoqJSpD7hcYkMZJRhhapSTVKYxTLci5/7V4P6DlIFaDn6iLQc3WAKv1QEoqR59beGI43kYzcQD1REmmlmKgESShBUqVohgwrVJEyA4WYGQaa758APQepAvRcXaQOeA62xx29p/h34woYjidptsJkKVSRmTJMVII8KDSKSpC0UjRPgSuMFj1htTDc3+/IVYGeg1QBeq4uUts953errMAMpLjDkhgBYsSRAUgJsP2WUo3YZ/wczwPcwqpRWqI15ymItFI0sQSJLzalSJAsOSbWmHWYlaThT4unQM9BqiA3UEfuKv6+HKQ2kauv3Z5LKEEuZCDnklSOSvvvyA/GljswgPMp2kvpGspaU7UuHgCa4fSEVaqj8hVEsgSNL0YSS5AUCZolx8VasxKhCQvrms2d0HOQKsgNlH+cBuGAUyYjA4y048Owe0rWg4hHf+mjXrs853DKDJTcSP19OeeCYjjhUV+BksyU4QnFpvhiU7IETS9FC5REhcliIhmrC7gPeg5SBZxiA+8rAu8rj94td76097b8t+hSh4dh93RcZMwpxyt/j9Bzf6FARRapSUdH4XhYjkcpVmGyFKnIR2VYshgRlSApEjS9FHuiJKQ6ykBYacbZzAc9B3EpNBidX/GyOVmcBui5vwA99yJYjicsrAqlizVkTjmeJEYeFpkSS5AUCZKnwEt1Zg1G11xz65sBeg7iUpQbLVly/O/L1X2g5/4C9Nw/gqRZLWaVaM3ZcjxViorESIoETZYg2XK8WG1WozRhYevQXHzQcxCXAnrORYGee00YjtfjVpmBeqIk00qxxBIkodiUJEbyFIREa1aYLBjF1Nrx7NBzEJcCes5FgZ6zOxaGQ81MhclSpCYzZJhIjAg9XB6VYk+UpNxoMRJWK1srGjyh5yAuBfSciwI992bAKFaJWIrVZKYMSxIj8cWmhGJTWilarDaX6SkjyZgd8agPeg7iUkDPuSjQcw6B44GZ5tQoXaancsvxJDESX2RKLEGSxUhuOS7RPu3kUtPNndBzEJcCes5FgZ6rPVBWzkAwZXoqV4FnyfEUCZpYgiSJkVwFIdaaNSiNmu38qA96DuJSQM+5KNBztRmG5Q2EVYnQxWoyowwTPWvwzJRhBUpSZqBwC/s649mh5yAuBfSciwI9V7ewsjxGseXGp1NXp0rRJDEiEiNpUjRfQZTqzHrcSr9yJxfoOYhLAT3nokDPOQG45emoviw5liJBHxaZRCVIpgx7oiTEGrORtJL0880HPQdxKaDnXBToOaeEZjgd/nSV2owyLK0US5GgopKn49lVKE1aWJYHKRLU4ojJzKDnIA4Bes5FgZ5zESwMZzIzcoMlT0Gkl6IJxYioBDmXpEqVokVqUpi6mntTM7lAz0EcAvSciwI957JwHB/3xFiiMRepyWw5niJBk8RofLEpvRR9rCTKjRbEzNTQKrXQcxCHAD3nokDPuTLJYrTyozuW4wmaVSJ0icacpyBSJGhCMZIiQTNkWIGKLNVTGtQ+U1dDz0EcAvSciwI958q8Sj8UkuaMJFOmp3LK8VQp+rDI+LDIlCJBc+R4md5iIKy45R/3ZIGegzgE6DkXBXrOlfl3/S0tVk6LW2V6qlBFZsvxJDGSWIykSdE8BV6kJitMNEYxL5/AE3oO4hCg51wU6DlXxl7jCoRRfQqT5YmSzCjDEopNKRIkWYJmlGEFKlKF0kaSYSrN5HIh5PzFsLDXPy4E8o+AnnNRitRkiQZ6zkWpufFzPA9QilUhdJGazK8gMsqwxBJTfDGSXoo9VlHHz1y4cOmKmXbA0D2IKwM953JYGc5s5XLK8TwFTtJsXV8aG/IveJPjxHkAzFZOjdISPX38/OXDobeyFFSqFE2TornleKmO0mK0peanroa4MtBzLocWs66LEC8PEy8PE/tcksgMlKMjgrxpHDUfyoXzf0SEhwIAKCtnIhmpjipUkVlyPLEEiS82JYuRTBkm1pg1qBU1M28+PIizojBasqHnXAqeB/vvyBdE6BZc0u6+JXN0OBAHUAvn/bKyvB63yvTU4woiswxLEqPJEjRZgmaWYYUqUhjV9zpTV0NcGS1GP64gHB3FmwB67n/I9dTsM8Vz/pCINWZHxwJxALXQc9VhWB63sHIDVaIxZ8rwhGJTQjGSWIJklGHFalJhovW41b7LFUGcD5JmgxNV++Mqdt0sOxavyVM4ue2g5/5C4L3yfTGwMuei1AnPVYfjAUYxOswq0VIFSjJFggopowzLluNSnVmHW80vmLoa4prwPAiIkS++is4PV845U6jFaEdHVLPUuOdSpei5dOR0grL2p1MJyp3RpdtvlJ5KqHB4MH+fElVnk9RGwlqjX59LUUc991wsDKfFaKnWnKcgksWIqAR5WGRKL8WeKAmpjlKjtJnmYLXPlUFIZnGo2CtMGffE4OhYapwa99zv9xU5BFBQdSPJUCBDHR/GK6ZjqVS+azSvvxmcyXPVsTCcibTK9FSxmkyTYikSJEWKpkqRR2VYkYqsMFlQM8NB870Uic4c/Ri/kqF1ghSVpV18rtD9eMH5ZJXDg3ndc8kxJZYgL/niatxzpxOUOthHrGY4m6zNg56zH87tueowHI+YGYXR8kRJZMqw9FJMmL06W44Xqp4u2lBDU1fXUc4lqWIqQJbWSVJMvv5yanmmind4JK+Zcgxg81XJS764N+E5BeyiXzOcFmlgfc6OuJrnqsPzgLCwSoSW6sz5FUSSGEksNsUXIykSNE+Bl+kpI8nQLmy+kBR1GfyHq5UcjJW/5F3ouToM9Jx9gZ6rDg8AaWE1KF2sMecp8AwZnipFRSVIeimWX0HI9JQasRD/fOrqOkpoirrQ5OggIM9j/x3oOScFes6+QM+9IpSV0+NWocFT0N7DIlOaFM2rIIrVZhViIWmWccZHfdBztRboOacFes6+QM/9axiWR81MudFSqCIflWHppViqFEuRoGlStEBYpZZknKB7J/RcrQV6zmmBnrMv0HN2hOMBamZUCF2oIjNlWJIYiS9GUqVIlhx7XEGUGygTyVjq2iyy0HO1Fug5pwV6zr5Az9U0JM2qUbpUR+WUE5kyLFWKJomRZAmSW05ItGY9YbXU7uZO6LlaC/Sc0wI9Z1+g594wPA8sDK/HrWKt+XEFkSnDhJlcMmVYbjleqjMrTbWrkwv0XK0Fes5pgZ6zL9BztQGa4U0ko0ToQhX5qBRLlaLxRaYkMfKoDC1Sm9UojVIM46Cpq6Hnai3Qc04L9Jx9gZ6rnbAcj5gZuYEqUZM55XhGGZZQjDwqwzJlWJGaLNNTRsL6ZhZtgJ6rtTi557Zu3Tpw4MBhw4YNGjTowIEDDONCk69Az9kX6Lm6AsvxJM1pMVqsMWfL8WQxGl9kSpOimTL8iZIoN1A63FoTSyVDz/07EhMTExMTK+ckJycnJSXZ8RBO7rk+ffoMHjTowYMHJ0+ebNCgwc8bN9bgwWoZ0HP2BXquTmOmWS1Gl+mp/AoiS46nStBkCfqoDMtT4MVqUoPSZprj+Neq9tnRc97e3gsXLnz18hRFpaamUlTdaxwjSbJNmzZhYWGVMy9cuNCuXTs7no6Te27gwIErV6wQtjdu3Pjpp58K2xqNxs/Pz9fX98GDB7bCN2/e9PX1PX36NEmSAICIiIiioiKRSOTr63vu3LnKuw0LC/P19fX399dqtUJOdHR0RkZGYmKir6/v+fPnbSUzMzPXr1+/d+9epVIp5JSWlm7ftm3jxo2PHj2qsfMGAHrO3kDPORlWljeSTJmeylPgaaVYigRJlSAZMixThkl1lBKhceqfjeqzo+fCw8Mr30b+FqVK1bBhw6KiIvsc/g1y8eLF9u3bs+xf/rNYlu3Qvv21a9fsdRTn99zqVauE7dGjRw8fPhwAUFxc3Lp164kTJy5ZsqRp06bHjh8HABw7duyLL7746aefhgwZEhkRAQAYPHhwhw4dRo8evWjRog8++MBnzRoAAMMwY8eO7fTVV2vXrnVzc/v888/FYjEAYOrUqS1bthw7dqy3t3fDhg03b94MAEhJSfnss88WLVrk7u6+ZcsWAEBqauqnn346c+bMRYsWffTRR1euXKm5cz8t0hSqyZrbv6uRWAw95+RYWR6lmAqTpVBF5pbjaVL0YZFJJEYelWGFKlKJ0IiZfcmjPjt6rqioqLCwEABQVlb26NEjiqLOnz8fFRVlK8Cx7NWrV0+ePKlSKk0m07Zt2+rXr79+/foLFy7wPI9hWFRU1PHjx+/duyeUZ1n2/v37FoslISHh5MmT5eXltl3RNH3p0qVTp07JZP9bXPP2n38GBQVlZGQ8N7z79+8HBQXl5uYKL1UqVXh4eFBQUGpqKgBAp9NdvXrVan26KJhcJrMZKzk5OSgoqHLtYpK7u5eXV/VDzJkzx8PD4x9fuBfg5J4bM2ZMx44d58yZM3DgwIEDB0okEgDA+PHjp06dKhQ4f/58y5YtAQDu7u4//vijkCnUl4cNG/btt98KdbsrV668/Z//kCQZGRHxzjvv6PV6oWT37t2nTZsGAJgxY0a7du1IggAAHDhwoHnz5gCAw4cPf/bZZ5X32a9fv9WrVws5/v7+X331Vc2d++lE9eUMbW45niXDYHrNlFmG3c7T18RDnb8Fes6B8DzAKFaFCKP68EdlaIoETSvFMsqwEo25TP+X8ewX0zVFL1v+5R8wbuzYUaNGAQBOnjzZunXrUaNGubu7N23adPbs2QAAmqZ//PFHoefB9GnTpFLp2LFj33777aFDh65Zs4YkSXd39759+06bNq1lixaLFy8GAGAY1r59+4EDB44bN27QoEEtWrQQPKpSqbp16zZw4MDx48d37tRJLBbzPO8+aVKXLl1+/PHH5s2bBwQEVIltzZo1Xbt2HTt2bO9evTQajdFo7NWr16hRoyZNmvThhx8eP35co9HUq1fvzp07QnkvL69+/foBAFavXt2+XbvJkye3atVq5cqVAACe57/44os//vij+hU4fuxYuy+/tFePCif33MiRI/v07r179+527dp5TJ4sZH7zzTfdu3efOXOmp6fnsGHD3n33XZqm4+Pjv/jiCzc3t9u3bwvFBgwYsOJZm6dCoXinYcOcnJxVq1b179/ftv9ff/21S5cuAIApU6ZMefbrIyYm5pNPPuF5Xi6Xd+3a9dtvvz19+jQAgKbp5s2b//DDDzNmzJgxY0a/fv0+atKEf71HAi/htEiTVooRFhanYHrdhFEOW4MGeq5WwXK8MIFnqY56XEGkl6IJxUhisSlbjh+IleeoLHY5yuRJkyZOnAgAOHfu3FtvvRUdHQ0AEIlE9erVUyqVpaWl9erVq6ioAACo1WoAgEKhaNSoUX5+PgCAZVmpVCrsJy4urkGDBgiCMAzTpEmTyZMncxwHAOjYseOqVasAAIsWLfr666+Fwunp6Xq9/vChQ1+2bSvk3L9/v3HjxsKBBGiafr9Ro6tXrwIATAhCURRJkrbaob+/f9s2bQAAbm5uc+bMEcp/9tlnV69eTUtL++CDD4xGIwDAaDS+//776enpBEG8//77cbGx1a/A3Xv33n//fbVKZZfr6eSeGzhw4KqVKwEAFRUV9erVu3HjBgDgq6++8pw+/cSJE0FBQcHBwTExMcKvBrVavWnTpg8aNz5w4AAAYMCAAcuXLxf2I5PJGjZoUFRUtHr16gEDBtj2v3nz5u+++w4AMHXq1IkTJgiZt27datasmbBPhmGCgoI+++yzefPmMQzzySefLFmy5MSJE8ePHz979uzDSvV3u3NapHmihO2WdR7oudqPmWaNJBP0sCJPa5/6h8fkye7u7gCAkydPNmvWTMg0Ggwff/xxSkoKTdNDhgzp1KlTcHCw8FZBYWGjRo3S0tJse7hw4cLPP/88ffp0QVQsy37wwQeCnwAAs2bN8vT0BAB07dp165YtlQ89Yfz4Tp06/fLLL+vXr1++fHm9evVSkpNt7/I8v2TJkpYtW+7atQvHcSGTIIjff/99/fr1I0eObNWqFQAgJCTk448/BgAkJCQ0bdqUYZgtW7Z8/PHHwm5//vnnt9566+LFi0ajsfH77ycmJFS/AklJSf/3f/9XuSn1dXByzw0aNGjp4sXC9vTp03v37g0AmDBhgvA3VBmFQiFs/PTTT927dwcADB8+vEuXLiiKAgAOHz783nvvsSwbEhJSv3594fcLwzBffvnlsmXLAAAeHh4Txo8X9nDz5s1mzZqxLGvre3LlypV333nHarX269dvyZIlNXjClYD9UJwD6Lm6Qliq2l7tljbPnTp1qlmzZkIlTKfVfvrpp0IXfJZlDx8+3KFDh8GDB5MkKRaLbZ7DcXzw4MFdu3b19fWdPXv2hx9+qFQqWZb98MMPbd0a58yeLTSBdunSxX/PnsqHHjd27Hfdum3YsMHX13fDhg179+41GAxVwgsPD+/bt2+HDh3kcrlCoejUqdOIESN8fX3Hjh3bpk0bAIDRaGzcuHFKSorPmjVCxXTdunUtW7bctGmTr6+vr6/vrl27FApFRUXF+40axT98WP0KJCYmNmzYsFz+Mj+9Ok7uue+//37us1NITU2tV69eZmamWCxu3br1gAEDFixYILRoAwCmTZs2ZMiQadOmtWrVSuhdOW7cuBYtWowaOdLDw6Nx48aBgYEAAKvVOnHixNatW8+dO7dXr14//PCDTqcDAIwZM2bE8OHCgaKioho0aAAA8Pf37/rtt7NmzWrXrp2Pjw8AICMjQ2gdXbhw4ZAhQ7Zu3Vpz5w495xxAz9UV7NgP5bme02o0zZs3T0pKomlaKIbjeL169TIyMpRKZf369YV2S5FI9NZbbwmVrfj4+IYNG1b33OxZs2bOnAkAGDFixMiRI4VMFEUpilq5YkXfvn2rh4SiKMuylR+YNWnS5OTJk2eCgz9q0kTIOXz4cNOmTYXtadOm/fjjj127dhVa0YKDg21v2cBx/IMPPoiIiKh+uIiIiJYtWuAY9m8uXzWc3HN37txJT0+3vQwLCysoKAAAGI3G06dPBwQEXAgNFWpyKpXq5MmT+/bts9X9f/jhhxUrVqSkpOzbty8lJaXybq9fv75v377Lly/bnq7Fx8fHx8cL2wqFIjIyEgBAUdSlS5f27dt369Yt22dVKlVQUFBAQEBkZKRGo6m5c4eecw6g5+oKdvTcqJEjhc7hgYGB9evXFzynUavr16+fmZmZmJjYu1evDRs2TJky5euvvzbo9VartW3btkOGDNm2bZtUKm3Tps348eN9163r9NVXb731lkKhYFm2Xr16th4f7hMnCt3ukpKS3n333dmzZ/v6+n7//fcFBQVqtbpNmzbDhw/fvn37ksWL582bx/N8aWlpw4YNL1++rNfr+/fvv3r16qVLl7Zo0SI/Pz8/P//9Ro0WLly4YsWK5s2bN2vWTLgrxsbG1qtXr02bNoKVSZLs16/ft99++8svv6xZs2by5MkqlQoA0L179/Xr11e/Ahs3buzZs6d9rqbTe+516Nq166xZsxwdxb8Hes45gJ6rK9jRcxEREeHh4QCA7Ozs/fv3C5lmszkgIEChUJjN5qCgoKVLl/7666+qZz01Hj9+vGLFisOHDwMAxGLxqlWrfHx8EhMSjh07hqIoz/N7/f2fPHkiFL4WFWWrReXl5vr4+CxbtqxyT4Xfduzw9vbeuGGDMDLBYDBs2rRJGEhw+fJl76VLV69ebRtXkJiY6O3tvXXrVlFiYtDx44LnGIbZvn277YkgAIAkyWPHji1dunTlypWRERHCwINff/31udXHfv36bbTftB7Qcy/Ez8/vuR1e6wrQc84B9FxdAc779S8Qi8UfffRRXl5e5cy8vLwmH35YXFxsr6NAzzkt0HPOAfRcXQF67t+xZs2aM2fOVM4JDg729fW14yGg55wW6DnnAHqurgA9V2uBnnNaoOecA+i5ugL0XK0Fes5pgZ5zDqDn6grQc7UW6DmnBXrOOYCeqytAz9VaoOecFug55wB6rq4APVdrcbznDI6ZHdf5OZeizVNAz9V5oOfqCtBztRYHe+7YfcUDLciCyd4pWwcOJJJPlNBzdR7oubpCaIpaijs6CMjzOBDrUM8VqMgb+diVDC1Mdk6Zupu5BtwR64JC7Av0XF3hrEiVYgQKCqbalSposOWa9CVfXI17DgKBvBzoubpCTjl+Ph09naCEqValMyn66zn6l3xx0HOQGgRF0bKyMgSx01om1WBZ9rnL2L7iIsUsy167dk1Yx7I6qampDx8+BADwPM+yz6k3246emZkpLGRfPYyUlBTs72Zkh56DQGoU6DlIjWA0GhcuXPjVV1/17du3ffv2ly5d+hc74XleIpEQxAufQf6///f/evbsKUwXa2Pu3Lk9e/a0WP5+3WeWZTt27Fh5rYnKLFq0aPLkyQCAa9eutW3b9tq1a5XfTUhIaNu27c2bNwEAI0eO3L59e/U9VFRUdOjQITMz8+VhQM9BIDUK9BzE/hAE0atXrwkTJmRkZJhMpvT09MePH/+L/Vit1m+++ca2mG11+vTp06BBg4sXL9pyiouL//Of/7Rs2ZKiXmk4S/fu3WNiYp771sqVK4WVKs+dO/f222+PGTOm8ruenp5vvfVWaGioEOdzq5U8z7/orcpAz0EgNQr0HMT+7N69u2PHjlUySZI8fvz4n3/+6eXllZOTAwDw8/ObOXPmnj17zGYzAECtVv/yyy8zZ85ct24dgiA8z69du7Zhw4YeHh7CCiaFhYXLly+fPn36nTt3hH0OHz588ODBbm5utqP4+Pj07du3Z8+eJEkKB92yZcvMmTO9vb3FYrFQBsfxrVu3zpgx48SJE717946NjRXyDx48OGPGjB07dggtjTbPnTx5skuXLp07d37w4IFQMicnp3fv3t26dRNmpw0LC8vKyiorK9uyZYvQwnnz5s2zZ88yDHP06FEMwzAMCwwMvH379rJlyxYtWiSsVm8Deg4CqVGg5yD2p3///n5+flUyTSZT8+bNBwwYsHXrVrlcvnr16rFjx16/fn3cuHFeXl4AgOjo6A0bNsTGxo4fP15Yann37t2NGzdesmTJrVu3xGJx586djx49+scff7Rp00Z4ctanT5/g4ODvvvsuISEBAKDX63v37h0REdGlSxeLxWK1WseMGePu7h4REbF8+fIvvvhCEIybm9vo0aMvXbrk7e397rvvikQiAMD69euHDh0aFRXl6enp4eEBAFi9erXgucDAwMmTJ+/cuXPKlCnCucyZM2fLli3u7u4nT54EAPTr12/Pnj0kSbZp0+b06dM0Tbdq1erWrVsEQTRp0kQqlRoMhvr1648ZMyY0NNTNza1fv36VK3nQcxBIjQI9B7E/33zzTXBwcJVMDMOaN28eHR0NAMjJyfnkk09ycnLUavXt27ebNm1qMpkAACzLPnnyxM/P7/PPP2dZluO4du3aCWuyL1iwYNy4cTqdzmAw/PjjjzNnzgQA9OjRIy4ubteuXcLSyVu2bPHy8iopKWnfvj0A4MqVK61atbIF0L9//71792ZlZbVs2dL2SK9Dhw4ikUilUn3yyScikUij0SQlJX388ccWi2X9+vU2z40aNUqr1bZu3VqlUhkMho4dO2o0mhEjRgieGzFixN69ewEAycnJgwcPXrBgwYYNGwAAWq22TZs2ZWVlBoOhadOmWVlZAICSkpJPPvmkcucX6DkIpEaBnoPYnwEDBmzbtq1KptFo7NKli7DecXR09Icffjhu3LiRI0eOGjVq7NixFEVFRkYOGjTI29vby8vryy+/tFqtJpOpTZs2wmKMEydO7Ny58+jRo0ePHj1kyJBdu3YBAHr06BEVFWU0Gjt06JCbm9utW7esrKzCwsJ27doBAPbs2TNu3DhbAMuWLVu+fPmlS5cqt3P27ds3KSkpOzu7cePGY8eOFeJxc3MjSdLX19fmucGDBwMAJk+evHv37sDAwKlTpwIAfvjhB5vnAgIChB26u7v/97//FVpNbZ7TarVff/21QqEAACgUitatW8tkMlsM0HMQSI0CPQexP0eOHGnUqFFpaWnlTIPB8PXXXwtP5h4+fNiiRQvhsZwATdOffvrp/fv3AQAPHjwQqlwIgrRu3VrQw5w5c+bNm1flQD169BAe3S1cuPCbb76ZOHEiACA9PV3w3I0bNzp27GhrIRwxYkRgYGB8fHyrVq2ETIqiWrVqlZKSUlJS0qxZM6HiaMP2fC4wMHDQoEEAgNTU1I4dO3bq1CktLTUbWn8AAAbTSURBVA381XNCfS4lJcXNzW3kyJFbtmwBf/Vcp06dysrKAAAymax169Zy+f+mb4Ceg7wxeJ63/Uf8bQ8px8LzPAD2iRB6DmJ/GIaZNm1as2bNNmzYEBgY6OXldf36dYvF8umnn2ZkZAgFhg8f7ubmFhISEhAQEBgYyDBMt27dZsyYERISMmrUqEaNGlEUxXFc586dFy9enJycnJmZ2bJlyx07doSEhKxYsUJoA/zyyy/Pnj0LAMjOzn777beFjpeJiYlNmjSxWCw0Tffq1Wv06NHnzp1btWpVjx49jEaj1Wrt0KHDuHHj/vjjj8WLF//nP/8R5Oru7t63b9+QkJCDBw8K0lqwYIEgzoCAgK5duwqn1qtXr2+//VbY7tKly5EjRwAAvXv33rNnj8Fg+Oyzz65fv240Gt977724uDiCIBo3biyRSNRqdbNmzYQxdqWlpY0aNRKcJwA9B3lFzBRFUea/L/cCOJ7Hno3SYRiWIEmCNLMs9yzHajIZOO515yPmec6EkQz7uorCCILnObOZxHH05SXNZoLjXjYzFPQcpKYICQlZvHixl5fX2rVrpVIpx3EnT5601ZmETo/z5s3z8fERKnnFxcVC0+K9e/fOnj1L0zQAIDU1denSpYLAMjIyvL2958+fv3//fhzHAQBnzpyxjViIjIxEURQAUFFRcezYMeEJnMlk2rFjx/z58zdv3qxSqYSSUql0+fLlS5YsiY2NDQ8Pl0qlAACLxeLn5zdv3rxVq1YJ1bXY2NgbN24Ixw0JCRE+m5SUlJ6eLmyfP38+OzsbABAeHp6Tk1NcXBwYGGgL5sqVKyzL/v777wiCkCR54sQJYbw8iqK///67EOrTCwU9B3k1jChuMBmEehgPAGmmrAwDAOB5niBJnucEt7yoomaxULZxpRRlZllOpdGazaSQw3GcRqO0zbHwj2p7lcvyPFeh1tAMB16pOsbbjk6Q/1M4w1iF9h6SxPV6zfM/+gwTgtieuD/3iNBzEIiDgZ6DvCK42VKh1phMBgtFWRlWUV6GYQjPA7PFolCUUZSZYTmlRoPhmBFBOY5nWdZofDohFs/zJEkI9uI4VqgXavU6g9FgMhmsVgYAYDTqBc8RJIHhmIUysxyHEQSGIlq9nqtkM6vVimKozmhiWdZK02aS0Bv0LMebzWYUwxRqDUpaVFoNhqE4SVY+Bb0J0RsMKIYyLGdlGBzHTSjGcSxGEApFmcXydNgrRZmFITpWK20yGapcBwxDCILESTNtoViW0Wi1LMsK547jmAlFub9KGnoOAnEw0HOQVwQlzCYUoWmL1ogAANQqhVCPYVlWra4QylRotAAAjcEgVNRsU9ZZLBYLTQvbJEkKFUGtTmelLRiOmUxGAIDBoGNZxmql1To9AEBrMOAEaTSZCDNtQP7SeKjRKCmKomgrz3NmM2EwaBGcpCxWtUoBANDo9ZjZqtZqAc+qdLrKH9SZMJzASTNpxAidXksQhE6vIQmMYWiN5umMEFaGIZ7ZkaYtNlXbMFMWncGIk2ahldVg0DEMzfNApdUCwKu1Opr+y3RI9eZXe7YPgUDeJBGXLoWHhTk6CkgdAMFJE4pYLJRKbwQAqDRqs8ViZXmO45RqpZXlrCyv0up5Hmh0ejNl5nmeYawAAJ7jUBznOB4AwLIsgj1dXkit1VIWCsVQBDXxPK/TaRjGarVadXoDAEBn0Ftoi0Kl1Op0LMuxLEs9a/bU6tQkSQKep61W0sKYzWaNVkuazTqdhuM4lUaDELRaqwU8p9TqrMz/Pqg3YQRJECShR3C9XoPjKEVRVoalaatao7KyPMvxOEHQ1qfNpxYLpddrqzWi8uVKJUaQAABb2DwPVFo9z/Mqjbaq54YPHXrl8mWYYILJUclnzRroOcirgOIEiiEWC6UzGAEABEmaEJPwJAzDMRTDrCyvUGtR1IRgGMfzHMcaDFoAAGWhCPPTJkGCJCna+myHJIKiGI6zLMcwVr1eQ5KEUIYgcCttMVssGp3OYDRodVqzmbBVrViWxXAMJwgrwxoQFMMQgiQ4nsdJM4Iier0OISiDQc+yjM5gIEjSYHhaqzMiKEkSJEkYEZRlGQxDCdLMcjzPAwQ1YQRhsVoFgQngOKbXa6rPzI4TBG21AgBsYfMAlKs0GIagGF5Fi/UuhoefCQ6GCSaYHJXCLlyoPMwAAvnXsByn0mg4tqoVWJbjnt36GZZ79S4mDGPFMJSiyL9ddsNecBzPcs+Jj6IogsBJkjCbyef2kaEZVq1R89xz+ovWs3+YEAgEAnEcdh8Y9/qDDV4f/hn/IhjoOQgEAoE4M9BzEAgEAnFmoOcgEAgE4sz8f6eTXoHoJ2lzAAAAAElFTkSuQmCC" alt="" />

讲了那么多,我们到底需要干什么!重载这两个方法!! 
如果你的viewset含有post,那么你需要重载create方法,如果含有patch,那么就需要重载update方法。

# 假设现在是个博客,有一个创建文章,与修改文章的功能, model为Article。
class ArticleSerializer(serializers.Serializer):
user = serializers.HiddenField(
default=serializers.CurrentUserDefault())
name = serializers.CharField(max_length=20)
content = serializers.CharField() def create(self, validated_data):
# 除了用户,其他数据可以从validated_data这个字典中获取
# 注意,users在这里是放在上下文中的request,而不是直接的request
user = self.context['request'].user
name = validated_data['name ']
content = validated_data['content ']
return Article.objects.create(**validated_data) def update(self, instance, validated_data):
# 更新的特别之处在于你已经获取到了这个对象instance
instance.name = validated_data.get('name')
instance.content = validated_data.get('content')
instance.save()
return instance

可能会有人好奇,系统是怎么知道,我们需要调用serializer的create方法,还是update方法,我们从save( )方法可以看出,判断的依据是:

if self.instance is not None:pass

那么我们的mixins的create与update也已经在为开发者设置好了

# CreateModelMixin
serializer = self.get_serializer(data=request.data)
# UpdateModelMixin
serializer = self.get_serializer(instance, data=request.data, partial=partial)

也就是说,在update通过get_object( )的方法获取到了instance,然后传递给serializer,serializer再根据是否有传递instance来判断来调用哪个方法!

三、Validation自定义验证逻辑

1、单独的validate

在上面提到field,它能起到一定的验证作用,但很明显,它存在很大的局限性,举个简单的例子,我们要判断我们手机号码,如果使用CharField(max_length=11, min_length=11),它只能确保我们输入的是11个字符,那么我们需要自定义!

mobile_phone = serializers.CharField(max_length=11, min_length=11)

def validate_mobile_phone(self, mobile_phone):
# 注意参数,self以及字段名
# 注意函数名写法,validate_ + 字段名字
if not re.match(REGEX_MOBILE, mobile):
# REGEX_MOBILE表示手机的正则表达式
raise serializers.ValidationError("手机号码非法")
return mobile_phone

当然,这里面还可以加入很多逻辑,例如,还可以判断手机是否原本就存在数据库等等。

2、联合validate

上面验证方式,只能验证一个字段,如果是两个字段联合在一起进行验证,那么我们就可以重载validate( )方法。

start = serializers.DateTimeField()
finish = serializers.DateTimeField() def validate(self, attrs):
# 传进来什么参数,就返回什么参数,一般情况下用attrs
if data['start'] > data['finish']:
raise serializers.ValidationError("finish must occur after start")
return attrs

这个方法非常的有用,我们还可以再这里对一些read_only的字段进行操作,我们在read_only提及到一个例子,订单号的生成,我们可以在这步生成一个订单号,然后添加到attrs这个字典中。

order_sn = serializers.CharField(readonly=True)
def validate(self, attrs):
# 调用一个方法生成order_sn
attrs['order_sn'] = generate_order_sn()
return attrs

这个方法运用在modelserializer中,可以剔除掉write_only的字段,这个字段只验证,但不存在与指定的model当中,即不能save( ),可以在这delete掉!

3、Validators

validators可以直接作用于某个字段,这个时候,它与单独的validate作用差不多

def multiple_of_ten(value):
if value % 10 != 0:
raise serializers.ValidationError('Not a multiple of ten') class GameRecord(serializers.Serializer):
score = IntegerField(validators=[multiple_of_ten])

当然,drf提供的validators还有很好的功能:UniqueValidator,UniqueTogetherValidator等 
UniqueValidator: 指定某一个对象是唯一的,如,用户名只能存在唯一:

username = serializers.CharField(
max_length=11,
min_length=11,
validators=[UniqueValidator(queryset=UserProfile.objects.all())
)

UniqueTogetherValidator: 联合唯一,如用户收藏某个课程,这个时候就不能单独作用于某个字段,我们在Meta中设置。

class Meta:
validators = [
UniqueTogetherValidator(
queryset=UserFav.objects.all(),
fields=('user', 'course'),
message='已经收藏'
)]

四、ModelSerializer

讲了很多Serializer的,在这个时候,我还是强烈建议使用ModelSerializer,因为在大多数情况下,我们都是基于model字段去开发。

好处:

ModelSerializer已经重载了create与update方法,它能够满足将post或patch上来的数据进行进行直接地创建与更新,除非有额外需求,那么就可以重载create与update方法。 
ModelSerializer在Meta中设置fields字段,系统会自动进行映射,省去每个字段再写一个field。

class UserDetailSerializer(serializers.ModelSerializer):
"""
用户详情序列化
""" class Meta:
model = User
fields = ("name", "gender", "birthday", "email", "mobile")
# fields = '__all__': 表示所有字段
# exclude = ('add_time',): 除去指定的某些字段
# 这三种方式,存在一个即可

ModelSerializer需要解决的2个问题:

1,某个字段不属于指定model,它是write_only,需要用户传进来,但我们不能对它进行save( ),因为ModelSerializer是基于Model,这个字段在Model中没有对应,这个时候,我们需要重载validate! 
如在用户注册时,我们需要填写验证码,这个验证码只需要验证,不需要保存到用户这个Model中:

def validate(self, attrs):
del attrs["code"]
return attrs

2,某个字段不属于指定model,它是read_only,只需要将它序列化传递给用户,但是在这个model中,没有这个字段!我们需要用到SerializerMethodField。 
假设需要返回用户加入这个网站多久了,不可能维持这样加入的天数这样一个数据,一般会记录用户加入的时间点,然后当用户获取这个数据,我们再计算返回给它。

class UserSerializer(serializers.ModelSerializer):
days_since_joined = serializers.SerializerMethodField()
# 方法写法:get_ + 字段
def get_days_since_joined(self, obj):
# obj指这个model的对象
return (now() - obj.date_joined).days class Meta:
model = User

这个的SerializerMethodField用法还相对简单一点,后面还会有比较复杂的情况。

关于外键的serializers

讲了那么多,终于要研究一下外键啦~ 
其实,外键的field也比较简单,如果我们直接使用serializers.Serializer,那么直接用PrimaryKeyRelatedField就解决了。 
假设现在有一门课python入门教学(course),它的类别是python(catogory)。

# 指定queryset
category = serializers.PrimaryKeyRelatedField(queryset=CourseCategory.objects.all(), required=True)

ModelSerializer就更简单了,直接通过映射就好了 
不过这样只是用户获得的只是一个外键类别的id,并不能获取到详细的信息,如果想要获取到具体信息,那需要嵌套serializer

category = CourseCategorySerializer()

注意:上面两种方式,外键都是正向取得,下面介绍怎么反向去取,如,我们需要获取python这个类别下,有什么课程。 
首先,在课程course的model中,需要在外键中设置related_name

class Course(model.Model):
category = models.ForeignKey(CourseCategory, related_name='courses')
# 反向取课程,通过related_name
# 一对多,一个类别下有多个课程,一定要设定many=True
courses = CourseSerializer(many=True)

有一个小问题:我们在上面提到ModelSerializer需要解决的第二个问题中,其实还有一种情况,就是某个字段属于指定model,但不能获取到相关数据。

假设现在是一个多级分类的课程,例如,编程语言–>python–>python入门学习课程,编程语言与python属于类别,另外一个属于课程,编程语言类别是python类别的一个外键,而且属于同一个model,实现方法:

parent_category = models.ForeignKey('self', null=True, blank=True,
verbose_name='父类目别',
related_name='sub_cat')

现在获取编程语言下的课程,显然无法直接获取到python入门学习这个课程,因为它们两没有外键关系。SerializerMethodField( )也可以解决这个问题,只要在自定义的方法中实现相关的逻辑即可!

courses = SerializerMethodField()
def get_courses(self, obj):
all_courses = Course.objects.filter(category__parent_category_id=obj.id)
courses_serializer = CourseSerializer(all_course, many=True,
context={'request': self.context['request']})
return courses_serializer.data

上面的例子看起来有点奇怪,因为我们在SerializerMethodField()嵌套了serializer,就需要自己进行序列化,然后再从data就可以取出json数据。

可以看到传递的参数是分别是:queryset,many=True多个对象,context上下文。这个context十分关键,如果不将request传递给它,在序列化的时候,图片与文件这些Field不会再前面加上域名,也就是说,只会有/media/img…这样的路径!

转载出处: www.careeru.cn/blog/article/?id=85

django rest framework serializers的更多相关文章

  1. Sentry 开发者贡献指南 - Django Rest Framework(Serializers)

    Serializer 用于获取复杂的 python 模型并将它们转换为 json.序列化程序还可用于在验证传入数据后将 json 反序列化回 Python 模型. 在 Sentry,我们有两种不同类型 ...

  2. django rest framework serializers序列化

    serializers是将复杂的数据结构变成json或者xml这个格式的 serializers有以下几个作用: - 将queryset与model实例等进行序列化,转化成json格式,返回给用户(a ...

  3. django rest framework serializers解读

    serializers是什么?官网是这样的"Serializers allow complex data such as querysets and model instances to b ...

  4. django rest framework serializers小结

    注:转载至https://blog.csdn.net/l_vip/article/details/79156113 引言 serializers是什么?官网是这样的”Serializers allow ...

  5. Django rest framework的基本用法

    今天在网上看到几篇比较不错的drf基本功能介绍,本来想自己写一篇,后来发现脱不开原作者的思路,遂卒,直接扔链接小伙伴自己去看吧.... 1.django rest framework apiview. ...

  6. python 全栈开发,Day94(Promise,箭头函数,Django REST framework,生成json数据三种方式,serializers,Postman使用,外部python脚本调用django)

    昨日内容回顾 1. 内容回顾 1. VueX VueX分三部分 1. state 2. mutations 3. actions 存放数据 修改数据的唯一方式 异步操作 修改state中数据的步骤: ...

  7. Django Rest Framework源码剖析(六)-----序列化(serializers)

    一.简介 django rest framework 中的序列化组件,可以说是其核心组件,也是我们平时使用最多的组件,它不仅仅有序列化功能,更提供了数据验证的功能(与django中的form类似). ...

  8. 利用 Django REST framework 编写 RESTful API

    利用 Django REST framework 编写 RESTful API Updateat 2015/12/3: 增加 filter 最近在玩 Django,不得不说 rest_framewor ...

  9. django rest framework 入门

    django rest framework 入门1-序列化 Serialization 分类: Python 2013-01-22 22:24 11528人阅读 评论(0) 收藏 举报 djangop ...

随机推荐

  1. Python编程从入门到实践笔记——if语句

    Python编程从入门到实践笔记——if语句 #coding=utf-8 cars=['bwm','audi','toyota','subaru','maserati'] bicycles = [&q ...

  2. View的绘制流程

    这是年假最后一篇笔记了,本篇文章的内容主要来自<android开发艺术探索>,在文章的最后有这本书的网上版本. 项目源码 目录 MeasureSpec SpecMode分类 UNSPECI ...

  3. Do you have an English name? 你有英文名吗?

    文中提到的所有人名都是虚构的,如有雷同,纯属巧合. 当然,你的洋名儿也可能是德文.法文.意大利文,等々々々. 全球化时代,和老外的交流也多了."高端"的程序员想要进欧美系外企,想要 ...

  4. ASP.NET Core 基于JWT的认证(一)

    ASP.NET Core 基于JWT的认证(一) Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计 ...

  5. Xamarin 开发Android应用简易教程(1)

    最近领导又安排了新的项目需求,只好学习学习如何在.net环境下开发APP(原来没有接触过App开发)! 1.安装VS2017移动应用开发模块. 2.使用VS2017,主要是便利,无需配置环境等一系列麻 ...

  6. Android 最简单的测试UI卡顿

    就两个类: public class BlockDetectByPrinter { private static final String START = ">>>> ...

  7. C,java,Python,这些名字背后的江湖!

    还记得高中的时候,有一次我们计算机老师问我们班要不要去参加市里面的C语言比赛,当时还小的我对编程世界压根就一片空白.那时候我就想啊,为什么是C语言,那么A语言,B语言或者是D语言又是什么呢? 后来就到 ...

  8. 从0开始的Python学习011模块

    简介 你已经学习了如何在你的程序中定义一次函数而重用代码.如果你想要在其他程序中重用很多函数,那么你该如何编写程序呢?你可能已经猜到了,答案是使用模块.模块基本上就是一个包含了所有你定义的函数和变量的 ...

  9. SQL server 2017使用教程

    1.安装: 从https://www.microsoft.com/en-us/sql-server/sql-server-downloads官网下载sql server2017试用版 180天 安装完 ...

  10. CG-CTF simple-machine

    运行一下,输入flag: 用ida打开: input_length和input_byte_804B0C0为重命名的变量:现在一个个看调用的函数. sub_8048526(): 这个函数使用了mmap分 ...