美多商城项目(十)

2019-07-18 13:03:01 浏览数 (1)

正文共: 8702字 21图 预计阅读时间: 22分钟

项目仓库

代码语言:javascript复制
https://github.com/EthanYan6/E-commerce-sites.git

结合代码查看笔记,效果更佳。笔记只是记录重点或者难点。

每日分享

It is time to shed the burdens of the past year and come up fresh and alive.

是时候摆脱过去一年的负担,重新焕发活力。

小闫语录

身边总会有人问『我做xxx,什么时候开始比较好?』我的答案永远不会变『从现在开始』

做一件事,不要觉得现在时间尚早,也不要觉得为时已晚。开始做一件事的最佳的时间永远是现在。其实我们有很大一部分时间都是浪费在了犹豫上,而不是在解决问题上。考研的时候,有人会觉得都9月份了,其他人都准备半年了,我肯定比不过他们。算了,我明年再考吧......也有人会觉得都9月份了,我一定要比别人更加努力,一定要在12月份的时候赶上去,然后开始了详细的计划。只要你下定决心开始,那一刻永远不会晚。有人利用几个月时间考上了心仪的学府,也有人准备一两年仍然名落孙山。

如果你有正在犹豫的事,现在开始下定决心去做吧!

美多商城项目(十)

1.订单支付流程-支付宝

1.客户端点击支付,向服务器发送一个请求。携带订单的id。

客户端申请访问获取支付网址和参数,服务器向其返回。

2.服务器返回给客户端支付宝的支付网址和参数。

业务参数:outtradeno商户订单号;total_amout订单总金额;subject订单标题。 可选参数:returnurl同步回调地址,支付成功之后的回调地址,支付结果相关参数在回调网址后;notifyurl异步通知地址,用户完成之后,支付宝会访问此地址,然后支付宝通知商户用户支付结果。

3.客户端访问支付网址。

4.支付宝让客户端重定向访问订单支付页面。

5.客户端访问订单支付页面地址。

6.支付宝平台返回订单支付页面。

7.客户端让用户登录支付宝,选择支付方式,点击确认付款。

8.支付宝让客户端浏览器重定向访问return_url指定的地址。

9.客户端访问return_url指定的地址,服务器保存支付信息。

服务器保存支付结果相关信息

10.服务器向客户端返回支付结果。

2.支付宝支付API

2.1获取支付宝支付网址和参数

代码语言:javascript复制
API: GET /orders/(?P<order_id>d )/payment/
参数:
    通过请求头,传递jwt token
    通过url地址传递订单编号
响应:
    {
        "alipay_url":"支付宝支付网址和参数"
    }
2.1.1业务逻辑

1.需要用户登录,设置权限。

1.1获取登录用户

2.获取order_id并校验订单是否有效。

代码语言:javascript复制
# 关键代码
order = OrderInfo.objects.get(order_id=order_id,
                             user=user,
                             pay_method=OrderInfo.PAY_METHODS_ENUM['ALIPAY'],
                             status=OrderInfo.ORDER_STATUS_ENUM['UNPAID'])

订单号是否存在;是否是此用户的订单;支付方式是否是支付宝;是否是待支付订单。

3.组织支付宝支付网址和参数。

代码语言:javascript复制
# 构造支付宝支付链接地址
alipay = AliPay(
    appid="", # 开发者应用APPID
    app_notify_url=None,  # 默认回调url
    app_private_key_path="", # 网站的私钥文件路径
    alipay_public_key_path="",  # 支付宝的公钥文件路径,验证支付宝回传消息使用,不是你自己的公钥,
    sign_type="RSA2",  # 签名算法,RSA 或者 RSA2
    debug=False  # 默认False,是否使用沙箱环境
)
# 组织支付参数
# 电脑网站支付,需要跳转到https://openapi.alipaydev.com/gateway.do?   order_string
total_pay = order.total_amount # Decimal
order_string = alipay.api_alipay_trade_page_pay(
    out_trade_no=order_id, # 商户订单号
    total_amount=str(total_pay),  # 订单总金额
    subject='美多商城%s' % order_id, # 订单标题
    return_url="http://www.meiduo.site:8080/pay_success.html", # 回调地址
)

4.返回支付宝支付网址和参数。

代码语言:javascript复制
alipay_url = settings.ALIPAY_URL   '?'   order_string
return Response({"alipay_url": alipay_url})

