2020-12-14 jwt多方式登錄和表關(guān)系建立和表操作

上節(jié)回顧

1、jwt:重點(diǎn)(跟語言套像,框架無關(guān))

-json web token
-cookie:客戶端瀏覽器上的鍵值對(duì)酿联,數(shù)據(jù)不安全
-session:服務(wù)端的鍵值對(duì)(內(nèi)存,數(shù)據(jù)庫,redis贞让,文件)周崭,安全,對(duì)服務(wù)端壓力大
-token:三段:頭喳张,荷載续镇,簽名
    -header:公司信息,加密方式销部,類型
    -payload:荷載摸航,真正有用的數(shù)據(jù)部分,用戶id舅桩,用戶名字
    -signature:簽名酱虎,把頭和荷載部分通過加密算法加密--》得到一個(gè)簽名

2、drf-jwt模塊

-快速使用:默認(rèn)使用的是auth的user表
    -1擂涛、創(chuàng)建用戶
    -2读串、在路由中配置path('login/',obtain_jwt_token),
    -3、在postman中測(cè)試撒妈,用戶名密碼輸入剛剛創(chuàng)建的用戶就可以生成token
    -4爹土、讓一個(gè)視圖必須登錄以后才能訪問
        -authentication_classes=[JSONWebTokenAuthentication,]
        -permission_classes=[IsAuthenticated,]
    -5、讓一個(gè)視圖可以登錄后訪問踩身,也可以不登陸訪問就只加上token的認(rèn)證
        -authentication_classes=[JSONWebTokenAuthentication,]
    -6、用postman測(cè)試社露,在請(qǐng)求頭中加入
        -Authorization   jwt adasffa
-自己寫基于jwt的認(rèn)證類(登錄了能訪問挟阻,不登錄就不能訪問)
    class JwtAuthentication(BaseJSONWebTokenAuthentication):
        def authenticate(self, request):
            #token=request.GET.get('token')
            token=request.META.get('HTTP_Authorization'.upper())
            try:
                # 驗(yàn)證token是否正確
                payload = jwt_decode_handler(token)
            except jwt.ExpiredSignature:
                raise AuthenticationFailed('過期了')
            except jwt.DecodeError:
                raise AuthenticationFailed('解碼錯(cuò)誤')
            except jwt.InvalidTokenError:
                raise AuthenticationFailed('不合法的token')
            user=self.authenticate_credentials(payload)  # 這是用的自帶的user表的字段取出的user,不適用于自己寫的user表峭弟,自己創(chuàng)建的用戶表需要自己手動(dòng)取
            return (user, token)
-自定制認(rèn)證類的使用方式:
    -全局使用
    -局部使用

3附鸽、base64編碼(跟語言無關(guān),跟框架無關(guān))

-不同語言的base64可以互相編碼解碼
-base64內(nèi)置模塊
-圖片的二進(jìn)制瞒瘸,有時(shí)候也會(huì)以base64的形式編碼

4坷备、drf的視圖(兩個(gè)視圖基類,5個(gè)視圖擴(kuò)展類情臭,9個(gè)視圖子類省撑,視圖集)+序列化器+自動(dòng)生成路由

今日內(nèi)容

1、基于jwt的多方式登錄

-1俯在、手機(jī)號(hào)+密碼竟秫,用戶名+密碼,郵箱+密碼
-2跷乐、流程分析(post請(qǐng)求):
    -路由:自動(dòng)生成
    -視圖類:ViewSet(ViewSetMixin肥败,Views.APIView) 所有東西自己寫,路由可以自己生成
    -序列化類:重寫validate方法,在這里面對(duì)用戶名和密碼進(jìn)行校驗(yàn)馒稍,就是全局鉤子
-3皿哨、代碼實(shí)現(xiàn)

路由

也可以選擇自動(dòng)生成
path('login/', views.LoginViewSet.as_view({'post':'create'})),

