django配置

qq登录

dev

QQ_CLIENT_ID = '101792382'  # 应用ID
QQ_REDIRECT_URI = 'http://demo.myuxi.wang/oauth_callback.html'  # 回调网址
QQ_STATE = '/wap/member/member.html'  # 会员中心
QQ_CLIENT_SECRET = '09a0d1903eb475f6c9e7181048a8e7b0'  # 应用秘钥

qq认证类

import json
import logging
import urllib
from urllib.request import urlopen

from django.conf import settings
from rest_framework.serializers import Serializer

from oauth.constants import BING_USER_ACCESS_TOKEN_EXPIRES
from oauth.excepterror import OauthQQAPIError

logger = logging.getLogger(‘django’)

from itsdangerous import TimedJSONWebSignatureSerializer as TJWSSerializer, BadData

class OAuthQQ(object):

 """
    QQ认证辅助工具类
    """

    def __init__(self, client_id=None, client_secret=None, redirect_uri=None, state=None):
        self.client_id = client_id if client_id else settings.QQ_CLIENT_ID
        self.redirect_uri = redirect_uri if redirect_uri else settings.QQ_REDIRECT_URI
        # self.state = state if state else settings.QQ_STATE
        self.state = state or settings.QQ_STATE
        self.client_secret = client_secret if client_secret else settings.QQ_CLIENT_SECRET

    def get_login_url(self):
        url = 'https://graph.qq.com/oauth2.0/authorize?'
        params = {
            'response_type': 'code',
            'client_id': self.client_id,
            'redirect_uri': self.redirect_uri,
            'state': self.state  # 登陆后默认跳转地址
        }
        url += urllib.parse.urlencode(params)
        # print(url)
        return url

    def get_login_token(self, code):
        url = 'https://graph.qq.com/oauth2.0/token?'
        params = {
            'grant_type': 'authorization_code',
            'client_id': self.client_id,
            'client_secret': self.client_secret,
            'code': code  # 登陆后默认跳转地址
            , 'redirect_uri': self.redirect_uri
        }
        url += urllib.parse.urlencode(params)
        try:
            resp = urlopen(url)  # 发送请求
            print(type(resp))

            resp_data = resp.read().decode()  # str
            print('resp_data', resp_data)
            print(type(resp_data))
            # 吧 str转换成字典类型,一层获取他的token
            resp_dict = urllib.parse.parse_qs(resp_data)
            print(resp_dict)
        except Exception as e:
            logger.error("获取access_token异常: %s" % e)
            raise OauthQQAPIError
        else:
            access_token = resp_dict.get("access_token")
            print('action_token', access_token)
            return access_token[0]

    def get_login_opeid(self, access_token):
        url = 'https://graph.qq.com/oauth2.0/me?access_token=' + access_token
        # url返回的数据callback( {"client_id":"YOUR_APPID","openid":"YOUR_OPENID"} );

        try:
            resp = urlopen(url)
            resp_data = resp.read().decode()
            resp_data = resp_data[10:-4]
            print('resp_date', resp_data)
            resp = json.loads(resp_data)

        except Exception:
            logger.error("获取opend_id异常")
            raise OauthQQAPIError
        else:
            openid = resp.get('openid')
            print(openid, "openid")
        return openid

    def get_noteist_user(self, openid):
        s = TJWSSerializer(settings.SECRET_KEY, BING_USER_ACCESS_TOKEN_EXPIRES)  # 配置 (秘钥,有效期
        token = s.dumps({"openid": openid})
        return token.decode()

    @staticmethod
    def check_noteist_user(access_token):
        s = TJWSSerializer(settings.SECRET_KEY, BING_USER_ACCESS_TOKEN_EXPIRES)  # 配置 (秘钥,有效期

        try:
            data = s.loads(access_token)
            print(data['openid'])
        except BadData:
             return None

        else:
            print('openidlllllll',data['openid'])
            return data['openid']

设置序列化器

#! /usr/bin/env python
# -*- coding: utf-8 -*-
# author:weizi
from django_redis import get_redis_connection
from rest_framework import serializers

from oauth.models import OAuthQQUser
from oauth.utils import OAuthQQ
from users.models import User


