Gerapy项目的结构:Vue+Django独立开发电商项目

.
├── client/  # 前端(客户端),vue项目。该文件夹不包含在上线项目中。
│   ├── build/
│   ├── server/
│   ├── src/  # 前端源码
│   │   ├── App.vue
│   │   ├── components/  # 组件
│   │   ├── favicon.ico
│   │   ├── index.html  # 入口html文件
│   │   ├── main.js
│   │   ├── pages/
│   ├── static/
│   ├── theme/
│   └── twistd.pid
├── cmd/
├── downloadermiddlewares/  # Gerapy内置的Scrapy下载器中间件
├── __init__.py
├── pipelines/  # Gerapy内置的Scrapy pipeline
├── server/  # Django项目
│   ├── core  # Django应用(app)
│   │   ├── admin.py
│   │   ├── apps.py
│   │   ├── build.py
│   │   ├── config.py
│   │   ├── encoder.py
│   │   ├── __init__.py
│   │   ├── middlewares.py
│   │   ├── migrations/
│   │   ├── models.py
│   │   ├── parser.py
│   │   ├── response.py
│   │   ├── scheduler.py
│   │   ├── templates  # 前端模板文件;从vue项目中构建来的前端文件
│   │   │   ├── favicon.ico
│   │   │   ├── index.html
│   │   │   └── static
│   │   │       ├── css
│   │   │       ├── fonts
│   │   │       ├── images
│   │   │       └── js
│   │   ├── tests.py
│   │   ├── time.py
│   │   ├── urls.py
│   │   ├── utils.py
│   │   └── views.py
│   ├── __init__.py
│   ├── manage.py
│   └── server
│       ├── __init__.py
│       ├── settings.py
│       ├── urls.py
│       └── wsgi.py
├── spiders/
├── templates/  # Gerapy内置的爬虫模板
└── VERSION

观察以上结构,最重要的两个部分,一个是client文件夹,一个是server文件夹。前者是vue单页面应用项目,它提供一个入口页面,页面中有一系列取数和数据组织逻辑。后者是一个Django项目,它管理数据库和api行为。

下面是server/core/urls.py中的部分代码:

# in server/core/urls.pyurlpatterns = [
    url(r'^$', views.index, name='index'),
    url(r'^api/index/status/$', views.index_status, name='index_status'),
    url(r'^api/client/$', views.client_index, name='client_index'),
    url(r'^api/client/create', views.client_create, name='client_create'),
    url(r'^api/client/(\d+)/$', views.client_info, name='client_info'),
    url(r'^api/client/(\d+)/status', views.client_status, name='client_status'),
    ... ...]

可以看出来,它除了一个url指向返回入口页面的视图,其它url都指向api视图。

以下是server/core/views.py的部分代码:

# in server/core/views.py
def index(request):
    """
    render index page
    :param request: request object
    :return: page
    """
    return render(request, 'index.html')

... ...

def client_info(request, client_id):
    """
    get client info
    :param request: request object
    :param id: client id
    :return: json
    """
    if request.method == 'GET':
        return JsonResponse(model_to_dict(Client.objects.get(id=client_id)))
... ...

可以看到,index视图返回一个渲染的入口页面的响应;client_info视图返回一个JSONResponse响应:Client.objects.get(id=client_id)),从Client模型对应的表中取出特定的记录;model_to_dict(Client.objects.get(id=client_id)),将记录(模型实例)转换为字典dict;JsonResponse(model_to_dict(Client.objects.get(id=client_id))),返回一个JSONResponse响应。JSONResponse响应决定了响应头的content-type是application/json。

Vue是View的法语说法,也就是说,Vue自打出生以来,就是为View而生。选择vue.js进行前端渲染,就放弃了Django内置的模型引擎。从功能模块上来说,Django将利用其强大的ORM功能,继续负责对Model的管理和操作;Django的view,将负责1)返回vue的入口文件,2)成为api-view,负责对数据的序列化与反序列化,返回JSON(等能被机器取数的)响应;Django的URLconf,将负责后端路由,指向vue入口文件和api。vue负责前端视图逻辑和前端模型,以及前端路由。