視圖

class LoginViewSet(ViewSet):
    def create(self, request, *args, **kwargs):
        # 實(shí)例化得到一個(gè)序列化類的對(duì)象
        # ser=LoginSerializer(data=request.data,context={'request':request}) #context數(shù)據(jù)交流的橋梁
        ser = LoginSerializer(data=request.data)
        # 序列化類的對(duì)象的校驗(yàn)方法
        ser.is_valid(raise_exception=True)  # 字段自己的校驗(yàn),局部鉤子校驗(yàn)纽谒,全局鉤子校驗(yàn)证膨,只要走了這個(gè),并且沒有拋異常佛舱,
        #就會(huì)走到序列化器的全局鉤子去校驗(yàn)椎例,那么全局鉤子里往序列化器里添加屬性,那么我在這數(shù)據(jù)校驗(yàn)之后就能從序列化對(duì)象里取到添加的屬性
        # 如果通過请祖,表示登錄成功订歪,返回手動(dòng)簽發(fā)的token
        token = ser.context.get('token')
        username = ser.context.get('username')
        return APIResponse(token=token, username=username)
        # 如果失敗,不用管了

序列化器類

from rest_framework import serializers
from app01.models import UserInfo
import re
from rest_framework.exceptions import ValidationError
from rest_framework_jwt.utils import jwt_encode_handler, jwt_payload_handler
from rest_framework_jwt.views import obtain_jwt_token

class LoginSerializer(serializers.ModelSerializer):
    username = serializers.CharField()

    class Meta:
        model = UserInfo
        fields = ['username', 'password']

    def validate(self, attrs):
        # username可能是郵箱肆捕,手機(jī)號(hào)刷晋,用戶名
        username = attrs.get('username')
        password = attrs.get('password')
        # 如果是手機(jī)號(hào)
        if re.match('^1[3-9]\d{9}$', username):
            # 以手機(jī)號(hào)登錄
            user = UserInfo.objects.filter(phone=username).first()
        elif re.match('^.+@.+$', username):
            # 以郵箱登錄
            user = UserInfo.objects.filter(email=username).first()
        else:
            # 以用戶名登錄
            user = UserInfo.objects.filter(username=username).first()
        # 如果user有值并且密碼正確
        if user and user.check_password(password):
            # 登錄成功,生成token
            # drf-jwt中有通過user對(duì)象生成token的方法
            payload = jwt_payload_handler(user)
            token = jwt_encode_handler(payload)
            # token是要在視圖類中使用慎陵,現(xiàn)在我們?cè)谛蛄谢愔?            # self.context.get('request')
            # 視圖類和序列化類之間通過context這個(gè)字典來傳遞數(shù)據(jù)
            self.context['token'] = token
            self.context['username'] = user.username
            return attrs

        else:
            raise ValidationError('用戶名或密碼錯(cuò)誤')

2眼虱、 自定義user表拳喻,簽發(fā)token振愿,認(rèn)證類

表模型

class MyUser(models.Model):
    # 這里字段必須用username豁遭,應(yīng)為是生成token的源碼里用的就是這個(gè)字段名
    username = models.CharField(max_length=32)
    password = models.CharField(max_length=32)
    phone = models.CharField(max_length=32)
    email = models.EmailField()

路由

path('login2/', views.MyLoginView.as_view()),

視圖

# 這是從jwt的配置文件中導(dǎo)出的功能
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
from rest_framework_jwt.views import obtain_jwt_token