class OAuthQQUserSerialzier(serializers.ModelSerializer):
    """创建或绑定用户的序列化器"""
    mobile = serializers.RegexField(label="手机号", regex=r'1[3-9]\d{9}$')
    sms_code = serializers.CharField(label="短信验证码", write_only=True)
    tuser = serializers.CharField(label="推荐码", write_only=True, allow_null=True, allow_blank=True)
    access_token = serializers.CharField(label="操作凭证", write_only=True)

    token = serializers.CharField(label="JWT token", read_only=True)  # JWT


    class Meta:
        model = User
        fields = ("id","username", "password", "tuser", "sms_code", "mobile", "promoter", "promocode", "token",'access_token')
        extra_kwargs = {
            'username': {
                'read_only':True
            },
            'password': {
                'write_only': True,
                'min_length': 6,
                'max_length': 20,
                'error_messages': {
                    'min_length': '仅允许6-20个字符的密码',
                    'max_length': '仅允许6-20个字符的密码',
                }
            },
            'tuser': {
                'max_length': 11,
                'error_messages': {
                    'max_length': '仅允许最大11个字符的推荐码',
                }
            }
        }


    def validate(self, data):
        access_token = data['access_token']
        openid = OAuthQQ.check_noteist_user(access_token)
        if not openid:
            raise serializers.ValidationError("无效的access_token")
        data['openid'] = openid

        """判断短信验证码"""
        redis_conn = get_redis_connection('verify_codes')
        mobile = data["mobile"]
        real_sms_code = redis_conn.get("sms_%s" % mobile)

        if real_sms_code is None:
            raise serializers.ValidationError("无效的验证码")
        if data["sms_code"] != real_sms_code.decode(): # 从redis取出来的数据都是二进制 必须进行解码
            raise serializers.ValidationError("短信验证码错误")

        # 如果用户存在,检查用户手机对应的密码是否正确
        try:
            user = User.objects.get(mobile=mobile)
        except User.DoesNotExist:
            pass
        else:
            password = data['password']
            if not user.check_password(password):
                raise serializers.ValidationError("密码错误")
            data['user'] = user

        return data

    def create(self, validated_data):
        """重写保存方法 密码也要加密"""
        print(validated_data)

        openid = validated_data['openid']
        user = validated_data.get('user') # 如果用户不存在 None
        mobile = validated_data['mobile']
        password = validated_data['password']
        promocode = validated_data['tuser']

        try:
            upuser = User.objects.get(promocode=promocode)
        except User.DoesNotExist:
            promoter = 0
        else:
            promoter = upuser.id

        # 判断用户是否存在
        if not user:
            user = User.objects.create_user(username=mobile,mobile=mobile,password=password,promoter=promoter) # create_user 底层自动会把密码加密保存

        OAuthQQUser.objects.create(user=user, openid=openid)

        # 颁发令牌
        from rest_framework_jwt.settings import api_settings # 切记 不要导错包
        jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

        payload = jwt_payload_handler(user)
        token = jwt_encode_handler(payload)

        user.token = token # 赋值 颁发token

        return user

view

from django.shortcuts import render

# Create your views here.
from rest_framework import status
from rest_framework.generics import CreateAPIView
from rest_framework.response import Response
from rest_framework.views import APIView
from django.http import HttpResponse

from oauth.excepterror import OauthQQAPIError
from oauth.models import OAuthQQUser
from oauth.serializers import QqUserSerializer
from oauth.seriallizers1 import OAuthQQUserSerialzier
from oauth.utils import OAuthQQ


# 跳转到qq登陆页面
class OauthView(APIView):
    def get(self, request):
        # city = request.args.get('c')
        next = request.query_params.get('next')

        # print(city)
        oauth_QQ = OAuthQQ(state=next)  # 这里的state是为了登陆成功后返回的url
        login_url = oauth_QQ.get_login_url()
        print(login_url)

        return Response({"login_url": login_url})

  

