├── .gitignore ├── README.md ├── RESTfulApi ├── README.md ├── __init__.py ├── app.py ├── common │ ├── __init__.py │ ├── authority.py │ ├── fields.py │ ├── parsers.py │ └── util.py ├── handler │ ├── __init__.py │ ├── account.py │ ├── book.py │ ├── book_type.py │ ├── reference.py │ ├── sales_record.py │ ├── session.py │ └── vip.py ├── models │ ├── __init__.py │ ├── init.py │ ├── shop_db.py │ └── token_db.py ├── resources │ ├── __init__.py │ ├── account.py │ ├── book.py │ ├── book_type.py │ ├── reference.py │ ├── sales_record.py │ ├── session.py │ └── vip.py └── utils │ ├── __init__.py │ ├── authority.py │ ├── fields │ ├── __init__.py │ ├── account.py │ ├── book.py │ ├── book_type.py │ ├── common.py │ ├── sales_record.py │ └── vip.py │ └── parsers │ ├── __init__.py │ ├── account.py │ ├── book.py │ ├── book_type.py │ ├── common.py │ ├── sales_record.py │ ├── session.py │ └── vip.py ├── config ├── __init__.py └── default.py └── run.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | 27 | # PyInstaller 28 | # Usually these files are written by a python script from a template 29 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 30 | *.manifest 31 | *.spec 32 | 33 | # Installer logs 34 | pip-log.txt 35 | pip-delete-this-directory.txt 36 | 37 | # Unit test / coverage reports 38 | htmlcov/ 39 | .tox/ 40 | .coverage 41 | .coverage.* 42 | .cache 43 | nosetests.xml 44 | coverage.xml 45 | *,cover 46 | .hypothesis/ 47 | 48 | # Translations 49 | *.mo 50 | *.pot 51 | 52 | # Django stuff: 53 | *.log 54 | 55 | # Sphinx documentation 56 | docs/_build/ 57 | 58 | # PyBuilder 59 | target/ 60 | 61 | #Ipython Notebook 62 | .ipynb_checkpoints 63 | 64 | # PyCharm 65 | .idea/ 66 | 67 | # others 68 | *~ 69 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RESTfulAPI 2 | flask-restful 实例。 3 | 4 | 以mongodb作为数据库。 5 | 6 | -------------------------------------------------------------------------------- /RESTfulApi/README.md: -------------------------------------------------------------------------------- 1 | # RESTful服务器:http://host:port/api 2 | 3 | ## 所有用户角色及其权限: 4 | 5 | `root` 6 | ``` 7 | 除了最自己删、改、查。拥有一切权限(只要存在该功能)。 8 | ``` 9 | 10 | `admin` 11 | ``` 12 | 除了对于root用户的一切操作,对同等级角色的删除与更改。拥有一切权限,具体如下: 13 | 用户: 14 | 1、获取非root用户列表(含过滤)。 15 | 2、创建用户(可创建admin/stuff两种角色的用户)。 16 | 3、删除stuff用户。 17 | 4、更新stuff和自己的资料。 18 | 5、查看非root用户的详情信息。 19 | 图书: 20 | 1、获取图书列表(含过滤)。 21 | 2、增加图书。 22 | 3、下架图书。 23 | 4、更新图书信息。 24 | 5、查看图书详情信息。 25 | 书种: 26 | 1、获取书种(含过滤)。 27 | 2、增加书种。 28 | 3、删除书种(前提是无图书引用该书种)。 29 | 索引: 30 | 1、查看引用某书种的所有书籍。 31 | 2、解除所有书籍对某书种的引用(之后可以删除)。 32 | 3、查看与某用户相关的所有销售记录。 33 | 4、查看与某图书有关的所有销售记录。 34 | 5、查看与某VIP有关的所有销售记录。 35 | 销售记录: 36 | 1、获取所有销售记录。 37 | 2、增加销售记录(即售书)。 38 | VIP: 39 | 1、获取VIP列表(含过滤)。 40 | 2、创建VIP。 41 | 3、删除某VIP。 42 | ``` 43 | 44 | `stuff` 45 | ``` 46 | 普通员工的权限,具体如下: 47 | 用户: 48 | 1、获取角色为stuff用户列表(含过滤)。 49 | 2、更新自己的资料(包括密码)。 50 | 5、查看角色为stuff用户的详情信息。 51 | 图书: 52 | 1、获取图书列表(含过滤)。 53 | 2、查看图书详情信息。 54 | 书种: 55 | 1、获取书种(含过滤)。 56 | 2、增加书种。 57 | 索引: 58 | 1、查看引用某书种的所有书籍。 59 | 2、查看与某用户相关的所有销售记录。 60 | 3、查看与某图书有关的所有销售记录。 61 | 4、查看与某VIP有关的所有销售记录。 62 | 销售记录: 63 | 1、增加销售记录(即售书)。 64 | VIP: 65 | 1、获取VIP列表(含过滤)。 66 | 2、创建VIP。 67 | 4、删除某VIP。 68 | ``` 69 | 70 | ## 所有接口地址及其简略: 71 | 72 | `/session` *[登录、注销](#session)* 73 | 74 | `/accounts` *[获取用户、新增用户](#accounts)* 75 | `/accounts/` *[用户删、改、查](#accounts-1)* 76 | 77 | `/books` *[获取图书、新增图书](#books)* 78 | `/books/` *[图书删、改、查](#books-1)* 79 | 80 | `/vips` *[获取VIP、新增VIP](#vips)* 81 | `/vips/` *[VIP删除](#vips-1)* 82 | 83 | `/types` *[获取书种、新增书种](#types)* 84 | `/types/` *[书种删除](#types-1)* 85 | 86 | `/sales_records` *[获取销售记录、添加销售记录](#sales_records)* 87 | 88 | `/references/book2type/` *[解除图书对书种的索引、获取某书种的所有图书](#book2type)* 89 | `/references/record2account/` *[获取某用户的售书记录](#record2account)* 90 | `/references/record2book/` *[获取某图书的销售记录](#record2book)* 91 | `/references/record2vip/` *[获取某VIP的购买记录](#record2vip)* 92 | 93 | 94 | ## 详情说明 95 | 写在前面 96 | 97 | 1、越权请求会得到如下统一response 98 | { 99 | "message": "You don't have the permission to access the requested resource. It is either read-protected or not readable by the server." 100 | } 101 | 102 | 2、除了get方法,其他方法的请求结果都有'success'字段。可以根据该字段判断请求是否成功,再根据其余的message或者token/id获得其他信息。 103 | 104 | 3、如果form-data缺少某必要字段,会出现如下格式提示(下面是未填写密码) 105 | { 106 | "message": { 107 | "password": "This is password" 108 | } 109 | } 110 | 111 | ### /session 登录、注销 112 | 113 | #### post: 登录 114 | ##### form-data 115 | ``` 116 | username: root 117 | password: password 118 | ``` 119 | ##### response 120 | ``` 121 | { 122 | "id": "56ebb6ee159ce145f818193b", 123 | "message": "No message", 124 | "success": 1, 125 | "token": "0wnCLKVPFG5x2eW8" 126 | } 127 | ``` 128 | 129 | #### delete: 登出 130 | ##### headers 131 | ``` 132 | token: 0wnCLKVPFG5x2eW8 133 | ``` 134 | 注:如无特别说明,以下所有请求除了要求的form-data或param以外,还要必须提供key为\'token'值为\'XXXX'的header键值对。根据RESTful的等幂性,此字段提供身份验证。 135 | ##### response 136 | ``` 137 | { 138 | "message": "No message", 139 | "success": 1 140 | } 141 | ``` 142 | 143 | ### /accounts 获取用户、新增用户 144 | 145 | #### post 新增用户 146 | ##### form-data 147 | ``` 148 | username: skyduy 149 | nickname: YuJun 150 | password: secret 151 | confirm: secret 152 | role: 1 (其中0为员工,1为超级管理员) 153 | ``` 154 | ##### response(post /accounts) 155 | ``` 156 | { 157 | "id": "56ed05cb159ce12c74a634f5", 158 | "message": "No message", 159 | "success": 1, 160 | "token": "kdqdxwJowiraNP3D" 161 | } 162 | ``` 163 | 164 | #### get 获取所有用户 165 | ##### param(可选,此时表示过滤:nickname或者username),当有param时: 166 | ``` 167 | /accounts?username=skyduy&&nickname=YuJun 168 | ``` 169 | ##### response(get /accounts) 170 | ``` 171 | { 172 | "accounts": [ 173 | { 174 | "id": "56ed05cb159ce12c74a634f5", 175 | "nickname": "YuJun", 176 | "role": "stuff" 177 | }, 178 | { 179 | "id": "56ed073d159ce12b0c442de8", 180 | "nickname": "张三", 181 | "role": "stuff" 182 | }, 183 | { 184 | "id": "56ed0805159ce100546b669e", 185 | "nickname": "张三", 186 | "role": "admin" 187 | } 188 | ] 189 | } 190 | ``` 191 | ### /accounts/account_id:str 用户删、改、查 192 | 193 | #### get 查看用户详情信息 194 | ##### response(get /accounts/56ed0805159ce100546b669e) 195 | ``` 196 | { 197 | "created": "Sat, 19 Mar 2016 16:04:21 -0000", 198 | "description": "", 199 | "id": "56ed0805159ce100546b669e", 200 | "nickname": "张三", 201 | "role": "admin", 202 | "username": "yangjing1" 203 | } 204 | ``` 205 | 206 | 207 | #### put 查看用户详情信息 208 | ##### form-data 209 | ``` 210 | nickname: '员工of张三' 211 | new_password: 2 (填写该框表示要修改密码,可选) 212 | confirm: 2 (填写该框表示要修改密码,可选) 213 | old_password: 1 (填写该框表示要修改密码,可选) 214 | des: 'new_des' (可选) 215 | ``` 216 | 217 | ##### response(put /accounts/56ed073d159ce12b0c442de8) 218 | ``` 219 | { 220 | "id": "56ed073d159ce12b0c442de8", 221 | "message": "user's profile update successfully!", 222 | "success": 1 223 | } 224 | ``` 225 | 226 | 227 | #### delete 删除用户 228 | ##### response(delete /accounts/56ed073d159ce12b0c442de8) 229 | ``` 230 | { 231 | "message": "No message", 232 | "success": 1 233 | } 234 | ``` 235 | 236 | ### /books 获取图书、新增图书 237 | 238 | #### post 获取图书列表(含过滤) 239 | ##### form-data 240 | ``` 241 | name: 海贼王 242 | count: 100 243 | price: 20.5 244 | des: 可为空 245 | ``` 246 | ##### response(post /books) 247 | ``` 248 | { 249 | "id": "56ed0c06159ce147ec4131dc", 250 | "message": "No message", 251 | "success": 1 252 | } 253 | ``` 254 | #### get 获取图书列表(含过滤) 255 | ##### response(get /books) 256 | ``` 257 | { 258 | "books": [ 259 | { 260 | "id": "56ed0c06159ce147ec4131dc", 261 | "name": "海贼王", 262 | "price": 20.5, 263 | "sales": 0 264 | }, 265 | { 266 | "id": "56ed0c66159ce147ec4131dd", 267 | "name": "金瓶梅", 268 | "price": 58, 269 | "sales": 0 270 | } 271 | ] 272 | } 273 | ``` 274 | ### /books/book_id:str 图书删、改、查 275 | 276 | #### get 查看图书详情信息 277 | ##### response(get /books/56ed0c66159ce147ec4131dd) 278 | ``` 279 | { 280 | "description": "张三喜欢的故事", 281 | "id": "56ed0c66159ce147ec4131dd", 282 | "name": "金瓶梅", 283 | "price": 58, 284 | "remaining": 100, 285 | "sales": 0, 286 | "type": [] 287 | } 288 | ``` 289 | #### put 更新图书信息 290 | ##### form-data 291 | ``` 292 | delta: -20 293 | price: 100 294 | des = '张三超级喜欢的故事,被他买掉了20本,因此升价为100元'(可选) 295 | type_id = 'type_id1'(根据种类id添加一个种类,若不存在id忽略) 296 | type_id = 'type_id2'(表示一次性添加两个种类) 297 | ``` 298 | ##### response(put /books/56ed0c66159ce147ec4131dd) 299 | ``` 300 | { 301 | "id": "56ed0c66159ce147ec4131dd", 302 | "message": "No message", 303 | "success": 1 304 | } 305 | ``` 306 | #### delete 下架某图书 307 | ##### response(delete /books/56ed0c66159ce147ec4131dd) 308 | ``` 309 | { 310 | "message": "No message", 311 | "success": 1 312 | } 313 | ``` 314 | 315 | ### /vips 获取VIP、新增VIP 316 | 317 | #### post 新增VIP 318 | ##### form-data 319 | ``` 320 | username: vip1 321 | nickname: 我是大V 322 | phone: 1233457 (可选最长15) 323 | ``` 324 | ##### response (post /vips) 325 | ``` 326 | { 327 | "id": "56ed0ec2159ce1266c62acae", 328 | "message": "No message", 329 | "success": 1 330 | } 331 | ``` 332 | #### get 获取VIP列表(含过滤) 333 | ``` 334 | { 335 | "vips": [ 336 | { 337 | "id": "56ed0ec2159ce1266c62acae", 338 | "nickname": "我是大V", 339 | "phone": "1233457", 340 | "username": "vip1" 341 | }, 342 | { 343 | "id": "56ed0ed7159ce1266c62acaf", 344 | "nickname": "我也是大V", 345 | "phone": "12345678901", 346 | "username": "vip2" 347 | } 348 | ] 349 | } 350 | ``` 351 | 352 | ### /vips/vip_id:str VIP删除。 353 | 354 | #### delete 查看某VIP详情信息 355 | ##### response (delete /vips/56ed0ec2159ce1266c62acae) 356 | ``` 357 | { 358 | "message": "No message", 359 | "success": 1 360 | } 361 | ``` 362 | 363 | ### /types 获取书种、新增书种。 364 | 365 | #### post 新增书种 366 | ##### form-data 367 | ``` 368 | name: 动漫 369 | ``` 370 | ##### response (post /types) 371 | ``` 372 | { 373 | "id": "56ed0f92159ce1266c62acb0", 374 | "message": "No message", 375 | "success": 1 376 | } 377 | ``` 378 | 379 | #### get 获取书种列表(含过滤) 380 | ##### response(get /types) 381 | ``` 382 | { 383 | "books_types": [ 384 | { 385 | "id": "56ed0f92159ce1266c62acb0", 386 | "name": "动漫" 387 | }, 388 | { 389 | "id": "56ed0f9d159ce1266c62acb1", 390 | "name": "热血" 391 | }, 392 | { 393 | "id": "56ed0fa1159ce1266c62acb2", 394 | "name": "后宫" 395 | } 396 | ] 397 | } 398 | ``` 399 | 400 | ### /types/book_type_id:str 书种删除。 401 | 402 | #### delete 查看某书籍详情信息 403 | #### response(delete /types/56ed0f9d159ce1266c62acb1) 404 | ``` 405 | { 406 | "message": "No message", 407 | "success": 1 408 | } 409 | ``` 410 | 411 | ### /sales_records 获取销售记录、添加销售记录 412 | #### post 销售图书 413 | ##### form-data 414 | ``` 415 | count: 1 416 | seller_id: 56ed05cb159ce12c74a634f5 417 | book_id: 56ed0c06159ce147ec4131dc 418 | purchaser_id:56ed0ed7159ce1266c62acaf (可选) 419 | ``` 420 | ##### response (post /sales_records) 421 | ``` 422 | { 423 | "id": "56ed10f1159ce1266c62acb3", 424 | "message": "No message", 425 | "success": 1 426 | } 427 | ``` 428 | 429 | #### get 获取销售记录列表 430 | ##### response (get /sales_records) 431 | ``` 432 | { 433 | "sales_records": [ 434 | { 435 | "book": { 436 | "id": "56ed0c06159ce147ec4131dc", 437 | "name": "海贼王", 438 | "price": 20.5, 439 | "sales": 3 440 | }, 441 | "count": 1, 442 | "id": "56ed10f1159ce1266c62acb3", 443 | "price": 16.400000000000002, 444 | "purchaser": { 445 | "id": "56ed0ed7159ce1266c62acaf", 446 | "nickname": "我也是大V", 447 | "phone": "12345678901", 448 | "username": "vip2" 449 | }, 450 | "sale_time": "Sat, 19 Mar 2016 16:42:25 -0000", 451 | "seller": { 452 | "id": "56ed05cb159ce12c74a634f5", 453 | "nickname": "YuJun", 454 | "role": "stuff" 455 | } 456 | }, 457 | { 458 | "book": { 459 | "id": "56ed0c06159ce147ec4131dc", 460 | "name": "海贼王", 461 | "price": 20.5, 462 | "sales": 3 463 | }, 464 | "count": 2, 465 | "id": "56ed11b2159ce101a8f49bdb", 466 | "price": 20.5, 467 | "purchaser": { 468 | "id": null, 469 | "nickname": null, 470 | "phone": null, 471 | "username": null 472 | }, 473 | "sale_time": "Sat, 19 Mar 2016 16:45:38 -0000", 474 | "seller": { 475 | "id": "56ed05cb159ce12c74a634f5", 476 | "nickname": "YuJun", 477 | "role": "stuff" 478 | } 479 | } 480 | ] 481 | } 482 | ``` 483 | 484 | ### /references/book2type/book_type_id:str 解除图书对书种的索引、获取某书种的所有图书。 485 | 486 | #### get 获取某书种所有图书 487 | ##### response (get /references/book2type/56ed140a159ce139bca7ad1a) 488 | ``` 489 | { 490 | "books": [ 491 | { 492 | "id": "56ed0c06159ce147ec4131dc", 493 | "name": "海贼王", 494 | "price": 20, 495 | "sales": 3 496 | } 497 | ] 498 | } 499 | ``` 500 | #### delete 解除图书对书种的索引 501 | ##### response (delete /references/book2type/56ed140a159ce139bca7ad1a) 502 | ``` 503 | { 504 | "message": "No message", 505 | "success": 1 506 | } 507 | ``` 508 | 509 | ### /references/record2account/account_id:str 获取某用户的售书记录。 510 | 511 | #### get 获取某用户售书记录 512 | ##### response (get /references/record2account/56ed05cb159ce12c74a634f5) 513 | ``` 514 | { 515 | "sales_records": [ 516 | { 517 | "book": { 518 | "id": "56ed0c06159ce147ec4131dc", 519 | "name": "海贼王", 520 | "price": 20, 521 | "sales": 3 522 | }, 523 | "count": 1, 524 | "id": "56ed10f1159ce1266c62acb3", 525 | "price": 16.400000000000002, 526 | "purchaser": { 527 | "id": "56ed0ed7159ce1266c62acaf", 528 | "nickname": "我也是大V", 529 | "phone": "12345678901", 530 | "username": "vip2" 531 | }, 532 | "sale_time": "Sat, 19 Mar 2016 16:42:25 -0000", 533 | "seller": { 534 | "id": "56ed05cb159ce12c74a634f5", 535 | "nickname": "YuJun", 536 | "role": "stuff" 537 | } 538 | }, 539 | { 540 | "book": { 541 | "id": "56ed0c06159ce147ec4131dc", 542 | "name": "海贼王", 543 | "price": 20, 544 | "sales": 3 545 | }, 546 | "count": 2, 547 | "id": "56ed11b2159ce101a8f49bdb", 548 | "price": 20.5, 549 | "purchaser": { 550 | "id": null, 551 | "nickname": null, 552 | "phone": null, 553 | "username": null 554 | }, 555 | "sale_time": "Sat, 19 Mar 2016 16:45:38 -0000", 556 | "seller": { 557 | "id": "56ed05cb159ce12c74a634f5", 558 | "nickname": "YuJun", 559 | "role": "stuff" 560 | } 561 | } 562 | ] 563 | } 564 | ``` 565 | 566 | ### /references/record2book/book_id:str 获取某图书的销售记录。 567 | 568 | #### get 获取某图书的销售记录 569 | ##### response (get /references/record2book/56ed0c06159ce147ec4131dc) 570 | ``` 571 | { 572 | "sales_records": [ 573 | { 574 | "book": { 575 | "id": "56ed0c06159ce147ec4131dc", 576 | "name": "海贼王", 577 | "price": 20, 578 | "sales": 3 579 | }, 580 | "count": 1, 581 | "id": "56ed10f1159ce1266c62acb3", 582 | "price": 16.400000000000002, 583 | "purchaser": { 584 | "id": "56ed0ed7159ce1266c62acaf", 585 | "nickname": "我也是大V", 586 | "phone": "12345678901", 587 | "username": "vip2" 588 | }, 589 | "sale_time": "Sat, 19 Mar 2016 16:42:25 -0000", 590 | "seller": { 591 | "id": "56ed05cb159ce12c74a634f5", 592 | "nickname": "YuJun", 593 | "role": "stuff" 594 | } 595 | }, 596 | { 597 | "book": { 598 | "id": "56ed0c06159ce147ec4131dc", 599 | "name": "海贼王", 600 | "price": 20, 601 | "sales": 3 602 | }, 603 | "count": 2, 604 | "id": "56ed11b2159ce101a8f49bdb", 605 | "price": 20.5, 606 | "purchaser": { 607 | "id": null, 608 | "nickname": null, 609 | "phone": null, 610 | "username": null 611 | }, 612 | "sale_time": "Sat, 19 Mar 2016 16:45:38 -0000", 613 | "seller": { 614 | "id": "56ed05cb159ce12c74a634f5", 615 | "nickname": "YuJun", 616 | "role": "stuff" 617 | } 618 | } 619 | ] 620 | } 621 | ``` 622 | 623 | ### /references/record2vip/vip_id:str 获取某VIP的购买记录。 624 | 625 | #### get 获取某VIP的购买记录 626 | ##### response(get /references/record2vip/56ed0ed7159ce1266c62acaf) 627 | ``` 628 | { 629 | "sales_records": [ 630 | { 631 | "book": { 632 | "id": "56ed0c06159ce147ec4131dc", 633 | "name": "海贼王", 634 | "price": 20, 635 | "sales": 3 636 | }, 637 | "count": 1, 638 | "id": "56ed10f1159ce1266c62acb3", 639 | "price": 16.400000000000002, 640 | "purchaser": { 641 | "id": "56ed0ed7159ce1266c62acaf", 642 | "nickname": "我也是大V", 643 | "phone": "12345678901", 644 | "username": "vip2" 645 | }, 646 | "sale_time": "Sat, 19 Mar 2016 16:42:25 -0000", 647 | "seller": { 648 | "id": "56ed05cb159ce12c74a634f5", 649 | "nickname": "YuJun", 650 | "role": "stuff" 651 | } 652 | } 653 | ] 654 | } 655 | ``` 656 | -------------------------------------------------------------------------------- /RESTfulApi/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | """ 5 | File name: __init__.py 6 | Function Des: ... 7 | ~~~~~~~~~~ 8 | 9 | author: Jerry 10 | 11 | """ 12 | 13 | -------------------------------------------------------------------------------- /RESTfulApi/app.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | """ 5 | File name: app.py 6 | Function Des: ... 7 | ~~~~~~~~~~ 8 | 9 | author: Jerry 10 | 11 | """ 12 | 13 | from flask import Blueprint 14 | from flask.ext.restful import Api 15 | 16 | from RESTfulApi.resources.session import Session 17 | 18 | from RESTfulApi.resources.account import Accounts, Account 19 | 20 | from RESTfulApi.resources.book import Books, Book 21 | 22 | from RESTfulApi.resources.vip import Vips, Vip 23 | 24 | from RESTfulApi.resources.book_type import BookTypes, BookType 25 | 26 | from RESTfulApi.resources.sales_record import SalesRecords 27 | 28 | from RESTfulApi.resources.reference import ReferenceBook2Type, ReferenceSaleRecord2Account 29 | from RESTfulApi.resources.reference import ReferenceSaleRecord2Book, ReferenceSale2Vip 30 | 31 | api_bp = Blueprint('api', __name__) 32 | api = Api(api_bp) 33 | 34 | api.add_resource(Session, '/session') 35 | 36 | api.add_resource(Accounts, '/accounts') 37 | api.add_resource(Account, '/accounts/') 38 | 39 | api.add_resource(Books, '/books') 40 | api.add_resource(Book, '/books/') 41 | 42 | api.add_resource(Vips, '/vips') 43 | api.add_resource(Vip, '/vips/') 44 | 45 | api.add_resource(BookTypes, '/types') 46 | api.add_resource(BookType, '/types/') 47 | 48 | api.add_resource(SalesRecords, '/sales_records') 49 | 50 | api.add_resource(ReferenceBook2Type, '/references/book2type/') 51 | api.add_resource(ReferenceSaleRecord2Account, '/references/record2account/') 52 | api.add_resource(ReferenceSaleRecord2Book, '/references/record2book/') 53 | api.add_resource(ReferenceSale2Vip, '/references/record2vip/') 54 | -------------------------------------------------------------------------------- /RESTfulApi/common/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | """ 5 | File name: __init__.py.py 6 | Function Des: ... 7 | ~~~~~~~~~~ 8 | 9 | author: Jerry 10 | 11 | """ 12 | 13 | -------------------------------------------------------------------------------- /RESTfulApi/common/authority.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | """ 5 | File name: authority.py 6 | Function Des: ... 7 | ~~~~~~~~~~ 8 | 9 | author: Jerry 10 | 11 | """ 12 | 13 | from werkzeug import security 14 | 15 | from RESTfulApi.models.token_db import Token 16 | from RESTfulApi.models.shop_db import Account 17 | 18 | 19 | def create_token(length=16): 20 | return security.gen_salt(length) 21 | 22 | 23 | def is_root(token): 24 | token = Token.objects(token=token).first() 25 | if token is None: 26 | return False 27 | account = Account.objects(id=token.user_id).first() 28 | if account is None: 29 | return False 30 | if account.username == 'root': 31 | return True 32 | return False 33 | 34 | 35 | def is_admin(token): 36 | token = Token.objects(token=token).first() 37 | if token is None: 38 | return False 39 | account = Account.objects(id=token.user_id).first() 40 | if account is None: 41 | return False 42 | if account.role == 'stuff': 43 | return False 44 | return True 45 | 46 | 47 | def is_stuff(token): 48 | token = Token.objects(token=token).first() 49 | if token is None: 50 | return False 51 | account = Account.objects(id=token.user_id).first() 52 | if account is None: 53 | return False 54 | return True 55 | 56 | 57 | def is_self(account_id, token): 58 | token = Token.objects(token=token).first() 59 | if token is None: 60 | return False 61 | if account_id != token.user_id: 62 | return False 63 | return True 64 | -------------------------------------------------------------------------------- /RESTfulApi/common/fields.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | """ 5 | File name: fields.py 6 | Function Des: ... 7 | ~~~~~~~~~~ 8 | 9 | author: Jerry 10 | 11 | """ 12 | from flask.ext.restful import fields 13 | 14 | 15 | # ------------ book ------------ 16 | types_fields = { 17 | 'id': fields.String, 18 | 'name': fields.String, 19 | } 20 | 21 | book_fields = { 22 | 'id': fields.String, 23 | 'name': fields.String, 24 | 'price': fields.Float, 25 | 'remaining': fields.Integer, 26 | 'description': fields.String, 27 | 'sales': fields.Integer, 28 | 'type': fields.List(fields.Nested(types_fields)), 29 | } 30 | 31 | books_fields = { 32 | 'books': fields.List(fields.Nested(book_fields)) 33 | } 34 | 35 | # ------------ book type ------------ 36 | book_type_fields = { 37 | 'id': fields.String, 38 | 'name': fields.String, 39 | } 40 | 41 | book_types_fields = { 42 | 'books_types': fields.List(fields.Nested(book_type_fields)) 43 | } 44 | 45 | 46 | # ------------ account ------------ 47 | token_fields = { 48 | 'token': fields.String, 49 | 'message': fields.String, 50 | } 51 | 52 | account_fields = { 53 | 'id': fields.String, 54 | 'username': fields.String, 55 | 'nickname': fields.String, 56 | 'role': fields.String, 57 | 'description': fields.String, 58 | 'created': fields.DateTime, 59 | } 60 | 61 | accounts_fields = { 62 | 'accounts': fields.List(fields.Nested(account_fields)) 63 | } 64 | 65 | 66 | # ------------ vip ------------ 67 | vip_fields = { 68 | 'id': fields.String, 69 | 'username': fields.String, 70 | 'nickname': fields.Float, 71 | 'phone': fields.String, 72 | } 73 | 74 | vips_fields = { 75 | 'vips': fields.List(fields.Nested(vip_fields)) 76 | } 77 | 78 | # ------------ sale_record ------------ 79 | sales_record_fields = { 80 | 'id': fields.String, 81 | 'seller': fields.List(fields.Nested(account_fields)), 82 | 'book': fields.List(fields.Nested(book_fields)), 83 | 'count': fields.Integer, 84 | 'sale_time': fields.DateTime, 85 | 'price': fields.Float, 86 | 'purchaser': fields.List(fields.Nested(vip_fields)), 87 | 'message': fields.String, 88 | } 89 | 90 | sales_records_fields = { 91 | 'sales_records': fields.List(fields.Nested(sales_record_fields)) 92 | } 93 | -------------------------------------------------------------------------------- /RESTfulApi/common/parsers.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | """ 5 | File name: parsers.py 6 | Function Des: ... 7 | ~~~~~~~~~~ 8 | 9 | author: Jerry 10 | 11 | """ 12 | from flask.ext.restful import reqparse 13 | 14 | # ------------ book parser ------------ 15 | book_parser = reqparse.RequestParser() 16 | book_parser.add_argument( 17 | 'name', dest='name', 18 | type=unicode, location='form', 19 | required=True, help='The book\'s name', 20 | ) 21 | 22 | book_parser.add_argument( 23 | 'count', dest='count', 24 | type=int, location='form', 25 | required=True, help='The book\'s count', 26 | ) 27 | 28 | book_parser.add_argument( 29 | 'price', dest='price', 30 | type=float, location='form', 31 | required=True, help='The book\'s price', 32 | ) 33 | 34 | book_parser.add_argument( 35 | 'des', dest='des', 36 | type=str, location='form', 37 | required=False, help='The book\'s description', 38 | ) 39 | 40 | # ------------ book_update parser ------------ 41 | book_update_parser = reqparse.RequestParser() 42 | book_update_parser.add_argument( 43 | 'delta', dest='delta', 44 | type=int, location='form', 45 | required=True, help='The book\'s deviation', 46 | ) 47 | 48 | book_update_parser.add_argument( 49 | 'price', dest='price', 50 | type=float, location='form', 51 | required=True, help='The book\'s new price', 52 | ) 53 | 54 | book_update_parser.add_argument( 55 | 'des', dest='des', 56 | type=str, location='form', 57 | required=False, help='The book\'s new description', 58 | ) 59 | 60 | book_update_parser.add_argument( 61 | 'type_id', dest='types_id', action='append', 62 | type=str, location='form', 63 | required=True, help='The book\'s new list of type id', 64 | ) 65 | 66 | 67 | # ------------ book_type parser ------------ 68 | book_type_parser = reqparse.RequestParser() 69 | book_type_parser.add_argument( 70 | 'name', dest='name', 71 | type=unicode, location='form', 72 | required=True, help='The book_type\'s name', 73 | ) 74 | 75 | 76 | # ------------ login parser ------------ 77 | login_parser = reqparse.RequestParser() 78 | login_parser.add_argument( 79 | 'username', dest='username', 80 | type=str, location='form', 81 | required=True, help='This is username', 82 | ) 83 | 84 | login_parser.add_argument( 85 | 'password', dest='password', 86 | type=str, location='form', 87 | required=True, help='This is password', 88 | ) 89 | 90 | # ------------ logout parser ------------ 91 | token_parser = reqparse.RequestParser() 92 | token_parser.add_argument('token', location='headers', required=True) 93 | 94 | # ------------ register parser ------------ 95 | register_parser = reqparse.RequestParser() 96 | register_parser.add_argument( 97 | 'username', dest='username', 98 | type=str, location='form', 99 | required=True, help='This is username', 100 | ) 101 | 102 | register_parser.add_argument( 103 | 'nickname', dest='nickname', 104 | type=unicode, location='form', 105 | required=True, help='This is nickname', 106 | ) 107 | 108 | register_parser.add_argument( 109 | 'password', dest='password', 110 | type=str, location='form', 111 | required=True, help='This is password', 112 | ) 113 | 114 | register_parser.add_argument( 115 | 'confirm', dest='confirm', 116 | type=str, location='form', 117 | required=True, help='This is password\'s confirm', 118 | ) 119 | register_parser.add_argument( 120 | 'role', dest='role', 121 | type=int, location='form', 122 | required=True, help='This is user\'s role', 123 | ) 124 | 125 | # ------------ register parser ------------ 126 | account_update_parser = reqparse.RequestParser() 127 | 128 | account_update_parser.add_argument( 129 | 'nickname', dest='nickname', 130 | type=str, location='form', 131 | required=True, help='This is new nickname', 132 | ) 133 | 134 | book_update_parser.add_argument( 135 | 'des', dest='des', 136 | type=str, location='form', 137 | required=False, help='The account description', 138 | ) 139 | 140 | # ------------ vip parser ------------ 141 | vip_parser = reqparse.RequestParser() 142 | vip_parser.add_argument( 143 | 'username', dest='username', 144 | type=unicode, location='form', 145 | required=True, help='The vip\'s username', 146 | ) 147 | 148 | vip_parser.add_argument( 149 | 'nickname', dest='nickname', 150 | type=unicode, location='form', 151 | required=True, help='The vip\'s nickname', 152 | ) 153 | 154 | vip_parser.add_argument( 155 | 'phone', dest='phone', 156 | type=str, location='form', 157 | required=False, help='The vip\'s phone', 158 | ) 159 | 160 | # ------------ sales record parser ------------ 161 | sales_record_parser = reqparse.RequestParser() 162 | sales_record_parser.add_argument( 163 | 'count', dest='count', 164 | type=int, location='form', 165 | required=True, help='The sales\'s count', 166 | ) 167 | 168 | sales_record_parser.add_argument( 169 | 'seller_id', dest='seller_id', 170 | type=str, location='form', 171 | required=True, help='The sales\'s seller id', 172 | ) 173 | 174 | sales_record_parser.add_argument( 175 | 'book_id', dest='book_id', 176 | type=str, location='form', 177 | required=True, help='The sales\'s book id', 178 | ) 179 | 180 | sales_record_parser.add_argument( 181 | 'purchaser_id', dest='purchaser_id', 182 | type=str, location='form', 183 | required=False, help='The sales\'s purchaser id', 184 | ) 185 | -------------------------------------------------------------------------------- /RESTfulApi/common/util.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | """ 5 | File name: util.py 6 | Function Des: ... 7 | ~~~~~~~~~~ 8 | 9 | author: Jerry 10 | 11 | """ 12 | 13 | -------------------------------------------------------------------------------- /RESTfulApi/handler/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | """ 5 | File name: __init__.py 6 | Function Des: ... 7 | ~~~~~~~~~~ 8 | 9 | author: Jerry 10 | 11 | """ 12 | 13 | -------------------------------------------------------------------------------- /RESTfulApi/handler/account.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | """ 5 | File name: account.py 6 | Function Des: ... 7 | ~~~~~~~~~~ 8 | 9 | author: Jerry 10 | 11 | """ 12 | from mongoengine import Q 13 | from flask import abort 14 | from RESTfulApi.models.shop_db import Account 15 | from RESTfulApi.models.token_db import Token 16 | from RESTfulApi.utils.authority import create_token, is_admin, is_root, is_self, is_stuff 17 | 18 | 19 | def get_accounts(args, token=None): 20 | if token is None or not is_stuff(token): 21 | return abort(403) 22 | if is_admin(token): 23 | condition = Q(username__ne='root') 24 | else: 25 | condition = Q(username__ne='root') & Q(role='stuff') 26 | if 'username' in args: 27 | condition &= Q(username=args['username']) 28 | if 'nickname' in args: 29 | condition &= Q(nickname=args['nickname']) 30 | accounts = Account.objects(condition) 31 | return accounts 32 | 33 | 34 | def get_all_accounts(token=None): 35 | if token is None or not is_stuff(token): 36 | return abort(403) 37 | if is_admin(token): 38 | condition = Q(username__ne='root') 39 | else: 40 | condition = Q(username__ne='root') & Q(role='stuff') 41 | accounts = Account.objects(condition) 42 | return accounts 43 | 44 | 45 | def create_account(username, password, confirm, role, nickname, token=None): 46 | if token is None or not is_admin(token): 47 | return abort(403) 48 | 49 | if password != confirm: 50 | return { 51 | "message": "password not conformity" 52 | } 53 | if Account.objects(username=username).first() is not None: 54 | return { 55 | "message": "username has been register" 56 | } 57 | 58 | if str(role) == '1': 59 | role = 'admin' 60 | else: 61 | role = 'stuff' 62 | account = Account( 63 | username=username, 64 | nickname=nickname, 65 | password=Account.create_password(password), 66 | role=role, 67 | ).save() 68 | token = Token( 69 | user_id=str(account.id), 70 | token=create_token(), 71 | ).save() 72 | return { 73 | 'id': account.id, 74 | 'success': 1, 75 | 'token': token.token 76 | } 77 | 78 | 79 | def rm_account(account_id, token=None): 80 | if token is None or not is_admin(token): 81 | return abort(403) 82 | 83 | account = Account.objects(id=account_id).first() 84 | if account is None: 85 | return {'message': 'this account has been deleted'} 86 | if account.role == 'admin': 87 | if not is_root(token): 88 | return abort(403) 89 | account.delete() 90 | return {'success': 1} 91 | 92 | 93 | def update_account(account_id, nickname, des, old_password, new_password, confirm, token=None): 94 | if token is None or not (is_admin(token) or is_self(account_id, token)): 95 | return abort(403) 96 | account = Account.objects(id=account_id).first() 97 | if account is None or account.username == 'root': 98 | return abort(403) 99 | if des is None: 100 | des = "" 101 | password = account.password 102 | if new_password or confirm: 103 | if new_password == confirm: 104 | if Account.check_password(account, old_password): 105 | password = Account.create_password(new_password) 106 | else: 107 | return { 108 | 'success': 0, 109 | 'message': 'wrong password' 110 | } 111 | else: 112 | return { 113 | 'success': 0, 114 | 'message': 'pwd != confirm' 115 | } 116 | account.update( 117 | nickname=nickname, 118 | description=des, 119 | password=password, 120 | ) 121 | account.save() 122 | return { 123 | 'success': 1, 124 | 'id': account_id, 125 | 'message': 'user\'s profile update successfully!' 126 | } 127 | 128 | 129 | def get_account_by_id(account_id, token=None): 130 | if token is None or not is_stuff(token): 131 | return abort(403) 132 | condition = Q(id=account_id) 133 | if is_admin(token) and not is_root(token): 134 | condition &= Q(username__ne='root') 135 | elif not is_root(token): 136 | condition = Q(username__ne='root') & Q(role='stuff') 137 | account = Account.objects(condition).first() 138 | return account 139 | -------------------------------------------------------------------------------- /RESTfulApi/handler/book.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | """ 5 | File name: book.py 6 | Function Des: ... 7 | ~~~~~~~~~~ 8 | 9 | author: Jerry 10 | 11 | """ 12 | from flask import abort 13 | from mongoengine import Q, ValidationError 14 | from RESTfulApi.models.shop_db import Book, Type 15 | from RESTfulApi.utils.authority import is_admin, is_stuff 16 | 17 | 18 | def get_all_books(token=None): 19 | if token is None or not is_stuff(token): 20 | return abort(403) 21 | books = Book.objects() 22 | return books 23 | 24 | 25 | def create_book(name, price, count, description, token=None): 26 | if token is None or not is_admin(token): 27 | return abort(403) 28 | if Book.objects(name=name).first() is not None: 29 | return { 30 | 'message': 'this book has been existed' 31 | } 32 | book = Book( 33 | name=name, 34 | price=price, 35 | remaining=count, 36 | description=description, 37 | ) 38 | book = book.save() 39 | return { 40 | 'success': 1, 41 | 'id': book.id 42 | } 43 | 44 | 45 | def get_book_by_id(book_id, token=None): 46 | if token is None or not is_stuff(token): 47 | return abort(403) 48 | book = Book.objects(id=book_id).first() 49 | return book 50 | 51 | 52 | def get_books(args, token=None): 53 | if token is None or not is_stuff(token): 54 | return abort(403) 55 | condition = None 56 | if 'id' in args: 57 | condition = Q(id=args['id']) 58 | if 'name' in args: 59 | if condition is None: 60 | condition = Q(name=args['name']) 61 | else: 62 | condition &= Q(name=args['name']) 63 | books = Book.objects(condition) 64 | return books 65 | 66 | 67 | def rm_book(book_id, token=None): 68 | if token is None or not is_admin(token): 69 | return abort(403) 70 | book = Book.objects(id=book_id) 71 | book.delete() 72 | return {'success': 1} 73 | 74 | 75 | def update_book(book_id, delta, price, des, type_id_list, token=None): 76 | if token is None or not is_admin(token): 77 | return abort(403) 78 | book = Book.objects(id=book_id).first() 79 | if book is None: 80 | return {'message': 'This book does not exist.'} 81 | remaining = book.remaining 82 | if des is None: 83 | des = "" 84 | book.update( 85 | price=price, 86 | remaining=remaining+delta, 87 | description=des, 88 | ) 89 | del book.type[:] 90 | if type_id_list is not None: 91 | for i in type_id_list: 92 | try: 93 | term = Type.objects(id=i).first() 94 | except ValidationError: 95 | continue 96 | if term is None: 97 | continue 98 | book.type.append(term) 99 | book.save() 100 | return { 101 | 'success': 1, 102 | 'id': book_id, 103 | } 104 | -------------------------------------------------------------------------------- /RESTfulApi/handler/book_type.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | """ 5 | File name: book_type.py 6 | Function Des: ... 7 | ~~~~~~~~~~ 8 | 9 | author: Jerry 10 | 11 | """ 12 | from flask import abort 13 | from mongoengine import Q, OperationError 14 | from RESTfulApi.models.shop_db import Type 15 | from RESTfulApi.utils.authority import is_admin, is_stuff 16 | 17 | 18 | def get_all_types(token=None): 19 | if token is None or not is_stuff(token): 20 | return abort(403) 21 | types = Type.objects() 22 | return types 23 | 24 | 25 | def create_book_type(name, token=None): 26 | if token is None or not is_stuff(token): 27 | return abort(403) 28 | if Type.objects(name=name).first() is not None: 29 | return {'message': 'This type has been exist'} 30 | book_type = Type(name=name).save() 31 | return { 32 | 'id': book_type.id, 33 | 'success': 1, 34 | } 35 | 36 | 37 | def get_book_types(args, token=None): 38 | if token is None or not is_stuff(token): 39 | return abort(403) 40 | condition = None 41 | if 'id' in args: 42 | condition = Q(id=args['id']) 43 | if 'name' in args: 44 | if condition is None: 45 | condition = Q(name=args['name']) 46 | else: 47 | condition &= Q(name=args['name']) 48 | types = Type.objects(condition) 49 | return types 50 | 51 | 52 | def rm_book_type(book_type_id, token=None): 53 | if token is None or not is_admin(token): 54 | return abort(403) 55 | book_type = Type.objects(id=book_type_id) 56 | try: 57 | book_type.delete() 58 | except OperationError: 59 | return { 60 | "message": "please dereference before delete the type." 61 | } 62 | else: 63 | return {'success': 1} 64 | -------------------------------------------------------------------------------- /RESTfulApi/handler/reference.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | """ 5 | File name: reference.py 6 | Function Des: ... 7 | ~~~~~~~~~~ 8 | 9 | author: Jerry 10 | 11 | """ 12 | from flask import abort 13 | from RESTfulApi.models.shop_db import Type, Book, Account, Vip, SalesRecord 14 | from RESTfulApi.utils.authority import is_admin, is_stuff 15 | 16 | 17 | def get_books_by_type(type_id, token=None): 18 | if token is None or not is_stuff(token): 19 | return abort(403) 20 | the_type = Type.objects(id=type_id).first() 21 | books = Book.objects(type__in=[the_type]) 22 | return books 23 | 24 | 25 | def rm_ref_book2type(type_id, token=None): 26 | if token is None or not is_admin(token): 27 | return abort(403) 28 | the_type = Type.objects(id=type_id).first() 29 | all_books = Book.objects() 30 | for book in all_books: 31 | if the_type in book.type: 32 | book.type.remove(the_type) 33 | book.save() 34 | return {'success': 1} 35 | 36 | 37 | def get_sales_records_by_account(account_id, token=None): 38 | if token is None or not is_stuff(token): 39 | return abort(403) 40 | account = Account.objects(id=account_id).first() 41 | sales_records = SalesRecord.objects(seller=account) 42 | return sales_records 43 | 44 | 45 | def get_sales_records_by_book(book_id, token=None): 46 | if token is None or not is_stuff(token): 47 | return abort(403) 48 | book = Book.objects(id=book_id).first() 49 | sales_records = SalesRecord.objects(book=book) 50 | return sales_records 51 | 52 | 53 | def get_sales_records_by_vip(vip_id, token=None): 54 | if token is None or not is_stuff(token): 55 | return abort(403) 56 | vip = Vip.objects(id=vip_id).first() 57 | sales_records = SalesRecord.objects(purchaser=vip) 58 | return sales_records 59 | 60 | -------------------------------------------------------------------------------- /RESTfulApi/handler/sales_record.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | """ 5 | File name: sales_record.py 6 | Function Des: ... 7 | ~~~~~~~~~~ 8 | 9 | author: Jerry 10 | 11 | """ 12 | from flask import abort 13 | from mongoengine import ValidationError 14 | from RESTfulApi.models.shop_db import SalesRecord 15 | from RESTfulApi.models.shop_db import Account, Book, Vip 16 | from RESTfulApi.utils.authority import is_stuff, is_admin 17 | 18 | 19 | def get_all_sales_records(token=None): 20 | if token is None or not is_admin(token): 21 | return abort(403) 22 | sales_records = SalesRecord.objects() 23 | return sales_records 24 | 25 | 26 | def create_sales_record(count, seller_id, book_id, purchaser_id, token=None): 27 | if token is None or not is_stuff(token): 28 | return abort(403) 29 | book = Book.objects(id=book_id).first() 30 | if book is None: 31 | return {'message': 'Missing parameter book, or book id is wrong.'} 32 | if book.remaining < count: 33 | return {'message': 'This book is not enough'} 34 | price = book.price 35 | seller = Account.objects(id=seller_id).first() 36 | if seller is None: 37 | return {'message': 'Missing parameter seller, or seller id is wrong.'} 38 | try: 39 | purchaser = Vip.objects(id=purchaser_id).first() 40 | except ValidationError: 41 | purchaser = None 42 | if purchaser is not None: 43 | price *= 0.8 44 | book.remaining -= count 45 | book.sales += count 46 | book.save() 47 | sales_record = SalesRecord( 48 | count=count, 49 | price=price, 50 | book=book, 51 | seller=seller, 52 | purchaser=purchaser, 53 | ).save() 54 | return { 55 | 'id': sales_record.id, 56 | 'success': 1 57 | } 58 | 59 | -------------------------------------------------------------------------------- /RESTfulApi/handler/session.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | """ 5 | File name: session.py 6 | Function Des: ... 7 | ~~~~~~~~~~ 8 | 9 | author: Jerry 10 | 11 | """ 12 | from RESTfulApi.models.shop_db import Account 13 | from RESTfulApi.models.token_db import Token 14 | from RESTfulApi.utils.authority import create_token 15 | 16 | 17 | def login(username, password): 18 | account = Account.objects(username=username).first() 19 | if account is None: 20 | return {'message': 'this account does not exist'} 21 | if Account.check_password(account, password): 22 | new_token = create_token() 23 | token = Token.objects(user_id=str(account.id)).first() 24 | if token is None: 25 | Token(user_id=str(account.id), token=new_token).save() 26 | else: 27 | token.update(token=new_token) 28 | return { 29 | 'id': account.id, 30 | 'success': 1, 31 | 'token': new_token 32 | } 33 | else: 34 | return { 35 | 'message': 'password is wrong.' 36 | } 37 | 38 | 39 | def logout(token): 40 | token = Token.objects(token=token).first() 41 | token.delete() 42 | return {'success': 1} 43 | -------------------------------------------------------------------------------- /RESTfulApi/handler/vip.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | """ 5 | File name: vip.py 6 | Function Des: ... 7 | ~~~~~~~~~~ 8 | 9 | author: Jerry 10 | 11 | """ 12 | from flask import abort 13 | from mongoengine import Q, NotUniqueError 14 | from RESTfulApi.models.shop_db import Vip 15 | from RESTfulApi.utils.authority import is_stuff 16 | 17 | 18 | def get_all_vips(token=None): 19 | if token is None or not is_stuff(token): 20 | return abort(403) 21 | 22 | vips = Vip.objects() 23 | return vips 24 | 25 | 26 | def create_vip(username, nickname, phone, token=None): 27 | if token is None or not is_stuff(token): 28 | return abort(403) 29 | if phone is None: 30 | phone = "" 31 | if Vip.objects(username=username).first() is not None: 32 | return {'message': 'The vip\'s name has been used'} 33 | vip = Vip( 34 | username=username, 35 | nickname=nickname, 36 | phone=phone, 37 | ).save() 38 | return { 39 | 'id': vip.id, 40 | 'success': 1, 41 | } 42 | 43 | 44 | def get_vips(args, token=None): 45 | if token is None or not is_stuff(token): 46 | return abort(403) 47 | 48 | if 'name' in args: 49 | return Vip.objects(Q(name=args['name'])) 50 | return None 51 | 52 | 53 | def rm_vip(book_id, token=None): 54 | if token is None or not is_stuff(token): 55 | return abort(403) 56 | vip = Vip.objects(id=book_id) 57 | vip.delete() 58 | return {'success': 1} 59 | 60 | 61 | -------------------------------------------------------------------------------- /RESTfulApi/models/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | """ 5 | File name: __init__.py.py 6 | Function Des: ... 7 | ~~~~~~~~~~ 8 | 9 | author: Jerry 10 | 11 | """ 12 | 13 | 14 | from shop_db import * 15 | from mongoengine import connect 16 | 17 | 18 | def register_database(app): 19 | database = app.config['MONGODB_SETTINGS']['DB'] 20 | connect(database) 21 | -------------------------------------------------------------------------------- /RESTfulApi/models/init.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | """ 5 | File name: init.py 6 | Function Des: ... 7 | ~~~~~~~~~~ 8 | 9 | author: Jerry 10 | 11 | """ 12 | from mongoengine import connect 13 | from werkzeug import security 14 | from RESTfulApi.models.shop_db import Account 15 | from RESTfulApi.models.token_db import Token 16 | from RESTfulApi.utils.authority import create_token 17 | 18 | 19 | connect('library') 20 | 21 | 22 | def create_password(raw): 23 | pwd = '{old}{new}'.format(old=raw, new='secret_for_ensure_password_security') 24 | return security.generate_password_hash(pwd) 25 | 26 | 27 | # 因代码需要,用户名必须为root 28 | def create_root(username='root', password='password', role='admin', nickname='Super'): 29 | account = Account( 30 | username=username, 31 | nickname=nickname, 32 | password=create_password(password), 33 | role=role, 34 | ).save() 35 | token = Token( 36 | user_id=str(account.id), 37 | token=create_token(), 38 | ).save() 39 | return token.token 40 | 41 | if __name__ == '__main__': 42 | print create_root() 43 | 44 | -------------------------------------------------------------------------------- /RESTfulApi/models/shop_db.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | """ 5 | File name: shop_db.py 6 | Function Des: MongoDB数据库映射 7 | ~~~~~~~~~~ 8 | 9 | author: Jerry 10 | 11 | """ 12 | 13 | from datetime import datetime 14 | from mongoengine import * 15 | from werkzeug import security 16 | from flask import current_app 17 | 18 | 19 | __all__ = ['Type', 'Book', 'SalesRecord', 'Vip', 'Account'] 20 | 21 | 22 | class Vip(Document): 23 | username = StringField(required=True, max_length=5, unique=True) 24 | nickname = StringField(required=True, max_length=40) 25 | phone = StringField(max_length=15) 26 | register_time = DateTimeField(default=datetime.today) 27 | 28 | 29 | class Type(Document): 30 | name = StringField(required=True, unique=True) 31 | 32 | 33 | class Book(Document): 34 | name = StringField(required=True, max_length=40, unique=True) 35 | price = FloatField(required=True) 36 | sales = IntField(default=0) 37 | remaining = IntField(required=True) 38 | description = StringField(default='', max_length=400) 39 | type = ListField(ReferenceField(Type, reverse_delete_rule=DENY)) 40 | 41 | 42 | class Account(Document): 43 | username = StringField(required=True, max_length=10, unique=True) 44 | password = StringField(required=True, max_length=100) 45 | nickname = StringField(required=True, max_length=10) 46 | role = StringField(max_length=10, default='stuff') 47 | description = StringField(default='', max_length=400) 48 | 49 | created = DateTimeField(default=datetime.today) 50 | 51 | @staticmethod 52 | def create_password(raw): 53 | pwd = '{old}{new}'.format(old=raw, new=current_app.config['PASSWORD_SECRET']) 54 | return security.generate_password_hash(pwd) 55 | 56 | @staticmethod 57 | def is_admin(self): 58 | return self.role == 'admin' 59 | 60 | @staticmethod 61 | def check_password(user, raw): 62 | pwd = '{old}{new}'.format(old=raw, new=current_app.config['PASSWORD_SECRET']) 63 | return security.check_password_hash(user.password, pwd) 64 | 65 | 66 | class SalesRecord(Document): 67 | seller = ReferenceField(Account, required=True) 68 | book = ReferenceField(Book, required=True) 69 | price = FloatField(required=True) 70 | count = IntField(default=1) 71 | sale_time = DateTimeField(default=datetime.today) 72 | purchaser = ReferenceField(Vip, required=False) 73 | 74 | -------------------------------------------------------------------------------- /RESTfulApi/models/token_db.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | """ 5 | File name: token_db.py 6 | Function Des: ... 7 | ~~~~~~~~~~ 8 | 9 | author: Jerry 10 | 11 | """ 12 | 13 | from datetime import datetime 14 | from mongoengine import * 15 | 16 | 17 | class Token(Document): 18 | user_id = StringField(required=True, unique=True) 19 | token = StringField(default='', unique=True) 20 | created = DateTimeField(default=datetime.today) 21 | -------------------------------------------------------------------------------- /RESTfulApi/resources/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | """ 5 | File name: __init__.py.py 6 | Function Des: ... 7 | ~~~~~~~~~~ 8 | 9 | author: Jerry 10 | 11 | """ 12 | -------------------------------------------------------------------------------- /RESTfulApi/resources/account.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | """ 5 | File name: account.py 6 | Function Des: ... 7 | ~~~~~~~~~~ 8 | 9 | author: Jerry 10 | 11 | """ 12 | from flask.ext.restful import Resource, request, marshal_with 13 | 14 | from RESTfulApi.handler.account import get_accounts, get_all_accounts 15 | from RESTfulApi.handler.account import create_account, rm_account, update_account, get_account_by_id 16 | 17 | from RESTfulApi.utils.fields import deleted_fields, pt_fields, pt_fields_with_token 18 | from RESTfulApi.utils.fields.account import account_detail_fields, accounts_fields 19 | 20 | from RESTfulApi.utils.parsers import token_parser 21 | from RESTfulApi.utils.parsers.account import register_parser, account_update_parser 22 | 23 | 24 | class Accounts(Resource): 25 | @marshal_with(accounts_fields) 26 | def get(self): 27 | token = token_parser.parse_args().token 28 | args = request.args 29 | if args: 30 | accounts = get_accounts(args, token=token) 31 | else: 32 | accounts = get_all_accounts(token=token) 33 | return {'accounts': accounts} 34 | 35 | @marshal_with(pt_fields_with_token) 36 | def post(self): 37 | token = token_parser.parse_args().token 38 | account_args = register_parser.parse_args() 39 | result = create_account( 40 | account_args.username, account_args.password, account_args.confirm, account_args.role, 41 | account_args.nickname, token=token 42 | ) 43 | return result 44 | 45 | 46 | class Account(Resource): 47 | @marshal_with(account_detail_fields) 48 | def get(self, account_id): 49 | token = token_parser.parse_args().token 50 | return get_account_by_id(account_id, token=token) 51 | 52 | @marshal_with(pt_fields) 53 | def put(self, account_id): 54 | token = token_parser.parse_args().token 55 | account_args = account_update_parser.parse_args() 56 | result = update_account(account_id, account_args.nickname, account_args.des, account_args.old_password, 57 | account_args.new_password, account_args.confirm, token=token) 58 | return result 59 | 60 | @marshal_with(deleted_fields) 61 | def delete(self, account_id): 62 | token = token_parser.parse_args().token 63 | result = rm_account(account_id, token=token) 64 | return result -------------------------------------------------------------------------------- /RESTfulApi/resources/book.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | """ 5 | File name: book.py 6 | Function Des: ... 7 | ~~~~~~~~~~ 8 | 9 | author: Jerry 10 | 11 | """ 12 | from flask.ext.restful import Resource, request, marshal_with 13 | 14 | from RESTfulApi.handler.book import get_all_books, create_book 15 | from RESTfulApi.handler.book import get_book_by_id, get_books, rm_book, update_book 16 | 17 | from RESTfulApi.utils.fields import deleted_fields, pt_fields 18 | from RESTfulApi.utils.fields.book import book_detail_fields, books_fields 19 | 20 | from RESTfulApi.utils.parsers import token_parser 21 | from RESTfulApi.utils.parsers.book import book_post_parser, book_put_parser 22 | 23 | 24 | class Books(Resource): 25 | @marshal_with(books_fields) 26 | def get(self): 27 | token = token_parser.parse_args().token 28 | args = request.args 29 | if args: 30 | books = get_books(args, token=token) 31 | else: 32 | books = get_all_books(token=token) 33 | return {'books': books} 34 | 35 | @marshal_with(pt_fields) 36 | def post(self): 37 | token = token_parser.parse_args().token 38 | book_args = book_post_parser.parse_args() 39 | result = create_book(book_args.name, book_args.price, book_args.count, book_args.des, token=token) 40 | return result 41 | 42 | 43 | class Book(Resource): 44 | @marshal_with(book_detail_fields) 45 | def get(self, book_id): 46 | token = token_parser.parse_args().token 47 | return get_book_by_id(book_id, token=token) 48 | 49 | @marshal_with(pt_fields) 50 | def put(self, book_id): 51 | token = token_parser.parse_args().token 52 | book_args = book_put_parser.parse_args() 53 | result = update_book(book_id, book_args.delta, book_args.price, book_args.des, book_args.type_ids, token=token) 54 | return result 55 | 56 | @marshal_with(deleted_fields) 57 | def delete(self, book_id): 58 | token = token_parser.parse_args().token 59 | result = rm_book(book_id, token=token) 60 | return result 61 | -------------------------------------------------------------------------------- /RESTfulApi/resources/book_type.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | """ 5 | File name: book_type.py 6 | Function Des: ... 7 | ~~~~~~~~~~ 8 | 9 | author: Jerry 10 | 11 | """ 12 | 13 | from flask.ext.restful import Resource, request, marshal_with 14 | 15 | from RESTfulApi.handler.book_type import get_all_types, create_book_type, get_book_types, rm_book_type 16 | 17 | from RESTfulApi.utils.parsers import token_parser 18 | from RESTfulApi.utils.parsers.book_type import book_type_post_parser 19 | 20 | from RESTfulApi.utils.fields import pt_fields, deleted_fields 21 | from RESTfulApi.utils.fields.book_type import book_types_fields 22 | 23 | 24 | class BookTypes(Resource): 25 | @marshal_with(book_types_fields) 26 | def get(self): 27 | token = token_parser.parse_args().token 28 | args = request.args 29 | if args: 30 | books_types = get_book_types(args, token=token) 31 | else: 32 | books_types = get_all_types(token=token) 33 | return {'books_types': books_types} 34 | 35 | @marshal_with(pt_fields) 36 | def post(self): 37 | token = token_parser.parse_args().token 38 | book_args = book_type_post_parser.parse_args() 39 | result = create_book_type(book_args.name, token=token) 40 | return result 41 | 42 | 43 | class BookType(Resource): 44 | @marshal_with(deleted_fields) 45 | def delete(self, book_type_id): 46 | token = token_parser.parse_args().token 47 | result = rm_book_type(book_type_id, token=token) 48 | return result 49 | -------------------------------------------------------------------------------- /RESTfulApi/resources/reference.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | """ 5 | File name: reference.py 6 | Function Des: ... 7 | ~~~~~~~~~~ 8 | 9 | author: Jerry 10 | 11 | """ 12 | from flask.ext.restful import Resource, marshal_with 13 | from RESTfulApi.utils.fields import deleted_fields 14 | from RESTfulApi.utils.parsers import token_parser 15 | from RESTfulApi.utils.fields.book import books_fields 16 | from RESTfulApi.utils.fields.sales_record import sales_records_fields 17 | from RESTfulApi.handler.reference import get_sales_records_by_book, get_sales_records_by_vip 18 | from RESTfulApi.handler.reference import get_books_by_type, rm_ref_book2type, get_sales_records_by_account 19 | 20 | 21 | class ReferenceBook2Type(Resource): 22 | @marshal_with(books_fields) 23 | def get(self, book_type_id): 24 | token = token_parser.parse_args().token 25 | books = get_books_by_type(book_type_id, token=token) 26 | return {'books': books} 27 | 28 | @marshal_with(deleted_fields) 29 | def delete(self, book_type_id): 30 | token = token_parser.parse_args().token 31 | result = rm_ref_book2type(book_type_id, token=token) 32 | return result 33 | 34 | 35 | class ReferenceSaleRecord2Account(Resource): 36 | @marshal_with(sales_records_fields) 37 | def get(self, account_id): 38 | token = token_parser.parse_args().token 39 | sales_records = get_sales_records_by_account(account_id, token=token) 40 | return {'sales_records': sales_records} 41 | 42 | 43 | class ReferenceSaleRecord2Book(Resource): 44 | @marshal_with(sales_records_fields) 45 | def get(self, book_id): 46 | token = token_parser.parse_args().token 47 | sales_records = get_sales_records_by_book(book_id, token=token) 48 | return {'sales_records': sales_records} 49 | 50 | 51 | class ReferenceSale2Vip(Resource): 52 | @marshal_with(sales_records_fields) 53 | def get(self, vip_id): 54 | token = token_parser.parse_args().token 55 | sales_records = get_sales_records_by_vip(vip_id, token=token) 56 | return {'sales_records': sales_records} 57 | 58 | -------------------------------------------------------------------------------- /RESTfulApi/resources/sales_record.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | """ 5 | File name: sales_record.py 6 | Function Des: ... 7 | ~~~~~~~~~~ 8 | 9 | author: Jerry 10 | 11 | """ 12 | from flask.ext.restful import Resource, marshal_with 13 | 14 | from RESTfulApi.handler.sales_record import get_all_sales_records, create_sales_record 15 | from RESTfulApi.utils.parsers import token_parser 16 | from RESTfulApi.utils.parsers.sales_record import sales_record_post_parser 17 | from RESTfulApi.utils.fields import pt_fields 18 | from RESTfulApi.utils.fields.sales_record import sales_records_fields 19 | 20 | 21 | class SalesRecords(Resource): 22 | @marshal_with(sales_records_fields) 23 | def get(self): 24 | token = token_parser.parse_args().token 25 | sales_records = get_all_sales_records(token=token) 26 | return {'sales_records': sales_records} 27 | 28 | @marshal_with(pt_fields) 29 | def post(self): 30 | token = token_parser.parse_args().token 31 | sales_args = sales_record_post_parser.parse_args() 32 | result = create_sales_record(sales_args.count, sales_args.seller_id, 33 | sales_args.book_id, sales_args.purchaser_id, token=token) 34 | return result 35 | -------------------------------------------------------------------------------- /RESTfulApi/resources/session.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | """ 5 | File name: session.py 6 | Function Des: ... 7 | ~~~~~~~~~~ 8 | 9 | author: Jerry 10 | 11 | """ 12 | from flask.ext.restful import Resource, marshal_with 13 | 14 | from RESTfulApi.handler.session import login, logout 15 | from RESTfulApi.utils.parsers import token_parser 16 | from RESTfulApi.utils.parsers.session import login_parser 17 | from RESTfulApi.utils.fields import deleted_fields, pt_fields_with_token 18 | 19 | 20 | class Session(Resource): 21 | @marshal_with(pt_fields_with_token) 22 | def post(self): 23 | login_args = login_parser.parse_args() 24 | result = login(login_args.username, login_args.password) 25 | return result 26 | 27 | @marshal_with(deleted_fields) 28 | def delete(self): 29 | token = token_parser.parse_args().token 30 | result = logout(token) 31 | return result 32 | -------------------------------------------------------------------------------- /RESTfulApi/resources/vip.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | """ 5 | File name: vip.py 6 | Function Des: ... 7 | ~~~~~~~~~~ 8 | 9 | author: Jerry 10 | 11 | """ 12 | from flask.ext.restful import Resource, request, marshal_with 13 | 14 | from RESTfulApi.handler.vip import get_all_vips, create_vip, get_vips, rm_vip 15 | 16 | from RESTfulApi.utils.parsers import token_parser 17 | from RESTfulApi.utils.parsers.vip import vip_post_parser 18 | from RESTfulApi.utils.fields import deleted_fields, pt_fields 19 | from RESTfulApi.utils.fields.vip import vips_fields 20 | 21 | 22 | class Vips(Resource): 23 | @marshal_with(vips_fields) 24 | def get(self): 25 | token = token_parser.parse_args().token 26 | args = request.args 27 | if args: 28 | vips = get_vips(args, token=token) 29 | else: 30 | vips = get_all_vips(token=token) 31 | return {'vips': vips} 32 | 33 | @marshal_with(pt_fields) 34 | def post(self): 35 | token = token_parser.parse_args().token 36 | vip_args = vip_post_parser.parse_args() 37 | result = create_vip(vip_args.username, vip_args.nickname, vip_args.phone, token=token) 38 | return result 39 | 40 | 41 | class Vip(Resource): 42 | @marshal_with(deleted_fields) 43 | def delete(self, vip_id): 44 | token = token_parser.parse_args().token 45 | result = rm_vip(vip_id, token=token) 46 | return result 47 | -------------------------------------------------------------------------------- /RESTfulApi/utils/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | """ 5 | File name: __init__.py.py 6 | Function Des: ... 7 | ~~~~~~~~~~ 8 | 9 | author: Jerry 10 | 11 | """ 12 | 13 | -------------------------------------------------------------------------------- /RESTfulApi/utils/authority.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | """ 5 | File name: authority.py 6 | Function Des: ... 7 | ~~~~~~~~~~ 8 | 9 | author: Jerry 10 | 11 | """ 12 | 13 | from werkzeug import security 14 | 15 | from RESTfulApi.models.token_db import Token 16 | from RESTfulApi.models.shop_db import Account 17 | 18 | 19 | def create_token(length=16): 20 | return security.gen_salt(length) 21 | 22 | 23 | def is_root(token): 24 | token = Token.objects(token=token).first() 25 | if token is None: 26 | return False 27 | account = Account.objects(id=token.user_id).first() 28 | if account is None: 29 | return False 30 | if account.username == 'root': 31 | return True 32 | return False 33 | 34 | 35 | def is_admin(token): 36 | token = Token.objects(token=token).first() 37 | if token is None: 38 | return False 39 | account = Account.objects(id=token.user_id).first() 40 | if account is None: 41 | return False 42 | if account.role == 'stuff': 43 | return False 44 | return True 45 | 46 | 47 | def is_stuff(token): 48 | token = Token.objects(token=token).first() 49 | if token is None: 50 | return False 51 | account = Account.objects(id=token.user_id).first() 52 | if account is None: 53 | return False 54 | return True 55 | 56 | 57 | def is_self(account_id, token): 58 | token = Token.objects(token=token).first() 59 | if token is None: 60 | return False 61 | if account_id != token.user_id: 62 | return False 63 | return True 64 | -------------------------------------------------------------------------------- /RESTfulApi/utils/fields/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | """ 5 | File name: __init__.py.py 6 | Function Des: ... 7 | ~~~~~~~~~~ 8 | 9 | author: Jerry 10 | 11 | """ 12 | 13 | from common import * 14 | -------------------------------------------------------------------------------- /RESTfulApi/utils/fields/account.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | """ 5 | File name: account.py 6 | Function Des: ... 7 | ~~~~~~~~~~ 8 | 9 | author: Jerry 10 | 11 | """ 12 | from flask.ext.restful import fields 13 | 14 | # for get /accounts/ 15 | account_detail_fields = { 16 | 'id': fields.String, 17 | 'username': fields.String, 18 | 'nickname': fields.String, 19 | 'role': fields.String, 20 | 'description': fields.String, 21 | 'created': fields.DateTime, 22 | } 23 | 24 | # for get /accounts 25 | account_simple_fields = { 26 | 'id': fields.String, 27 | 'nickname': fields.String, 28 | 'role': fields.String, 29 | } 30 | 31 | accounts_fields = { 32 | 'accounts': fields.List(fields.Nested(account_simple_fields)) 33 | } 34 | -------------------------------------------------------------------------------- /RESTfulApi/utils/fields/book.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | """ 5 | File name: book.py 6 | Function Des: ... 7 | ~~~~~~~~~~ 8 | 9 | author: Jerry 10 | 11 | """ 12 | from flask.ext.restful import fields 13 | 14 | from book_type import book_type_fields 15 | 16 | # for get /books/ 17 | book_detail_fields = { 18 | 'id': fields.String, 19 | 'name': fields.String, 20 | 'price': fields.Float, 21 | 'remaining': fields.Integer, 22 | 'description': fields.String, 23 | 'sales': fields.Integer, 24 | 'type': fields.List(fields.Nested(book_type_fields)), 25 | } 26 | 27 | # for get /books 28 | 29 | book_simple_fields = { 30 | 'id': fields.String, 31 | 'name': fields.String, 32 | 'price': fields.Float, 33 | 'sales': fields.Integer, 34 | } 35 | 36 | books_fields = { 37 | 'books': fields.List(fields.Nested(book_simple_fields)) 38 | } 39 | 40 | -------------------------------------------------------------------------------- /RESTfulApi/utils/fields/book_type.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | """ 5 | File name: book_type.py 6 | Function Des: ... 7 | ~~~~~~~~~~ 8 | 9 | author: Jerry 10 | 11 | """ 12 | from flask.ext.restful import fields 13 | 14 | book_type_fields = { 15 | 'id': fields.String, 16 | 'name': fields.String, 17 | } 18 | 19 | # for get /types 20 | book_types_fields = { 21 | 'books_types': fields.List(fields.Nested(book_type_fields)) 22 | } 23 | -------------------------------------------------------------------------------- /RESTfulApi/utils/fields/common.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | """ 5 | File name: common.py 6 | Function Des: post/delete/put响应内容 7 | ~~~~~~~~~~ 8 | 9 | author: Jerry 10 | 11 | """ 12 | from flask.ext.restful import fields 13 | 14 | # after post/put with return id 15 | pt_fields = { 16 | 'id': fields.String, 17 | 'success': fields.Integer(default=0), 18 | 'message': fields.String(default='No message'), 19 | } 20 | 21 | # after post/put with return token 22 | pt_fields_with_token = { 23 | 'id': fields.String, 24 | 'token': fields.String, 25 | 'success': fields.Integer(default=0), 26 | 'message': fields.String(default='No message'), 27 | } 28 | 29 | # after delete 30 | deleted_fields = { 31 | 'success': fields.Integer(default=0), 32 | 'message': fields.String(default='No message'), 33 | } 34 | -------------------------------------------------------------------------------- /RESTfulApi/utils/fields/sales_record.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | """ 5 | File name: sales_record.py 6 | Function Des: ... 7 | ~~~~~~~~~~ 8 | 9 | author: Jerry 10 | 11 | """ 12 | from flask.ext.restful import fields 13 | from account import account_simple_fields 14 | from book import book_simple_fields 15 | from vip import vip_fields 16 | 17 | sales_record_fields = { 18 | 'id': fields.String, 19 | 'seller': fields.Nested(account_simple_fields), 20 | 'book': fields.Nested(book_simple_fields), 21 | 'price': fields.Float, 22 | 'count': fields.Integer, 23 | 'sale_time': fields.DateTime, 24 | 'purchaser': fields.Nested(vip_fields), 25 | } 26 | 27 | # from get /sales_records 28 | sales_records_fields = { 29 | 'sales_records': fields.List(fields.Nested(sales_record_fields)) 30 | } 31 | -------------------------------------------------------------------------------- /RESTfulApi/utils/fields/vip.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | """ 5 | File name: vip.py 6 | Function Des: ... 7 | ~~~~~~~~~~ 8 | 9 | author: Jerry 10 | 11 | """ 12 | from flask.ext.restful import fields 13 | 14 | 15 | vip_fields = { 16 | 'id': fields.String, 17 | 'username': fields.String, 18 | 'nickname': fields.String, 19 | 'phone': fields.String, 20 | } 21 | 22 | # for get /vips 23 | vips_fields = { 24 | 'vips': fields.List(fields.Nested(vip_fields)) 25 | } 26 | -------------------------------------------------------------------------------- /RESTfulApi/utils/parsers/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | """ 5 | File name: __init__.py.py 6 | Function Des: ... 7 | ~~~~~~~~~~ 8 | 9 | author: Jerry 10 | 11 | """ 12 | 13 | from common import * 14 | -------------------------------------------------------------------------------- /RESTfulApi/utils/parsers/account.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | """ 5 | File name: account.py 6 | Function Des: ... 7 | ~~~~~~~~~~ 8 | 9 | author: Jerry 10 | 11 | """ 12 | from flask.ext.restful import reqparse 13 | 14 | # ------------ register parser ------------ 15 | register_parser = reqparse.RequestParser() 16 | register_parser.add_argument( 17 | 'username', dest='username', 18 | type=str, location='form', 19 | required=True, help='This is username', 20 | ) 21 | 22 | register_parser.add_argument( 23 | 'nickname', dest='nickname', 24 | type=unicode, location='form', 25 | required=True, help='This is nickname', 26 | ) 27 | 28 | register_parser.add_argument( 29 | 'password', dest='password', 30 | type=str, location='form', 31 | required=True, help='This is password', 32 | ) 33 | 34 | register_parser.add_argument( 35 | 'confirm', dest='confirm', 36 | type=str, location='form', 37 | required=True, help='This is password\'s confirm', 38 | ) 39 | register_parser.add_argument( 40 | 'role', dest='role', 41 | type=int, location='form', 42 | required=True, help='This is user\'s role', 43 | ) 44 | 45 | # ------------ account update parser ------------ 46 | account_update_parser = reqparse.RequestParser() 47 | 48 | account_update_parser.add_argument( 49 | 'nickname', dest='nickname', 50 | type=unicode, location='form', 51 | required=True, help='This is new nickname', 52 | ) 53 | 54 | account_update_parser.add_argument( 55 | 'des', dest='des', 56 | type=unicode, location='form', 57 | required=False, help='The user\'s new description', 58 | ) 59 | 60 | account_update_parser.add_argument( 61 | 'old_password', dest='old_password', 62 | type=str, location='form', 63 | required=False, help='This is old password', 64 | ) 65 | 66 | account_update_parser.add_argument( 67 | 'new_password', dest='new_password', 68 | type=str, location='form', 69 | required=False, help='This is new password', 70 | ) 71 | 72 | account_update_parser.add_argument( 73 | 'confirm', dest='confirm', 74 | type=str, location='form', 75 | required=False, help='This is new password\'s confirm', 76 | ) 77 | -------------------------------------------------------------------------------- /RESTfulApi/utils/parsers/book.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | """ 5 | File name: book.py 6 | Function Des: ... 7 | ~~~~~~~~~~ 8 | 9 | author: Jerry 10 | 11 | """ 12 | from flask.ext.restful import reqparse 13 | 14 | 15 | # ------------ book add parser ------------ 16 | book_post_parser = reqparse.RequestParser() 17 | book_post_parser.add_argument( 18 | 'name', dest='name', 19 | type=unicode, location='form', 20 | required=True, help='The book\'s name', 21 | ) 22 | 23 | book_post_parser.add_argument( 24 | 'price', dest='price', 25 | type=float, location='form', 26 | required=True, help='The book\'s price', 27 | ) 28 | 29 | book_post_parser.add_argument( 30 | 'count', dest='count', 31 | type=int, location='form', 32 | required=True, help='The book\'s count', 33 | ) 34 | 35 | book_post_parser.add_argument( 36 | 'des', dest='des', 37 | type=unicode, location='form', 38 | required=False, help='The book\'s description', 39 | ) 40 | 41 | # ------------ book update parser ------------ 42 | book_put_parser = reqparse.RequestParser() 43 | book_put_parser.add_argument( 44 | 'delta', dest='delta', 45 | type=int, location='form', 46 | required=True, help='The book\'s deviation', 47 | ) 48 | 49 | book_put_parser.add_argument( 50 | 'price', dest='price', 51 | type=float, location='form', 52 | required=True, help='The book\'s new price', 53 | ) 54 | 55 | book_put_parser.add_argument( 56 | 'des', dest='des', 57 | type=unicode, location='form', 58 | required=False, help='The book\'s new description', 59 | ) 60 | 61 | book_put_parser.add_argument( 62 | 'type_id', dest='type_ids', action='append', 63 | type=str, location='form', 64 | required=False, help='The book\'s new list of type id', 65 | ) 66 | -------------------------------------------------------------------------------- /RESTfulApi/utils/parsers/book_type.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | """ 5 | File name: book_type.py 6 | Function Des: ... 7 | ~~~~~~~~~~ 8 | 9 | author: Jerry 10 | 11 | """ 12 | from flask.ext.restful import reqparse 13 | 14 | 15 | # ------------ book_type add parser ------------ 16 | book_type_post_parser = reqparse.RequestParser() 17 | book_type_post_parser.add_argument( 18 | 'name', dest='name', 19 | type=unicode, location='form', 20 | required=True, help='The book_type\'s name', 21 | ) 22 | -------------------------------------------------------------------------------- /RESTfulApi/utils/parsers/common.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | """ 5 | File name: common.py 6 | Function Des: ... 7 | ~~~~~~~~~~ 8 | 9 | author: Jerry 10 | 11 | """ 12 | from flask.ext.restful import reqparse 13 | 14 | 15 | token_parser = reqparse.RequestParser() 16 | token_parser.add_argument('token', location='headers', required=True) 17 | 18 | 19 | -------------------------------------------------------------------------------- /RESTfulApi/utils/parsers/sales_record.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | """ 5 | File name: sales_record.py 6 | Function Des: ... 7 | ~~~~~~~~~~ 8 | 9 | author: Jerry 10 | 11 | """ 12 | from flask.ext.restful import reqparse 13 | 14 | # ------------ sales record add parser ------------ 15 | sales_record_post_parser = reqparse.RequestParser() 16 | sales_record_post_parser.add_argument( 17 | 'count', dest='count', 18 | type=int, location='form', 19 | required=True, help='The sales\'s count', 20 | ) 21 | 22 | sales_record_post_parser.add_argument( 23 | 'seller_id', dest='seller_id', 24 | type=str, location='form', 25 | required=True, help='The sales\'s seller id', 26 | ) 27 | 28 | sales_record_post_parser.add_argument( 29 | 'book_id', dest='book_id', 30 | type=str, location='form', 31 | required=True, help='The sales\'s book id', 32 | ) 33 | 34 | sales_record_post_parser.add_argument( 35 | 'purchaser_id', dest='purchaser_id', 36 | type=str, location='form', 37 | required=False, help='The sales\'s purchaser id', 38 | ) 39 | -------------------------------------------------------------------------------- /RESTfulApi/utils/parsers/session.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | """ 5 | File name: session.py 6 | Function Des: ... 7 | ~~~~~~~~~~ 8 | 9 | author: Jerry 10 | 11 | """ 12 | from flask.ext.restful import reqparse 13 | 14 | 15 | # ------------ login parser ------------ 16 | login_parser = reqparse.RequestParser() 17 | login_parser.add_argument( 18 | 'username', dest='username', 19 | type=str, location='form', 20 | required=True, help='This is username', 21 | ) 22 | 23 | login_parser.add_argument( 24 | 'password', dest='password', 25 | type=str, location='form', 26 | required=True, help='This is password', 27 | ) 28 | -------------------------------------------------------------------------------- /RESTfulApi/utils/parsers/vip.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | """ 5 | File name: vip.py 6 | Function Des: ... 7 | ~~~~~~~~~~ 8 | 9 | author: Jerry 10 | 11 | """ 12 | from flask.ext.restful import reqparse 13 | 14 | 15 | # ------------ vip add parser ------------ 16 | vip_post_parser = reqparse.RequestParser() 17 | vip_post_parser.add_argument( 18 | 'username', dest='username', 19 | type=unicode, location='form', 20 | required=True, help='The vip\'s username', 21 | ) 22 | 23 | vip_post_parser.add_argument( 24 | 'nickname', dest='nickname', 25 | type=unicode, location='form', 26 | required=True, help='The vip\'s nickname', 27 | ) 28 | 29 | vip_post_parser.add_argument( 30 | 'phone', dest='phone', 31 | type=str, location='form', 32 | required=False, help='The vip\'s phone', 33 | ) 34 | -------------------------------------------------------------------------------- /config/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | """ 5 | File name: __init__.py 6 | Function Des: ... 7 | ~~~~~~~~~~ 8 | 9 | author: Jerry 10 | 11 | """ 12 | 13 | -------------------------------------------------------------------------------- /config/default.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | """ 5 | File name: default.py 6 | Function Des: ... 7 | ~~~~~~~~~~ 8 | 9 | author: Jerry 10 | 11 | """ 12 | 13 | MONGODB_SETTINGS = {'DB': 'library'} # 设置mongodb的数据库 14 | PASSWORD_SECRET = 'secret_for_ensure_password_security' 15 | TOKEN_SECRET = 'secret_for_ensure_token_security' 16 | -------------------------------------------------------------------------------- /run.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # encoding: utf-8 3 | 4 | """ 5 | File name: run.py 6 | Function Des: ... 7 | ~~~~~~~~~~ 8 | 9 | author: Jerry 10 | 11 | """ 12 | 13 | from flask import Flask, g 14 | from RESTfulApi.app import api_bp 15 | from RESTfulApi.models import register_database 16 | 17 | 18 | def create_app(**config): 19 | """ 20 | 创建并初始化一个 Flask App 21 | :param 22 | :return 23 | """ 24 | app = Flask(__name__) 25 | register_config(app, config) 26 | register_database(app) 27 | register_routes(app) 28 | return app 29 | 30 | 31 | def register_config(app, config): 32 | if config.get('debug') is True: 33 | app.debug = True 34 | 35 | from config import default 36 | app.config.from_object(default) 37 | 38 | 39 | def register_routes(app): 40 | app.register_blueprint(api_bp, url_prefix='/api') 41 | 42 | if __name__ == '__main__': 43 | create_app(debug=True).run() 44 | --------------------------------------------------------------------------------