class MyLoginView(APIView):
    def post(self, request, *args, **kwargs):
        username = request.data.get('username')
        password = request.data.get('password')
        # 如果是手機(jī)號(hào)
        if re.match('^1[3-9]\d{9}$', username):
            # 以手機(jī)號(hào)登錄
            user = MyUser.objects.filter(phone=username).first()
        elif re.match('^.+@.+$', username):
            # 以郵箱登錄
            user = MyUser.objects.filter(email=username).first()
        else:
            # 以用戶名登錄
            user = MyUser.objects.filter(username=username).first()
        # 如果user有值并且密碼正確
        if user and user.password == password:
            # 登錄成功憾赁,生成token
            # drf-jwt中有通過user對(duì)象生成token的方法
            payload = jwt_payload_handler(user)
            token = jwt_encode_handler(payload)
            return APIResponse(token=token, username=user.username)
        else:
            return APIResponse(code=101, msg='用戶名或密碼錯(cuò)誤')

from app01.auth import JWTAuthentication

class OrderAPIView(APIView):
    authentication_classes = [JWTAuthentication,]
    def get(self,request):
        # print(request.user)  # 自己的user對(duì)象 {'user_id': 1, 'username': 'lqz', 'exp': 1605545489, 'email': '33@qq.com'}
        print(request.user)  # user是個(gè)字典肛响,就是認(rèn)證后返回的user质况,就是payload字典威彰。內(nèi)部有user_id,
        #后續(xù)要查詢?cè)撚脩舻乃杏唵畏嘌Γ苯痈鶕?jù)user_id查詢即可
        return APIResponse(msg='全部訂單')

自定義認(rèn)證類

from rest_framework_jwt.utils import jwt_decode_handler

import jwt
from rest_framework.exceptions import AuthenticationFailed
from rest_framework_jwt.authentication import BaseJSONWebTokenAuthentication

from app01.models import MyUser


class JWTAuthentication(BaseJSONWebTokenAuthentication):
    def authenticate(self, request):
        token = request.META.get('http_authorization'.upper())
        try:
            payload = jwt_decode_handler(token)
        except jwt.ExpiredSignature:
            raise AuthenticationFailed('過期了')
        except jwt.DecodeError:
            raise AuthenticationFailed('解碼錯(cuò)誤')
        except jwt.InvalidTokenError:
            raise AuthenticationFailed('不合法的token')
        # 得到user對(duì)象纺铭,應(yīng)該是自己user表中的user對(duì)象
        print(payload)  # {'user_id': 1, 'username': 'lqz', 'exp': 1605545489, 'email': '33@qq.com'}
        # user=MyUser.objects.get(id=payload['user_id'])  # 可以這樣取,是訪問數(shù)據(jù)庫寇钉,效率有問題,也可以直接從那個(gè)payload里取舶赔,就是字典里取值扫倡,很快
        user = payload  # 直接讓uesr就是payload
        return (user, token)

3、book竟纳,publish撵溃,author表關(guān)系及抽象表建立

# 注意:以后所有的數(shù)據(jù)刪除,盡量用軟刪除蚁袭,使用一個(gè)字段標(biāo)志是否刪除征懈,而不是真正的從數(shù)據(jù)庫中刪除
    -好處:1 這樣刪除數(shù)據(jù)不會(huì)影響索引,不會(huì)導(dǎo)致索引失效
          2 之前存的用戶數(shù)據(jù)還在揩悄,以備以后使用
# 表模型如下
# 抽象出一個(gè)基表(不再數(shù)據(jù)庫生成,abstract=True),只用來繼承

class BaseModel(models.Model):
    is_delete = models.BooleanField(default=False)
    create_time = models.DateTimeField(auto_now_add=True)

    class Meta:
        # 基表必須設(shè)置abstract卖哎,基表就是給普通Model類繼承使用的,設(shè)置了abstract就不會(huì)完成數(shù)據(jù)庫遷移完成建表
        abstract = True