class QqUserView(CreateAPIView):

    def get(self, request):
        code = request.query_params.get('code')
        if not code:
            return Response({"status": "缺少code"}, status=status.HTTP_400_BAD_REQUEST)
        try:
            oauth_QQ = OAuthQQ(state=next)
            oauth_token = oauth_QQ.get_login_token(code)
            openid = oauth_QQ.get_login_opeid(oauth_token)
            #return Response({'openid':openid})
            print('view里面的openid',openid)
        except OauthQQAPIError:
            return Response({"emssage": "qq接口出现问题"},
            status = status.HTTP_503_SERVICE_UNAVAILABLE)

        try:
            oauth_qq_user = OAuthQQUser.objects.get(openid=openid)
        except OAuthQQUser.DoesNotExist:
            # 如果openid数据不存在,处理这个openid并返回

            access_token =oauth_QQ.get_noteist_user(openid)
            # 用户自己生成的access_token
            return Response({'access_token': access_token})




        else:
            # 如果数据存在,表示用户已经绑定过身份 签发token
            # 颁发令牌
            from rest_framework_jwt.settings import api_settings  # 切记 不要导错包
            jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
            jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
            user = oauth_qq_user.user
            payload = jwt_payload_handler(user)
            token = jwt_encode_handler(payload)
            print(token)
            return Response({'token': token, 'username': user.username, 'user_id': user.id})

    serializer_class = OAuthQQUserSerialzier
    def post(self,request,*args,**kwargs):
         return super().post(request,*args, **kwargs)
         # return Response(request.data)



记得配置对应的urls
urlpatterns = [
re_path(r’^qq/authorization/ ′ , v i e w s . O a u t h V i e w . a s v i e w ( ) ) , r e p a t h ( r ′ q q / u s e r / ', views.OauthView.as_view()), re_path(r'^qq/user/ ,views.OauthView.asview()),repath(rqq/user/’, views.QqUserView.as_view()),
]

七牛云存储

dev

‘’’

qiniustorage  app注册
#七牛存储
QINIU_ACCESS_KEY = 'nyXcuSxtLRxBX2SRFphG2DjNDuEFFkyCqHRrr7I2'
QINIU_SECRET_KEY = 'FWpyEKyAivREU_H9amdOo2LEGvNvVmOO4Hc-beKh'
QINIU_BUCKET_NAME = 'yxwall'
QINIU_BUCKET_DOMAIN = 'qglcu1e3u.hb-bkt.clouddn.com/'  # 解析的域名
QINIU_SECURE_URL = False  # 使用http

PREFIX_URL = 'http://'  # 前缀协议是否用https

MEDIA_URL = PREFIX_URL + QINIU_BUCKET_DOMAIN + '/media/'

# MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_ROOT = 'media'

STATIC_URL = QINIU_BUCKET_DOMAIN + '/static/'
STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'static'),
]
# STATIC_ROOT = os.path.join(BASE_DIR, 'static')
STATIC_ROOT = "static"  # 静态文件收集