2.2保存支付宝支付结果

代码语言:javascript复制
API: PUT /payment/status/?<支付的结果数据>
参数:
    通过请求头,传递jwt token
    通过查询字符串传递支付结果数据
响应:
    {
        "trade_id": "支付交易编号"
    }
2.2.1业务逻辑

1.获取支付结果数据并进行签名验证。

outtradeno商户订单号 total_amount签名字符串 trade_no支付交易号

2.校验订单是否有效。

3.保存支付结果并修改订单支付状态。

4.返回应答。

3.Xadmin

Xadmin是Django的第三方扩展,比Django自带的admin站点使用方便。我们可以使用此管理站点进行网站管理。

3.1安装

通过如下命令安装xadmin的最新版

代码语言:javascript复制
pip install https://github.com/sshwsfc/xadmin/tarball/master

在配置文件中注册如下应用

代码语言:javascript复制
INSTALLED_APPS = [
    ...
    'xadmin',
    'crispy_forms',
    'reversion',
    ...
]

xadmin有建立自己的数据库模型类,需要进行数据库迁移,在数据库中建立依赖的数据表。

代码语言:javascript复制
python manage.py migrate

在总路由中添加xadmin的路由信息

代码语言:javascript复制
import xadmin

urlpatterns = [
    # url(r'^admin/', admin.site.urls),
    url(r'xadmin/', include(xadmin.site.urls)),
    ...
]

3.2使用

1.在 adminx.py文件中注册模型。
代码语言:javascript复制
xadmin.site.register(<模型类>)
2.定义模型Admin管理类直接继承object。
2.1站点全局配置
代码语言:javascript复制
import xadmin
from xadmin import views
from goods import models

class BaseSetting(object):
    """xadmin的基本配置"""
    enable_themes = True  # 开启主题切换功能
    use_bootswatch = True

xadmin.site.register(views.BaseAdminView, BaseSetting)

class GlobalSettings(object):
    """xadmin的全局配置"""
    site_title = "闫氏商城运营管理系统"  # 设置站点标题
    site_footer = "闫氏集团"  # 设置站点的页脚
    menu_style = "accordion"  # 设置菜单折叠

xadmin.site.register(views.CommAdminView, GlobalSettings)
2.2站点Model管理

xadmin可以使用的页面样式控制基本与Django原生的admin一致。

list_display 控制列表展示的字段

search_fields 控制可以通过搜索框搜索的字段名称,xadmin使用的是模糊查询

list_filter 可以进行过滤操作的列

ordering 默认排序的字段

readonly_fields 在编辑页面的只读字段

exclude 在编辑页面隐藏的字段

list_editable 在列表页可以快速直接编辑的字段

showdetailfileds 在列表页提供快速显示详情信息

refresh_times 指定列表页的定时刷新

list_export 控制列表页导出数据的可选格式

data_charts 控制显示图标的样式

model_icon 控制菜单的图标

model_icon

代码语言:javascript复制
class SKUAdmin(object):
    model_icon = 'fa fa-gift'

xadmin.site.register(models.SKU, SKUAdmin)

list_display

代码语言:javascript复制
list_display = ['id', 'name', 'price', 'stock', 'sales', 'comments']

search_fields

代码语言:javascript复制
search_fields = ['id','name']

list_filter

代码语言:javascript复制
list_filter = ['category']

list_editable

代码语言:javascript复制
list_editable = ['price', 'stock']

showdetailfields

代码语言:javascript复制
show_detail_fields = ['name']

list_export 注意,导出到xls(excel) 需要安装xlwt扩展

代码语言:javascript复制
list_export = ['xls', 'csv', 'xml']

refresh_times

代码语言:javascript复制
class OrderAdmin(object):
    list_display = ['order_id', 'create_time', 'total_amount', 'pay_method', 'status']
    refresh_times = [3, 5]  # 可选以支持按多长时间(秒)刷新页面

data_charts title 控制图标名称 x-field 控制x轴字段 y-field 控制y轴字段,可以是多个值 order 控制默认排序

代码语言:javascript复制
data_charts = {
        "order_amount": {'title': '订单金额', "x-field": "create_time", "y-field": ('total_amount',),
                       "order": ('create_time',)},
        "order_count": {'title': '订单量', "x-field": "create_time", "y-field": ('total_count',),
                       "order": ('create_time',)},
    }