class Book(BaseModel):
    name = models.CharField(max_length=16)
    price = models.DecimalField(max_digits=5, decimal_places=2)
    publish = models.ForeignKey(to='Publish', db_constraint=False, on_delete=models.DO_NOTHING)
    # 重點(diǎn):多對(duì)多外鍵實(shí)際在關(guān)系表中,ORM默認(rèn)關(guān)系表中兩個(gè)外鍵都是級(jí)聯(lián)
    # ManyToManyField字段不提供設(shè)置on_delete亏娜,如果想設(shè)置關(guān)系表級(jí)聯(lián)焕窝,只能手動(dòng)定義關(guān)系表
    authors = models.ManyToManyField(to='Author', related_name='books', db_constraint=False)

    # 自定義連表深度,不需要反序列化维贺,因?yàn)樽远x插拔屬性不參與反序列化
    # 把他包裝成數(shù)據(jù)屬性它掂,這樣在序列化類中可以顯示序列化后的字段里有這個(gè)屬性,不用重寫字段
    @property
    def publish_name(self):
        return self.publish.name

    # 這個(gè)寫到序列化器里后和source一樣溯泣,如果是個(gè)可執(zhí)行的就會(huì)執(zhí)行虐秋,如果是對(duì)象就會(huì)拿過去,包不包裝成數(shù)據(jù)屬性都一樣
    @property
    def author_list(self):
        # ll=[]
        # for author in self.authors.all():
        #     ll.append({'name':author.name,'sex':author.get_sex_display()})
        return [{'name': author.name, 'sex': author.get_sex_display()} for author in self.authors.all()]


class Publish(BaseModel):
    name = models.CharField(max_length=16)
    address = models.CharField(max_length=64)


class Author(BaseModel):
    name = models.CharField(max_length=16)
    sex = models.IntegerField(choices=[(0, '男'), (1, '女')], default=0)


class AuthorDetail(BaseModel):
    mobile = models.CharField(max_length=11)
    # 有作者可以沒有詳情垃沦,刪除作者客给,詳情一定會(huì)被級(jí)聯(lián)刪除
    # 外鍵字段為正向查詢字段,related_name是反向查詢字段
    author = models.OneToOneField(to='Author', related_name='detail', db_constraint=False, on_delete=models.CASCADE)

4肢簿、book表單增群增

class BookView(APIView):
    def post(self, request, *args, **kwargs):
        if isinstance(request.data, dict):
            # 增一條
            ser = serializer.BookSerializer(data=request.data)
            ser.is_valid(raise_exception=True)
            ser.save()
            return APIResponse(data=ser.data)
        elif isinstance(request.data, list):
            # 增多條
            ser = serializer.BookSerializer(data=request.data, many=True)
            # 內(nèi)部如何實(shí)現(xiàn)的靶剑?
            # many=True,ser不是BookSerializer對(duì)象,而是ListSerializer對(duì)象池充,套了一個(gè)個(gè)的BookSerializer
            print(type(ser))
            ser.is_valid(raise_exception=True)
            #
            from rest_framework.serializers import ListSerializer
            ser.save()  # ListSerializer的save
            return APIResponse(msg='增加%s條成功' % len(request.data))

5桩引、book表單查群查

class BookView(APIView):
    def get(self, request, *args, **kwargs):
        pk = kwargs.get('pk', None)# 這里要設(shè)置個(gè)默認(rèn)值,因?yàn)橛锌赡躪wargs是個(gè)空收夸,空去get就會(huì)報(bào)錯(cuò)
        if pk:
            # 單查
            # 方式一
            # book=models.Book.objects.filter(id=pk).filter(is_delete=False).first()
            # if not book:
            #     raise Exception('要查詢的不存在')

            # 方式二
            book = models.Book.objects.get(id=pk, is_delete=False)
            ser = serializer.BookSerializer(instance=book)

        else:
            # 查所有
            book_list = models.Book.objects.all().filter(is_delete=False)
            ser = serializer.BookSerializer(instance=book_list, many=True)
        return APIResponse(data=ser.data)

6 book表單改群改