DEFAULT_FILE_STORAGE = 'qiniustorage.backends.QiniuMediaStorage'
STATICFILES_STORAGE = 'qiniustorage.backends.QiniuStaticStorage'
'''

python manage.py collectstatic 命令收集

白名单配置

添加白名单

pip install django-cors-headers
INSTALLED_APPS = (

‘corsheaders’,

)
MIDDLEWARE = [
‘corsheaders.middleware.CorsMiddleware’,

]

CORS_ORIGIN_WHITELIST = (
    'http://127.0.0.1',
    'http://localhost',
    'http://m.myuxi.com',
    'http://api.myuxi.com',
    'http://demo.myuxi.wang',
)
CORS_ALLOW_CREDENTIALS = True  # 允许携带cookie

定时任务

# 这里的目录是在www中生成index.html静态文件 定时生成
GENERATED_STATIC_HTML_FILES_DIR = os.path.join(os.path.dirname(os.path.dirname(BASE_DIR)), 'www')
# 解决crontab中文问题
CRONTAB_COMMAND_PREFIX = 'LANG_ALL=zh_cn.UTF-8'
# 定时任务
CRONJOBS = [
    # 每2分钟执行一次生成主页静态文件
    ('*/5 * * * *', 'contents.crons.generate_static_index_html',
     '>> /home/sixstar/Desktop/MyxAll/myuxiwall/logs/crontab.log')
]

import sys
sys.path.insert(0, '../')
sys.path.insert(0, '../myuxiwall/apps')
# sys.path.insert(0, '../myuxiwall/utils')
if not os.getenv('DJANGO_SETTINGS_MODULE'):
    os.environ['DJANGO_SETTINGS_MODULE'] = 'myuxiwall.settings.dev'
import django
django.setup()  # 项目初始化
# 防止找不到路径,进在系统路径中添加
from django.conf import settings
from django.template import loader

from goods.models import SKU
def generate_static_index_html(sku_id):
    """
    生产静态首页 http://demo.myuxi.wang/index.html
    :return:
    """
    # 查询各个数据表的数据 组成复杂的数据

    sku = SKU.objects.get(id=sku_id)
    sku.image = sku.skuimage_set.all()
    Goods ={
        "sku":sku
    }
    # 制定一个首页的模板 ,templates是一个链接对象明白
    templates = loader.get_template('detail_temp.html')

    # 吧goods数据写入这个模板中
    html_text = templates.render(Goods)
    temp_path = os.path.join(settings.GENERATED_STATIC_HTML_FILES_DIR, 'wap/shop/goods/'+str(sku_id)+'.html')
    print("ok")

    with open(temp_path,'w') as f:
        f.write(html_text)

if __name__ == '__main__':
    skus =SKU.objects.all()
    for sku in skus:
        print(sku.default_image_url)
        generate_static_index_html(sku.id)

python manage.py crontab add 添加定时任务
python manage.py crontab show 查看

日志

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,  # 是否禁用已经存在的日志器
    'formatters': {  # 日志信息显示的格式
        'verbose': {
            'format': '%(levelname)s %(asctime)s %(module)s %(lineno)d %(message)s'
        },
        'simple': {
            'format': '%(levelname)s %(module)s %(lineno)d %(message)s'
        },
    },
    'filters': {  # 对日志进行过滤
        'require_debug_true': {  # django在debug模式下才输出日志
            '()': 'django.utils.log.RequireDebugTrue',
        },
    },
    'handlers': {  # 日志处理方法
        'console': {  # 向终端中输出日志
            'level': 'DEBUG',
            'filters': ['require_debug_true'],
            'class': 'logging.StreamHandler',
            'formatter': 'simple'
        },
        'file': {  # 向文件中输出日志
            'level': 'INFO',
            'class': 'logging.handlers.RotatingFileHandler',
            'filename': os.path.join(os.path.dirname(BASE_DIR), "logs/yxmall.log"),  # 日志文件的位置
            'maxBytes': 300 * 1024 * 1024,
            'backupCount': 10,
            'formatter': 'verbose'
        },
    },
    'loggers': {  # 日志器
        'django': {  # 定义了一个名为django的日志器
            'handlers': ['console', 'file'],  # 可以同时向终端与文件中输出日志
            'propagate': True,  # 是否继续传递日志信息
            'level': 'INFO',  # 日志器接收的最低日志级别
        },
    }
}

搜索引擎

Haystack

dev下

HAYSTACK_CONNECTIONS = {
    'default': {
        'ENGINE': 'haystack.backends.elasticsearch_backend.ElasticsearchSearchEngine',
        'URL': 'http://192.168.1.100:9200/',  # 此处为elasticsearch运行的服务器ip地址,端口号固定为9200
        'INDEX_NAME': 'myuxi',  # 指定elasticsearch建立的索引库的名称
    },
}
# 当添加、修改、删除数据时,自动生成索引
HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor'
# HAYSTACK_SEARCH_RESULTS_PER_PAGE = 2

在这里插入图片描述设置搜索索引
之前会需要docker运行一个容器
之后
pip install drf-haystack
pip install elasticsearch==2.4.1

INSTALLED_APPS = [

‘haystack’,

]

新建一个search_index.py


class SKUIndex(indexes.SearchIndex, indexes.Indexable):
    """
      SKU索引数据模型类
      """
    text = indexes.CharField(document=True, use_template=True)
    id = indexes.CharField(model_attr='id')
    name = indexes.CharField(model_attr='name')
    price = indexes.DecimalField(model_attr='price')
    default_image_url = indexes.CharField(model_attr='default_image_url')
    comments = indexes.IntegerField(model_attr='comments')

    def get_model(self):
        return SKU

    def index_queryset(self, using=None):
        return self.get_model().objects.filter(is_launched=True)

序列化器指定

from goods.search_indexes import SKUIndex
class SKUIndexSerializer(HaystackSerializer):
    class Meta:
        index_classes = [SKUIndex]
        filter = ('text', 'id', 'name', 'price', 'comments', 'default_image_url')

手动生成索引

python manage.py rebuild_index

view

from drf_haystack.viewsets import HaystackViewSet

class SKUSearchViewSet(HaystackViewSet):
"""
    SKU搜索
    """

    index_models = [SKU]
    serializer_class = SKUIndexSerializer

定义路由

router = DefaultRouter()
router.register('skus/search', views.SKUSearchViewSet, base_name='skus_search')
urlpatterns += router.urls

测试

http://127.0.0.1:8000/skus/search/?text=wifi
http://127.0.0.1:8000/skus/search/?id=1
http://127.0.0.1:8000/skus/search/?name=iphone

图片验证码

需要导包

class ImageAPiVew(APIView):
    def get(self,request,iamge_code_Id):
        text,image = captcha.generate_captcha()
        return HTTPResponse(image,context_type= 'image/jpg')

短信验证码

需要导包调用

 import sys
import logging
import uuid
# 需要安装 pip install aliyun-python-sdk-core-v3 aliyun-python-sdk-dysmsapi
from aliyunsdkdysmsapi.request.v20170525 import SendSmsRequest
# from aliyunsdkdysmsapi.request.v20170525 import QuerySendDetailsRequest
from aliyunsdkcore.client import AcsClient
from aliyunsdkcore.profile import region_provider
# from aliyunsdkcore.http import method_type as MT
# from aliyunsdkcore.http import format_type as FT
from django_redis.serializers import json

logger = logging.getLogger('django')
"""
短信业务调用接口示例,版本号:v20170525
"""
ACCESS_KEY_ID = "LTAIcbWjQFpuyqud"
ACCESS_KEY_SECRET = "aI6tNQTVNIekVosPoVLk67wt9Wjgi0"
"""
try:
    reload(sys)
    sys.setdefaultencoding('utf8')
except NameError:
    pass
except Exception as err:
    raise err
"""
# 注意:不要更改
REGION = "cn-hangzhou"
PRODUCT_NAME = "Dysmsapi"
DOMAIN = "dysmsapi.aliyuncs.com"

acs_client = AcsClient(ACCESS_KEY_ID, ACCESS_KEY_SECRET, REGION)
region_provider.add_endpoint(PRODUCT_NAME, REGION, DOMAIN)

def send_sms(business_id, phone_numbers, sign_name, template_code, template_param=None):
    smsRequest = SendSmsRequest.SendSmsRequest()
    # 申请的短信模板编码,必填
    smsRequest.set_TemplateCode(template_code)
    # 短信模板变量参数
    if template_param is not None:
        smsRequest.set_TemplateParam(template_param)
    # 设置业务请求流水号,必填。
    smsRequest.set_OutId(business_id)
    # 短信签名
    smsRequest.set_SignName(sign_name)
    # 数据提交方式
	# smsRequest.set_method(MT.POST)
	# 数据提交格式
    # smsRequest.set_accept_format(FT.JSON)
    # 短信发送的号码列表,必填。
    smsRequest.set_PhoneNumbers(phone_numbers)
    # 调用短信发送接口,返回json
    smsResponse = acs_client.do_action_with_exception(smsRequest).decode()
    # TODO 业务处理
    return smsResponse

def send_sms_code(mobile,code):
   try:
       __business_id = uuid.uuid1()
       ret = send_sms(__business_id, mobile, "新奇特商城", "SMS_120410887", {"code": code})
       #ret = {"Message": "OK", "RequestId": "03AD9770-0E46-4047-B954-51889CD27A9D", "BizId": "462021798320537017^0",
             # "Code": "OK"}
       result = json.loads(ret).get('Message')
   except Exception as e:
       logger.error("验证码错误")
   else:
       if result =='OK':
           logger.info("验证码正常")
       else:
           logger.error('验证码错误了')



# if __name__ == '__main__':
#     __business_id = uuid.uuid1()
#     # print(__business_id)
#     params = '{"code":"123456"}'
#     print(send_sms(__business_id, "17610805506", "新奇特商城", "SMS_120410887", params))

redis在django的使用数据库连接

建立数据库链接

    redis_conn = django_redis.get_redis_connection('verify_codes')
    pl = redis_conn.pipeline()  # redis管道
    pl.setex("sms_%s" %mobile,有效期,sms_code)
    pl.setex("sms_flag_%s" % mobile,间隔时间,1)
    pl.execute() 执行操作
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值