django-生鲜商城项目笔记

1.先搭建django虚拟环境
pip install virtualenv
在创建项目的文件夹中打开doc,virtualenv env
激活虚拟环境env\Script\activate.bat
下载django pip install django == 2.1.2
剩下的在pycharm中下载
**导出包列表
    pip freeze > package.txt
**使用导好的列表安装django
    pip install -r package.txt

# 创建登录装饰器
# 判断用户是否已登录,没有登录的话就重定向到登录界面
def login_docorator(func):
    def inner(request):
        uesrname = request.session.get('username')
        if username:
            return func(request)
        else:
            return redirect('/seller/login/')
    return inner
    
# md5加密 , 不可逆算法
import hashlib
def pwd_jm(password):
    md5 = hashlib.md5()
    md5.update(password.encode())
    result = md5.hexdigest()
    return result
    
# 注册功能,可以使用form表单
from django import forms
form django.forms import widgets

# 创建form表单类
class RegisterForm(forms.Form):
    username = forms.CharField(
        label = '用户名',
        required = True,
        min_length = 3,
        widget = widgets.TextInput(attrs={''placeholder': '用户名', 'class': 'layui-input''})
    )
    password = forms.CharField(
        label = '密码',
        required = True,
        min_length = 3,
        widget = widgets.TextInput(attrs={''placeholder': '密码', 'class': 'layui-input''})
    )
    nickname = forms.CharField(
        label = '昵称',
        required = True,
        min_length = 3,
        widget = widgets.TextInput(attrs={''placeholder': '昵称', 'class': 'layui-input''})
    )
    picture = forms.CharField(
        label = '头像',
        required = True,
        widget = widgets.FileInput(attrs={''placeholder': '头像', 'class': 'layui-input''})
    )
    
# 注册功能
# 导入时间模块 , 给上传的头像加时间戳确保上传的图片名称不一样
import time

def register(request):
    registerform = RegisterForm()
    if request.method == 'POST':
        registerform = RegisterForm(request.POST,request.FILES)
        if registerform.is_valid():
            data = registerform.cleaned_data
            username = data.get('username')
            nickname = data.get('nickname')
            password = data.get('password')
            picture = request.FILES.get('picture')
            time_temp = time.time()
            path = 'static/touxiang/'+str(time_temp)+'_'+picture.name
            with open(path,mode='wb') as f:
                for content in picture.chunks()
                    f.write(content)
            # 需使用加密后的密码存入数据库
            password = pwd_jm(password)
            models.Seller.objects.create(
                name=username,
                nickname=nickname,
                password=password,
                picture='touxiang/' + str(time_temp) + '-' + picture.name
            )
            return redirect('/seller/login/')
    return render(request, 'seller/register.html', {'registerform': registerform})


# 创建登录时提交的form表单类
class LoginForm(form.Form):
    username = forms.CharField(
        label='用户名',
        required=True,
        min_length=3,
        widget=widgets.TextInput(attrs={'placeholder': '用户名', 'class': 'layui-input'})
    )

    password = forms.CharField(
        label='密码',
        required=True,
        min_length=3,
        widget=widgets.PasswordInput(attrs={'placeholder': '密码', 'class': 'layui-input'})
    )

# 登录功能
def login(request):
    loginForm = LoginForm()
    error_msg = ''
    if request.method == "POST":
        loginForm = LoginForm(request.POST)
        if loginForm.is_valid():
            data = loginForm.cleaned_data
            username = data.get('username')
            password = data.get('password')
            pwd = pwd_jm(password)
            ret = models.Seller.objects.filter(name=username, password=pwd)
            if ret:
                # 设置session为了登录验证
                request.session['username'] = username
                nickname = ret[0].nickname
                request.session['nickname'] = nickname
                request.session['seller_id'] = ret[0].id
                return redirect('/seller/index/')
            else:
                error_msg = '用户名或密码错误'
    return render(request, 'seller/login.html', {'error_msg': error_msg})


# 导入模块 , 在页面显示登录时间
import datetime
# 加上装饰器
@login_docorator
def index(request):
    time = datetime.datetime.now()
    seller_id = request.session.get('seller_id')
    seller_obj = models.Seller.objects.get(id = seller_id)
    return render(request,'seller/index.html',locals())

# 退出登录
@login_docorator
def logout(request):
    # 清除session
    request.session.clear()
    # 重定向到登录界面
    return redirect('/seller/login/')