class BookView(APIView):
    def put(self, request, *args, **kwargs):
        pk = kwargs.get('pk', None)
        if pk:
            # 單條修改
            book = models.Book.objects.get(id=pk, is_delete=False)
            ser = serializer.BookSerializer(instance=book, data=request.data)
            ser.is_valid(raise_exception=True)
            ser.save()
            return APIResponse(msg='修改成功')
        else:
            # 分析:ListSerializer的update方法沒有寫坑匠,需要我們自己寫
            from rest_framework.serializers import ListSerializer
            # pks=[item['id'] for item in request.data] # 需要把id剔除

            # 如果不重寫ListSerializer的update方法,這是存不進(jìn)去的
            pks = []
            for item in request.data:
                pks.append(item['id'])
                item.pop('id')

            print(request.data)
            book_list = models.Book.objects.filter(id__in=pks, is_delete=False)
            ser = serializer.BookSerializer(instance=book_list, data=request.data, many=True)
            print(type(ser))
            ser.is_valid(raise_exception=True)
            ser.save()
            return APIResponse(msg='修改%s條成功')

            # 你們能想到的方法
            # pks = []
            # for item in request.data:
            #     pks.append(item['id'])
            #     item.pop('id')
            # book_list = models.Book.objects.filter(id__in=pks, is_delete=False)
            #
            # for i,book in enumerate(book_list):
            #     ser = serializer.BookSerializer(instance=book, data=request.data[i])
            #     ser.is_valid(raise_exception=True)
            #     ser.save()
            # return APIResponse(msg='修改%s條成功'%len(book_list))

7 book表的單刪群刪

class BookView(APIView):

    def delete(self, request, *args, **kwargs):
        pk = kwargs.get('pk', None)
        pks = []
        if pk:
            # 單條刪除
            # res=models.Book.objects.filter(id=pk).update(is_delete=True)
            # print(res)
            # return APIResponse(msg='刪除成功')
            pks.append(pk)
        else:
            pks = request.data  # 傳過來的就是列表

        res = models.Book.objects.filter(id__in=pks).update(is_delete=True)
        if res >= 1:
            return APIResponse(msg='刪除%s條成功' % res)
        else:
            # raise Exception('沒有要?jiǎng)h除的數(shù)據(jù)')
            return APIResponse(code=999, msg='沒有要?jiǎng)h除的數(shù)據(jù)')

8 序列化類

from app01 import models

# 重寫群改的序列化類,因?yàn)長istSerializer里沒有重寫update方法
class ListBookSerializer(serializers.ListSerializer):
    # def create(self, validated_data):
    #     print('=======',validated_data)
    #     return '1'
    def update(self, instance, validated_data):
        print(instance) # book_list:是一堆圖書對(duì)象
        print(validated_data) # 列表套字典卧惜,是要修改的數(shù)據(jù)

        #  self.child就是BookSerializer
        return [self.child.update(book, validated_data[i]) for i, book in enumerate(instance)]


class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Book
        list_serializer_class=ListBookSerializer # 指定many=True的時(shí)候笛辟,生成的ListBookSerializer的對(duì)象了
        fields = ['name', 'price', 'publish', 'authors', 'publish_name', 'author_list']
        extra_kwargs = {
            'publish': {'write_only': True},
            'authors': {'write_only': True},
            'publish_name': {'read_only': True},# 后面兩個(gè)字段是模型類的數(shù)據(jù)屬性,起始也可以重寫兩個(gè)字段也能達(dá)到相同的效果序苏,但是這樣寫更巧妙
            'author_list': {'read_only': True},

        }

    # def create(self, validated_data): # 寫了就不走自己的保存了
    #     print(validated_data)

9、路由