readonly_fields

代码语言:javascript复制
class SKUAdmin(object):
    ...
    readonly_fields = ['sales', 'comments']
3.savemodels和deletemodel。

在Django的原生admin站点中,如果想要在站点保存或删除数据时,补充自定义行为,可以重写如下方法:

save_model(self,request,obj,form,change)

delete_model(self,request,obj)

而在xadmin中,需要重写如下方法:

save_models(self)

delete_model(self)

在方法中,如果需要用到当前处理的模型类对象,需要通过 self.obj来获取,如

代码语言:javascript复制
class SKUSpecificationAdmin(object):
    def save_models(self):
        # 保存数据对象
        obj = self.new_obj
        obj.save()

        # 补充自定义行为
        from celery_tasks.html.tasks import generate_static_sku_detail_html
        generate_static_sku_detail_html.delay(obj.sku.id)

    def delete_model(self):
        # 删除数据对象
        obj = self.obj
        sku_id = obj.sku.id
        obj.delete()

        # 补充自定义行为
        from celery_tasks.html.tasks import generate_static_sku_detail_html
        generate_static_sku_detail_html.delay(sku_id)
4.用户管理设置需要先unregister再register。

xadmin会自动为admin站点添加用户User的管理配置

xadmin使用xadmin.plugins.auth.UserAdmin来配置

如果需要自定义User配置的话,需要先unregister(User),再添加自己的User配置并注册

代码语言:javascript复制
import xadmin
# Register your models here.

from users.models import User
from xadmin.plugins import auth


class UserAdmin(auth.UserAdmin):
    list_display = ['id', 'username', 'mobile', 'email', 'date_joined']
    readonly_fields = ['last_login', 'date_joined']
    search_fields = ('username', 'first_name', 'last_name', 'email', 'mobile')
    style_fields = {'user_permissions': 'm2m_transfer', 'groups': 'm2m_transfer'}

    def get_model_form(self, **kwargs):
        if self.org_obj is None:
            self.fields = ['username', 'mobile', 'is_staff']

        return super().get_model_form(**kwargs)


xadmin.site.unregister(User)
xadmin.site.register(User, UserAdmin)
5.主题切换,站点标题,页面底部标题,菜单折叠。
代码语言:javascript复制
enable_themes = True  # 开启主题切换功能
site_title = "闫氏商城运营管理系统"  # 设置站点标题
site_footer = "闫氏集团"  # 设置站点的页脚
menu_style = "accordion"  # 设置菜单折叠

4.Django用户权限控制

用户权限控制:控制一个用户能够对哪些数据表进行哪些操作(增删改查)。

在产品运营平台中,是需要对用户进行权限控制的。Django实现了用户权限的控制。

1.消费者用户与公司内部运营用户使用一个用户数据库来存储。

2.通过is_staff 来区分是运营用户还是消费者用户。

3.对于运营用户通过is_superuser 来区分是运营平台的管理员还是运营平台的普通用户

4.对于运营平台的普通用户,通过权限、组和组外权限来控制这个用户在平台上可以操作的数据。

5.对于权限,Django会为每个数据库表提供增、删、改、查四种权限。

6.用户最终的权限为 组权限 用户特有权限。

5.部署

开发阶段

服务器

作用

使用

域名

静态文件服务器

提供静态文件

live-server

www.meiduo.site

后端API服务器

提供后端API接口

python manage.py runserver

api.meiduo.site

部署阶段

服务器

作用

使用

域名

静态文件服务器

提供静态文件

Nginx

www.meiduo.site

后端API服务器

提供后端API接口

uwsgi

api.meiduo.site

uwsgi是遵循WSGI的web服务器

5.1.静态文件

当Django运行在生产模式时,将不再提供静态文件的支持,需要将静态文件交给静态文件服务器。

我们先收集所有静态文件。项目中的静态文件除了我们使用的frontendpc中之外,django本身还有自己的静态文件,如果rest_framework、xadmin、admin、ckeditor等。我们需要收集这些静态文件,集中一起放到静态文件服务器中。

我们要将收集的静态文件放到frontendpc目录下的static目录中,所以先创建目录static。

Django提供了收集静态文件的方法。先在配置文件中配置收集之后存放的目录

