邮箱验证 准备工作 1.安装 itsdangerous 模块(它提供加密解密的方法):
1 2 3 4 5 6 7 leazhi@ubuntuhome:~$ workon haoke_small (haoke_small) leazhi@ubuntuhome:~$itsdangerous ==1.1.0 Looking in indexes: https://pypi.tuna.tsinghua.edu.cn/simple Collecting itsdangerous Downloading https://pypi.tuna.tsinghua.edu.cn/packages/68/5f/447e04e828f47465eeab35b5d408b7ebaaaee207f48b7136c5a7267a30ae/itsdangerous-1.1.0-py3-none-any.whl (15 kB) Installing collected packages: itsdangerous Successfully installed itsdangerous-1.1.0
注意 : 这里 itsdangerous 的版本要低于 2.0.0 ,否则在后面使用 itsdangerous 模块会报:
1 2 3 File "/home/leazhi/small/haoke/haoke/apps/users/serializers.py" , line 17, in <module> from celery_tasks.email.tasks import send_verify_email ImportError: cannot import name 'TimedJSONWebSignatureSerializer' from 'itsdangerous' (/home/leazhi/Desktop/python3/Django/Project/small/haoke/haoke/apps/users/models.py)
解决方法 :
请参考:https://blog.csdn.net/weixin_43863487/article/details/123784400
邮件发送 1.编辑子应用 users 目录下的 models.py 文件,在该文件中导入 itsdangerous 模块中的 TimedJSONWebSignatureSerializer ,然后在 Uesr model 类下面添加一个生成邮箱链接的方法,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 ... from django.conf import settingsfrom itsdangerous import TimedJSONWebSignatureSerializer as TJWSerializer... def generate_verify_email_url (self ): ser = TJWSerializer(secret_key=settings.SECRET_KEY, expires_in=3600 ) data = { 'user_id' : self.id , 'email' : self.email, } token = ser.dumps(data).decode() return 'https://www.meiduo.site:8080/success_verify_email.html?token=' + token
2.编辑子应用 users 目录下的 serializers , 先导入异步任务中的 send_varify_email 方法,然后在 EmailSerializer 类的 update 方法中添加邮件地址发送的调用,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 ... from celery_tasks.email.tasks import send_verify_email... class EmailSerializer (serializers.ModelSerializer): """ 邮箱修改序列化器 """ class Meta : model = User fields = ('id' , 'email' ,) extra_kwargs = { 'email' : { 'required' : True , } } def update (self, instance, validated_data ): """ 重写更新方法 """ instance.email = validated_data['email' ] instance.save() verify_url = instance.generate_verify_email_url() send_verify_email(instance.email, verify_url = verify_url) return instance
激活邮箱 解密 token: 1.编辑子应用 users 目录下的 models.py 文件,导入 itsdangerous 的解密方法 BadData, 然后添加如下代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 ... from itsdangerous import TimedJSONWebSignatureSerializer as TJWSerializer, BadData... @staticmethod def check_verify_email_token (token ): ser = TJWSerializer(secret_key=settings.SECRET_KEY, expires_in=3600 ) try : data = ser.loads(token) except BadData: return None else : id = data.get('user_id' ) email = data.gete('email' ) try : user = User.objects.get(id =id , email=email) except User.DoesNotExist: return None else : return user
编写邮件验证视图 1.编辑子应用 users 目录下的 views 文件,添加邮箱验证视图,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 ... from rest_framework import status... class VerifyEmailView (View ): """ 邮箱验证视图 """ def get (self, request ): token = request.query_params.get('token' ) if not token: return Response({'message' : '缺少 token' }, status=status.HTTP_400_BAD_REQUEST) user = User.check_verify_email_token(token) if user is None : return Response({'message' : '链接信息无效' }, status=status.HTTP_400_BAD_REQUEST) else : user.email_active= True user.save() return Response({'message' : 'OK' })
添加邮箱验证的路由 1.编辑子应用 users 目录下的 urls 文件,添加邮箱验证的路由,如下:
1 2 3 4 5 6 7 urlpatterns = [ ... path('emails/verification/' , views.VerifyEmailView.as_view()), ]
收货地址 创建子应用 areas 1.创建子应用 areas,并添加到 settings.py 的 INSTALLED_APPS 中:
1.1.创建子应用 areas:
1 (haoke_small) leazhi@ubuntuhome:~/small/haoke/haoke/apps$ python ../../manage.py startapp areas
1.2.将创建的子应用添加到配置文件 dev.py 中;
1 2 3 4 5 6 7 8 9 10 ... INSTALLED_APPS = [ ... 'areas' , ] ...
创建 areas 的模型类: 1.编辑子应用 areas 目录下的 models.py 文件,创建模型类,如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 from django.db import modelsclass Area (models.Model): name = models.CharField(max_length=20 , verbose_name='名称' ) parent = models.ForeignKey('self' , null=True , blank=True , verbose_name='上级行政区域' , on_delete=models.SET_NULL, related_name='subs' ) class Meta : db_table = 'tb_areas' verbose_name = '行政区域' verbose_name_plural = verbose_name def __str__ (self ): return self.name
2.执行命令进行数据迁移:
1 2 (haoke_small) leazhi@ubuntuhome:~/small/haoke/haoke/apps$ python ../../manage makemigrations (haoke_small) leazhi@ubuntuhome:~/small/haoke/haoke/apps$ python ../../manage migrate
3.执行命令,往数据库中导入数据:
1 mysql -uroot -p small < areas.sql
创建序列化器 1.在子应用 areas 目录下新建 serializers.py 文件,编辑如下内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 from rest_framework import serializersfrom .models import Areaclass AreaModelSerializer (serializers.ModelSerializer): class Meta : model = Area fields = ('id' , 'name' ) class SubAreaModelSerializer (serializers.ModelSerializer): parent = serializers.StringRelatedField() subs = AreaModelSerializer(many=True , read_only=True ) class Meta : model = Area fields = ('id' , 'name' , 'subs' )
创建视图 1.编辑子应用 areas 目录下创建 views.py 文件,并编辑如下内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 from django.shortcuts import renderfrom rest_framework.viewsets import ModelViewSetfrom areas.models import Areafrom areas.serializers import AreaModelSerializer, SubAreaModelSerializerclass AreasViewSet (ModelViewSet ): pagination_class = None def get_queryset (self ): if self.action == 'list' : return Area.objects.filter (parent=None ) else : return Area.objects.all def get_serializer_class (self ): if self.action == 'list' : return AreaModelSerializer else : return SubAreaModelSerializer def list (self, request, *args, **kwargs ): queryset = self.get_queryset() serializer = self.get_serializer_class()(queryset, many=True ) return render(request, serializer.data, status=200 )
创建子应用的访问路由 1.子应用 areas 目录下的新建 urls.py 文件,添加如下内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 from django.urls import path, re_pathfrom . import viewsfrom rest_framework.routers import DefaultRouterurlpatterns = [ ] route = DefaultRouter() route.register(r'areas' , views.AreasViewSet, basename='areas' ) urlpatterns += route.urls
总路由添加子应用的路由 1.修改项目总路由,添加子应用的路由
1 2 3 4 5 6 7 8 9 10 11 from django.contrib import adminfrom django.urls import path, includeurlpatterns = [ path('admin/' , admin.site.urls), path('' , include('users.urls' )), path('' , include('verifications.urls' )), path('' , include('areas.urls' )), ]