# 商品类增加
def type_add(request):
    error_msg = ''
    if request.method == 'POST':
        type_name = request.POST.get('type_name')
        if type_name:
            # 查询数据库是否重名
            ret = models.GoodsType.objects.filter(name=type_name)
            if not ret:
                models.GoodsType.objects.create(name=type_name)
                return redirect('/seller/goods_type_list/')
            else:
                error_msg='此类型已经存在'

    return render(request,'seller/type_add.html',{'error_msg':error_msg})

# 为商品添加操作添加ajax请求,失去鼠标触点就发送ajax请求
from django.http import JsonResponse
def type_add_ajax(request):
    dec = {'status':'true'}
    name = request.GET.get('name')
    type_obj = models.GoodsType.objects.filter(name=name)
    if type_obj:
        dic['status] = 'false'
    return JsonResponse(dic)
    
def goods_type_list(request):
    goods_type_obj_list = models.GoodsType.objects.all()
    return render(request,'seller/type_list.html',locals())

def goods_type_delete(request):
    id = request.GET.get('id')
    models.GoodsType.objects.get(id = id).delete()
    return redirect('/seller/goods_type_list/')

def goods_type_change(request):
    if request.method == 'POST':
        name = request.POST.get('type_name')
        id = request.POST.get('id')
        goods_type_obj = models.GoodsType.objects.get(id=id)
        goods_type_obj.name = name
        goods_type_obj.save()
        return redirect('/seller/goods_type_list/')

    else:
        id = request.GET.get('id')
        goods_type_obj = models.GoodsType.objects.get(id=id)
        return render(request,'seller/type_change.html',{'goods_type_obj':goods_type_obj})


商品添加:
    1.创建商品类,图片类
        商品与商品类一对多
        商品与商家一对多
        商品与图片一对多
    2.将商品类型导入商品添加页码
    3.后台接受页面提交的数据
        create新数据
        获取图片(多个)
        将图片存在后台static中
        将图片路径保存到图片类数据库中
商品展示:
    1.获取当前账户id
    2.获取当前账户的商品
    
商品删除:
    1.先删除图片的相关信息(后台及数据库)
        使用os.remove(path)
    2.后删除商品相关信息
    
商品修改:
    1.将当前商品信息传入页面
    2.获取页面传入的数据并更新商品数据库
    3.删除原有商品图片
    4.保存新上传的图片信息


用户界面:
需要导入卖家模型类 , 卖家视图的函数(密码加密等)  
一.创建首页
    将所有商家商品导入
    点击单个商品进入该商品详情,同时有其他商品链接
    方法一:
        正常操作
        goods_obj_list = seller_models.Goods.objects.all()
        return render(request,'buyer/index.html',{'goods_obj_list':goods_obj_list})
    方法二:
        在后台写好前端的逻辑
        def index(request):
            goods_image_obj_list = []
            goods_obj_list = seller_models.Goods.objects.all()
            for goods_obj in goods_obj_list:
                image_obj = goods_obj.goodimages_set.first()
                image_path = image_obj.img_address.name
                dic = {'goods_obj':goods_obj,'image_path':image_path}
                goods_image_obj_list.append(dic)
            return render(requst,'buyer/index.html',{'goods_image_obj_list':goods_image_obj_list})
    
    
二.用户注册及登录
    正常操作
    注意设置session及ajax验证
    设置session:
        1.方法一
        obj = models.Buyer.objects.filter(name=uesrname,password=password).first()
        if obj:
            request.session['name'] = obj.name
        2.方法二
        querset = models.Buyer.objects.filter(name=uesrname,password=password)
        if querset:
            request.session['name'] = querset[0].name
        删除session
            删除session
            request.session.flush() # 将整个session删除
            request.session.clear() # 将session的内容删除
        设置session失效时间
            request.session.set_expiry(value) # value为失效时间值
        
    设置cookie
        response = redirect('/buyer/index/')
        response.set_cookie('name',querset[0].name)
        return response
        删除cookie
        response.set_cookie('username',max_age=0) # 设置失效时间
        response.delete_cookie('username') # 直接删    除
        

三.登录后个人中心显示
    显示收货地址信息及其曾删改查操作
    
四.购物车
    def car_jump(request):
        # 1.判断用户是否已登录
            buyer_id = request.session.get(buyer_id)
            if buyer_id:
                # 2.若是先加入购物车后登录的,获取Session或cookie中数据并去数据库调用相关数据
                if request.method == 'GET':
                    # 从cookie中获取商品id和数量
                    goods_id = request.COOKIES.get('goods_id')
                    count = request.COOKIES.get('count')
                    # 查询数据库, 将信息返回给页面
                    goods_obj = seller_models.Goods.objects.get(id=goods_id)
                    goods_name = goods_obj.good_name
                    goods_image_path = goods_obj.goodimages_set.first().img_address
                    goods_price = goods_obj.goods_xprice
                    all_goods_price = int(goods_price) * int(count)
                    buyer_car_obj = models.Car.objects.filter(goods_id=goods_id,buyer_id=buyer_id).first()
                    # 判断该商品是否已加入购物车,若已加入则修改数量
                    if buyer_car_obj:
                        buyer_car_obj.goods_num += int(count)
                        buyer_car_obj.save()
                    else:
                        models.Car.objects.create(
                            goods_id=goods_id,
                            goods_name=goods_name,
                            goods_picture=goods_img_path,
                            goods_price=goods_price,
                            goods_num=count,
                            buyer_id=buyer_id
                        )
                    # 删除cookie
                    response = render(request,'buyer/car_jump.html',locals())
                    response.delete_cookie('goods_id')
                    response.delete_cookie('count')
                    return response
                # 3.若是已登录后添加购物车的,按正常操作
                else:
                    goods_id = request.GET.get('id')
                    count = request.POST.get('count')  # 商品数量
                    goods_name = request.POST.get('goods_name')  # 商品名称
                    goods_price = request.POST.get('goods_cprice')  # 商品现价
                    goods_img_path = request.POST.get('goods_img_path') # 商品缩略图
                    all_goods_price = int(goods_price) * int(count)
                    buyer_car_obj = models.Car.objects.filter(goods_id=goods_id,buyer_id=buyer_id).first()
                    # 判断该商品是否已加入购物车,若已加入则修改数量
                    if buyer_car_obj:
                        buyer_car_obj.goods_num += int(count)
                        buyer_car_obj.save()
                    else:
                        models.Car.objects.create(
                            goods_id=goods_id,
                            goods_name=goods_name,
                            goods_picture=goods_img_path,
                            goods_price=goods_price,
                            goods_num=count,
                            buyer_id=buyer_id
                        )
                return render(request,'buyer/car_jump.html',locals())
    
                    
                    
            # 4.若未登录,获取传过来的数据,保存在session中或cookie中,重定向到登录界面
            goods_id = request.GET.get('goods_id')
            count = request.POST.get('count')
            response = redirect('/buyer/login/')
            response.set_cookie('goods_id',goods_id)
            response.set_cookie('count',count)
            return response
            
    购物车列表显示 , 删除 , 清空

五.确认订单
    创建订单模型类和订单中商品的详情模型类
    class Order(models.Model):
        order_num = models.CharField(max_length = 32) # 订单号
        order_time = models.DateField()
        order_status = models.CharField(max_length=32) # 订单状态
        order_total = models.FloatField()# 商品总价
        buyer = models.ForeignKey(to='Buyer',on_delete=models.CASCADE)
        address = models.ForeignKey(to='Address',on_delete=models.CASCADE)
    
    class OrderGoods(models.Model):
        # 跟购物车的模型类一样 , 只是这里跟订单类建立了一对多关系
        goods_name = models.CharField(max_length=32)  # 商品名字
        goods_picture = models.CharField(max_length=32)  # 商品缩略图
        goods_num = models.IntegerField()  # 商品数量
        goods_price = models.FloatField()  # 商品单价
        goods_id = models.IntegerField()  # 商品id
        order = models.ForeignKey(to='Order',on_delete=models.CASCADE)
        
    import random , time , datatime
    # 生成随机数拼接订单号
    def get_random_num():
        num = random.randint(1000,9999)
        return num
    
    def enter_order(request):
        address_id = rquest.POST.get('address')
        address_obj = models.Address.objects.get(id = address_id)
        times = datetime.datetime.now()
        now_time = times.strftime('%Y-%m-%d')
        new_buycar_list = []
        goods_all_price = 0
        # 获取后台传来的数据
        for key,value in request.POST.items():
            if key.startswith('name_'):
                buycar_obj = models.Car.objects.get(id=value)
                goods_xiaoji = int(buycar_obj.goods_num)*fioat(buycar_obj.goods_price)
                dic = {'buyer_obj':buycar_obj,'goods_xiaoji':goods_xiaoji}
                new_buycar_list.append(dic)
                goods_all_price += goods_xiaoji
            
            # 保存到订单数据库
            order_obj = models.Order.objects.create(
                order_num = now_time + str(get_random_num()),
                order_time = now_time,
                order_status = '1',
                order_total = goods_all_price,
                buyer_id = request.session.get('buyer_id'),
                address = address_obj,
            )
            # 保存订单中的商品详情
            for new_buycar_dic in new_buycar_list:
                buycar_obj = new_buycar_dic.get('buycar_obj')
                models.OrderGoods.objects.create(
                    goods_id = buycar_obj.goods_id,
                    oods_name=buycar_obj.goods_name,
                    goods_num=buycar_obj.goods_num,
                    goods_price=buycar_obj.goods_price,
                    goods_picture=buycar_obj.goods_picture,
                    order=order_obj
                )
            return render(request,'buyer/enter_order.html',locals())


六.添加支付宝
    加载第三方模块
    python-alipay-sdk
    教程网址:https://github.com/fzlee/alipay/blob/master/README.zh-hans.md
    蚂蚁金服官网入驻 , 使用沙箱支付宝 , 下载RSA签名工具生成秘钥和公钥
    
    from alipay import AliPay
    def alipay_method(request):
        order_num = request.GET.get('order_num')
        total = request.GET.get('total')
        # 商家私有秘钥
        app_private_key_string = """-----BEGIN RSA PRIVATE KEY-----
            MIIEpQIBAAKCAQEAyxlAeCqSs3qmB6zIlhAmqRQsetRM3H176CsnFTdBzlBRRKf7l266QHgWmHFovSqw4pAUnEBRJYE1slbLg6Mn3TzNhyeJSt+jZC9l2Ylz+NVOqmpCDPzMPbhnODrt2qgiNcoqjG3N9OEQqHACJ32g2Ei/oiS5uAD7x/G0WigzAaMkc0yTCf1gCg7AeUaCOK/+Pn5P+JPdjzwMDTgB17k/aLZwLWzN4bAHdgT21aYFeGtgn2V4ce78KjA9ekZITFraTY2xbl7ofcVXi/dXViNQEVqIOKcoAX5CUdGou3MEfkeL2pgRmvdHLCS4cFkM8DRwMA+XArbBp3SkuOXuXeYpJQIDAQABAoIBAQCajMG5b7Qo7ekQKBSP1QSGX3qlkY5XrwmuF8Bq7Zye8hGVrDrQ9oq26mtPX+WzJZxrG/cDHBJj9to0tsWxi2OXgGBqO9TG7D26zDK2AloE/dUZ6zgOCAUn5n5tlLJRVOaLhicwq5IxiV8SvgF1qazPSTTCny3QbrcqZKy4eqSt1eouhkjgqY7o+xuYsy9dAGW958U0SGMvLrb1erTF3aEXDxFRHFZTCwyWmjYjwUxBm8BKQRXIuzagYOkFQmRJT05CbO8IWoc8JBM+00dKxD7yeyKtTifQY2FzqtwCERuMzBrwz0wo1G5t5mJ9ZERc0u4W9OfJl/6lppI7I1nbmNohAoGBAPohxh3jqes9WrN+6VhH1VtCPU+EGXzOXdHuRCpMMhViP5tunu0BmigI0Cafv49Bn1FyCNG1xZwlsE7+M6Npj35+V/BQmhUGBv8DYnf/qXLdjM5NavsD8/cGDMrhy9LUHhWy53HdHx/cusZLHLoolpfZyXPXOxrFCDCm39o1ddqJAoGBAM/dAiqumJKLQ79tCV0BYRKPXBrQXX2j7rgr/h9gb/4wXwVoViStq4DqQ28izWVl5QMziQh7sXc+EkngRYmSzhy9FrDVCHVpu7skxe9zaMwpUOPcQIHxWlcWN6hp3Fh3pcEN/I9qzlPDLLGq/RqE2NOUPhWqt3qGWPfc4FQyCMK9AoGBAOAhC0kVCtjC7VcRTT3RgBh5zj5F/CCdOew2N9Y+2FHY6233PWjZmqxs2TcCxb8z6fIs4EIpQpycGNNvbA3tNKr/wwSO9MIJ2JMBEWa9K7TFWLozHL032Y9rWGMi2GRdtWd0G3cn0A/Y1XOBMoiMfgQrHhwyq79c9e3CWatJZAUhAoGAGZ72O2iV6co8qYW5F7upyW3ePnfcbjYcoJrbkeaDJ2Oy8qmvpIm7kAJQGYzCoHL0zXY2t9L3Rulhu7VnHNP5j9VGzLkVd9N2jlS0CRXCnxegntVxJhMnvYBBkAKsZEMrLSaaMNtLX0u5YJTg6bniOAIXvPfz8ahJoxOYmwgnyEkCgYEAncNyAiBPS5nFcJq0yxtaqdfAfIW+h6SxXBWkdI66bK+YEZ3hvoW42z4cyuo9WbdoKJ4UKP8m0UAQ+qF6gxTvo5jpbaxgYDRpzTbj4B5exUqvH4jyVjZ+U1ASoC/MOVw+HApvdLpcnd9kcIRfNk8FuA6Fvj6UmQJLsc0pA+b19KI=
        -----END RSA PRIVATE KEY-----"""
        # 支付宝返回的支付宝公钥
        alipay_public_key_string = """-----BEGIN PUBLIC KEY-----
            MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlTKZzALbl67tl//jq7pWyjUsRe887eogf67LLFkR+AnDN6CRtkG5VIlHOQrL3xgBKZkrT6LeOFIyBy82fRM5yXOTJsyqxfwM5Bi+2sOs2QpzonkxPDFQUPmp8svgX7suXtAIZPNDfpVMb3AZ5JkpczGfFE8bEMo0CoVbpQbPLdjFFlTfoPfEmj6jWVTO7StSBrNwTfT1VxcGjtlTao73WQ3NquWDzxdkvsb3Jq5gB2hOsCU5vB71sedQWtbuFHdulZK9PUytn9xd0r5chZyN0+k+bGrEQD7tuj1rnDkJEGF/bCGK9Z7U1E7+2dRo4u1WmQ+T1Y35OYyxoc3MAr+jiQIDAQAB
        -----END PUBLIC KEY-----"""
        
        alipay = AliPay(
            appid="2016101300679685", # 看用户信息
            app_notify_url=None,  # 默认回调url
            app_private_key_string=app_private_key_string,
            # 支付宝的公钥,验证支付宝回传消息使用,不是你自己的公钥,
            alipay_public_key_string=alipay_public_key_string,
            sign_type="RSA2",  # RSA 或者 RSA2 , 看用户信息
            debug=True,  # 默认False
        )
        order_string = alipay.api_alipay_trade_page_pay(
            out_trade_no=str(order_num),  # 订单号
            total_amount=str(total),  # 总价
            subject='水果商城',  # 标题
            return_url=None,
            notify_url=None,  # 可选, 不填则使用默认notify url
        )
        return redirect('https://openapi.alipaydev.com/gateway.do?' + order_string)

            
七.邮箱验证
    # 设置settings
        EMAIL_HOST_USER = '你的163邮箱'
        EMAIL_HOST_PASSWORD = '邮箱授权码设置的密码'
        EMAIL_USE_SSL = True
        EMAIL_HOST = 'smtp.163.com'
        EMAIL_PORT = 994
    # 创建邮箱模型类用于储存邮箱账户,验证码,时间戳
    class EmailVaild(models.Model):
        email_name = models.CharField(max_length=32)
        value = models.CharField(max_length=32)
        time = models.DateTimeField()
        
    from django.core.mail import EmailMultiAlternatives
    from django.http import JsonResponse
    def send_message(request):
        result = {'status':'error','data':''}
        if request.method == 'GET':
            email_name = request.GET.get('email')
            if email_name:
                try:
                    subject = '全球生鲜商城验证码'
                    yzm = get_random_num()
                    text_content = str(yzm)
                    msg = EmailMultiAlternatives(subject,text_content,'你的邮箱',[email_name])
                    msg.send()
                eccept Exception as e:
                    # 有异常执行
                    result['data'] = str(e)
                else:
                    result['status'] = 'success'
                    result['data'] = 'success'
                    models.EmailVaild.object.create(
                        email_name = email_name,
                        value = yzm,
                        time = datetime.datetime.now()
                        )
                finally:
                    return JsonResponse(result)
        return redirect('/buyer/register_email/')
    
    def register_email(request):
        error_msg={}
        if request.method == 'POST':
            email_name = request.POST.get('emailname')
            code = request.POST.get('code')
            userpass = request.POST.get('userpass')
            email_obj = models.EmailVaild.objects.filter(email_name=email_name).first()
            if email_obj:
                if code == email_obj.value:
                    db_time = time.mktime(email_obj.time.timetuple())
                    now_time = time.time()
                    if now_time-db_time<180: # 3min
                        models.Buyer.objects.create(
                            name = email_name,
                            password = pwd_jm(userpass)
                            )
                        email_obj.delete()
                        return redirect('/buyer/login/')
                        
                    else:
                        error_msg['yam_sx'] = '验证码失效'
                else:
                    error_msg['yzm_error'] == '验证码错误'
            else:
                error_msg['email_error'] == '邮箱不存在'
        return render(request,'buyer/register_email',{'error_msg':error_msg})
        
八.电话短信验证
    # 短信验证http://www.ihuyi.com/
    官网接口文档修修改改就ok
    其他步骤同上
                    

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(Django)