代码语言:javascript复制
STATIC_ROOT = os.path.join(os.path.dirname(os.path.dirname(BASE_DIR)), 'front_end_pc/static')

然后执行收集命令

代码语言:javascript复制
python manage.py collectstatic

我们使用Nginx服务器作为静态文件服务器

打开Nginx的配置文件

代码语言:javascript复制
sudo vim /usr/local/nginx/conf/nginx.conf

在server部分中配置

代码语言:javascript复制
server {
        listen       80;
        server_name  www.meiduo.site;

        location / {
             root   /home/python/Desktop/front_end_pc;
             index  index.html index.htm;
         }

        # 余下省略
}

重启Nginx服务器

代码语言:javascript复制
sudo /usr/local/nginx/sbin/nginx -s reload

首次启动nginx服务器

代码语言:javascript复制
sudo /usr/local/nginx/sbin/nginx

停止nginx服务器

代码语言:javascript复制
sudo /usr/local/nginx/sbin/nginx -s stop

5.2.动态接口

在项目中复制开发配置文件dev.py 到生产配置prod.py

修改配置文件prod.py中

代码语言:javascript复制
DEBUG = True
ALLOWED_HOSTS = [...,  'www.meiduo.site']  # 添加www.meiduo.site
CORS_ORIGIN_WHITELIST = (
    '127.0.0.1:8080',
    'localhost:8080',
    'www.meiduo.site:8080',
    'www.meiduo.site',  # 添加
)

修改wsgi.py文件

代码语言:javascript复制
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "Ethanyan_mall.settings.prod")

django的程序通常使用uwsgi服务器来运行

安装uwsgi

代码语言:javascript复制
pip install uwsgi

在项目目录/Ethanyan_mall下创建uwsgi配置文件 uwsgi.ini

代码语言:javascript复制
[uwsgi]
#使用nginx连接时使用,Django程序所在服务器地址
socket=127.0.0.1:8001
#直接做web服务器使用,Django程序所在服务器地址
#http=127.0.0.1:8001
#项目目录
chdir=/Users/delron/Desktop/E-commerce-sites/Ethanyan_mall
#项目中wsgi.py文件的目录,相对于项目目录
wsgi-file=Ethanyan_mall/wsgi.py
# 进程数
processes=4
# 线程数
threads=2
# uwsgi服务器的角色
master=True
# 存放进程编号的文件
pidfile=uwsgi.pid
# 日志文件,因为uwsgi可以脱离终端在后台运行,日志看不见。我们以前的runserver是依赖终端的
daemonize=uwsgi.log
# 指定依赖的虚拟环境
virtualenv=/Users/smart/.virtualenvs/djagno_py3

启动uwsgi服务器

代码语言:javascript复制
uwsgi --ini uwsgi.ini

注意如果想要停止服务器,除了可以使用kill命令之外,还可以通过

代码语言:javascript复制
uwsgi --stop uwsgi.pid

修改Nginx配置文件,让Nginx接收到请求后转发给uwsgi服务器

代码语言:javascript复制
upstream meiduo {
    server 10.211.55.2:8001;  # 此处为uwsgi运行的ip地址和端口号
    # 如果有多台服务器,可以在此处继续添加服务器地址
}

#gzip  on;
server {
    listen  8000;
    server_name api.meiduo.site;

    location / {
        include uwsgi_params;
        uwsgi_pass meiduo;
    }

}

server {
    listen       80;
    server_name  www.meiduo.site;

    #charset koi8-r;
    #access_log  logs/host.access.log  main;
    location /xadmin {
        include uwsgi_params;
        uwsgi_pass meiduo;
    }

    location /ckeditor {
        include uwsgi_params;
        uwsgi_pass meiduo;
    }

    location / {
        root   /home/python/Desktop/front_end_pc;
        index  index.html index.htm;
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   html;
    }
}

重启nginx

代码语言:javascript复制
sudo /usr/local/nginx/sbin/nginx -s reload

优质文章推荐:

公众号使用指南

redis操作命令总结

前端中那些让你头疼的英文单词

Flask框架重点知识总结回顾

项目重点知识点详解

难点理解&面试题问答

flask框架中的一些常见问题

团队开发注意事项

浅谈密码加密

Django框架中的英文单词

Django中数据库的相关操作

DRF框架中的英文单词

重点内容回顾-DRF

Django相关知识点回顾

0 人点赞