path('books/', views.BookView.as_view()),
re_path('books/(?P<pk>\d+)', views.BookView.as_view()),
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末捷凄,一起剝皮案震驚了整個(gè)濱河市忱详,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌跺涤,老刑警劉巖匈睁,帶你破解...
    沈念sama閱讀 221,273評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異桶错,居然都是意外死亡航唆,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,349評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門院刁,熙熙樓的掌柜王于貴愁眉苦臉地迎上來糯钙,“玉大人,你說我怎么就攤上這事∪伟叮” “怎么了再榄?”我有些...
    開封第一講書人閱讀 167,709評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長享潜。 經(jīng)常有香客問我困鸥,道長,這世上最難降的妖魔是什么剑按? 我笑而不...
    開封第一講書人閱讀 59,520評(píng)論 1 296
  • 正文 為了忘掉前任疾就,我火速辦了婚禮,結(jié)果婚禮上艺蝴,老公的妹妹穿的比我還像新娘猬腰。我一直安慰自己,他們只是感情好吴趴,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,515評(píng)論 6 397
  • 文/花漫 我一把揭開白布漆诽。 她就那樣靜靜地躺著,像睡著了一般锣枝。 火紅的嫁衣襯著肌膚如雪厢拭。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,158評(píng)論 1 308
  • 那天撇叁,我揣著相機(jī)與錄音供鸠,去河邊找鬼。 笑死陨闹,一個(gè)胖子當(dāng)著我的面吹牛楞捂,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播趋厉,決...
    沈念sama閱讀 40,755評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼寨闹,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了君账?” 一聲冷哼從身側(cè)響起繁堡,我...
    開封第一講書人閱讀 39,660評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎乡数,沒想到半個(gè)月后椭蹄,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,203評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡净赴,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,287評(píng)論 3 340
  • 正文 我和宋清朗相戀三年绳矩,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片玖翅。...
    茶點(diǎn)故事閱讀 40,427評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡翼馆,死狀恐怖割以,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情写妥,我是刑警寧澤拳球,帶...
    沈念sama閱讀 36,122評(píng)論 5 349
  • 正文 年R本政府宣布,位于F島的核電站珍特,受9級(jí)特大地震影響祝峻,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜扎筒,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,801評(píng)論 3 333
  • 文/蒙蒙 一莱找、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧嗜桌,春花似錦奥溺、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,272評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至层亿,卻和暖如春桦卒,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背匿又。 一陣腳步聲響...
    開封第一講書人閱讀 33,393評(píng)論 1 272
  • 我被黑心中介騙來泰國打工方灾, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人碌更。 一個(gè)月前我還...
    沈念sama閱讀 48,808評(píng)論 3 376
  • 正文 我出身青樓裕偿,卻偏偏與公主長得像,于是被迫代替她去往敵國和親痛单。 傳聞我的和親對(duì)象是個(gè)殘疾皇子嘿棘,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,440評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • 昨日回顧 1 分頁功能 2 全局異常 3 自己寫的Response 4 自動(dòng)生成接口文檔 1、作業(yè)講解之用戶注冊(cè)/...
    故鄉(xiāng)小城閱讀 695評(píng)論 0 0
  • 安裝Nginx:yum install -y nginxsystemctl start nginxsystemct...
    碧潭飄雪ikaros閱讀 698評(píng)論 0 1
  • 《Django Web典型模塊開發(fā)實(shí)戰(zhàn)》 一旭绒、Django組件 1蔫巩、AOP(Aspect Oriented Pro...
    myofee閱讀 325評(píng)論 1 1
  • 久違的晴天,家長會(huì)快压。 家長大會(huì)開好到教室時(shí),離放學(xué)已經(jīng)沒多少時(shí)間了垃瞧。班主任說已經(jīng)安排了三個(gè)家長分享經(jīng)驗(yàn)蔫劣。 放學(xué)鈴聲...
    飄雪兒5閱讀 7,524評(píng)論 16 22
  • 今天感恩節(jié)哎,感謝一直在我身邊的親朋好友个从。感恩相遇脉幢!感恩不離不棄歪沃。 中午開了第一次的黨會(huì),身份的轉(zhuǎn)變要...
    迷月閃星情閱讀 10,567評(píng)論 0 11