+ 'django.contrib.messages.middleware.MessageMiddleware',
|
|
|
56
|
+ 'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
|
|
57
|
+ 'django.middleware.security.SecurityMiddleware',
|
|
|
58
|
+)
|
|
|
59
|
+
|
|
|
60
|
+ROOT_URLCONF = 'pai2.urls'
|
|
|
61
|
+
|
|
|
62
|
+TEMPLATES = [
|
|
|
63
|
+ {
|
|
|
64
|
+ 'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
|
|
65
|
+ 'DIRS': [],
|
|
|
66
|
+ 'APP_DIRS': True,
|
|
|
67
|
+ 'OPTIONS': {
|
|
|
68
|
+ 'context_processors': [
|
|
|
69
|
+ 'django.template.context_processors.debug',
|
|
|
70
|
+ 'django.template.context_processors.request',
|
|
|
71
|
+ 'django.contrib.auth.context_processors.auth',
|
|
|
72
|
+ 'django.contrib.messages.context_processors.messages',
|
|
|
73
|
+ ],
|
|
|
74
|
+ },
|
|
|
75
|
+ },
|
|
|
76
|
+]
|
|
|
77
|
+
|
|
|
78
|
+WSGI_APPLICATION = 'pai2.wsgi.application'
|
|
|
79
|
+
|
|
|
80
|
+
|
|
|
81
|
+# Database
|
|
|
82
|
+# https://docs.djangoproject.com/en/1.8/ref/settings/#databases
|
|
|
83
|
+
|
|
|
84
|
+DATABASES = {
|
|
|
85
|
+ 'default': {
|
|
|
86
|
+ 'ENGINE': 'django.db.backends.mysql',
|
|
|
87
|
+ 'NAME': 'pai2',
|
|
|
88
|
+ 'USER': 'root',
|
|
|
89
|
+ 'PASSWORD': '',
|
|
|
90
|
+ }
|
|
|
91
|
+}
|
|
|
92
|
+
|
|
|
93
|
+
|
|
|
94
|
+# Internationalization
|
|
|
95
|
+# https://docs.djangoproject.com/en/1.8/topics/i18n/
|
|
|
96
|
+
|
|
|
97
|
+LANGUAGE_CODE = 'zh_CN'
|
|
|
98
|
+
|
|
|
99
|
+TIME_ZONE = 'Asia/Shanghai'
|
|
|
100
|
+
|
|
|
101
|
+USE_I18N = True
|
|
|
102
|
+
|
|
|
103
|
+USE_L10N = True
|
|
|
104
|
+
|
|
|
105
|
+USE_TZ = True
|
|
|
106
|
+
|
|
|
107
|
+
|
|
|
108
|
+# Static files (CSS, JavaScript, Images)
|
|
|
109
|
+# https://docs.djangoproject.com/en/1.8/howto/static-files/
|
|
|
110
|
+
|
|
|
111
|
+STATICFILES_DIRS = (
|
|
|
112
|
+ os.path.join(PROJ_DIR, 'static').replace('\\', '/'),
|
|
|
113
|
+)
|
|
|
114
|
+
|
|
|
115
|
+STATIC_ROOT = os.path.join(BASE_DIR, 'collect_static').replace('\\', '/')
|
|
|
116
|
+
|
|
|
117
|
+STATIC_URL = '/static/'
|
|
|
118
|
+
|
|
|
119
|
+STATICFILES_FINDERS = (
|
|
|
120
|
+ 'django.contrib.staticfiles.finders.FileSystemFinder',
|
|
|
121
|
+ 'django.contrib.staticfiles.finders.AppDirectoriesFinder',
|
|
|
122
|
+ # 'django.contrib.staticfiles.finders.DefaultStorageFinder',
|
|
|
123
|
+)
|
|
|
124
|
+
|
|
|
125
|
+MEDIA_ROOT = os.path.join(BASE_DIR, 'media').replace('\\', '/')
|
|
|
126
|
+
|
|
|
127
|
+MEDIA_URL = '/media/'
|
|
|
128
|
+
|
|
|
129
|
+# REST_FRAMEWORK 设置
|
|
|
130
|
+# See http://www.django-rest-framework.org/#example
|
|
|
131
|
+REST_FRAMEWORK = {
|
|
|
132
|
+ # Use Django's standard `django.contrib.auth` permissions,
|
|
|
133
|
+ # or allow read-only access for unauthenticated users.
|
|
|
134
|
+ # 'DEFAULT_PERMISSION_CLASSES': [
|
|
|
135
|
+ # 'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly',
|
|
|
136
|
+ # ]
|
|
|
137
|
+ 'DEFAULT_PERMISSION_CLASSES': ('rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly',),
|
|
|
138
|
+ 'PAGE_SIZE': 1
|
|
|
139
|
+}
|
|
|
140
|
+
|
|
|
141
|
+# 域名设置
|
|
|
142
|
+DOMAIN = 'http://xfoto.com.cn'
|
|
|
143
|
+
|
|
|
144
|
+try:
|
|
|
145
|
+ from local_settings import *
|
|
|
146
|
+except ImportError:
|
|
|
147
|
+ pass
|
|
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+"""pai2 URL Configuration
|
|
|
2
|
+
|
|
|
3
|
+The `urlpatterns` list routes URLs to views. For more information please see:
|
|
|
4
|
+ https://docs.djangoproject.com/en/1.8/topics/http/urls/
|
|
|
5
|
+Examples:
|
|
|
6
|
+Function views
|
|
|
7
|
+ 1. Add an import: from my_app import views
|
|
|
8
|
+ 2. Add a URL to urlpatterns: url(r'^$', views.home, name='home')
|
|
|
9
|
+Class-based views
|
|
|
10
|
+ 1. Add an import: from other_app.views import Home
|
|
|
11
|
+ 2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home')
|
|
|
12
|
+Including another URLconf
|
|
|
13
|
+ 1. Add an import: from blog import urls as blog_urls
|
|
|
14
|
+ 2. Add a URL to urlpatterns: url(r'^blog/', include(blog_urls))
|
|
|
15
|
+"""
|
|
|
16
|
+from django.conf import settings
|
|
|
17
|
+from django.conf.urls import include, url
|
|
|
18
|
+from django.conf.urls.static import static
|
|
|
19
|
+from django.contrib import admin
|
|
|
20
|
+
|
|
|
21
|
+from rest_framework import routers
|
|
|
22
|
+from account import views as account_views
|
|
|
23
|
+from photo import views as photo_views
|
|
|
24
|
+
|
|
|
25
|
+router = routers.DefaultRouter()
|
|
|
26
|
+# router.register(r'users', account_views.UserViewSet)
|
|
|
27
|
+# router.register(r'groups', account_views.GroupViewSet)
|
|
|
28
|
+router.register(r'lensmans', account_views.LensmanInfoViewSet)
|
|
|
29
|
+router.register(r'photos', photo_views.PhotoInfoViewSet)
|
|
|
30
|
+
|
|
|
31
|
+urlpatterns = [
|
|
|
32
|
+ url(r'^pai2admin/', include(admin.site.urls)),
|
|
|
33
|
+]
|
|
|
34
|
+
|
|
|
35
|
+urlpatterns += [
|
|
|
36
|
+ url(r'^api/', include('api.urls', namespace='api')),
|
|
|
37
|
+ # url(r'^photo/', include('photo.urls', namespace='photo'))
|
|
|
38
|
+]
|
|
|
39
|
+
|
|
|
40
|
+# Wire up our API using automatic URL routing.
|
|
|
41
|
+# Additionally, we include login URLs for the browsable API.
|
|
|
42
|
+urlpatterns += [
|
|
|
43
|
+ url(r'^api/', include(router.urls)),
|
|
|
44
|
+ url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework'))
|
|
|
45
|
+]
|
|
|
46
|
+
|
|
|
47
|
+urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
|
|
|
48
|
+urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
|
|
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+# morefun_uwsgi.ini file
|
|
|
2
|
+[uwsgi]
|
|
|
3
|
+
|
|
|
4
|
+# Django-related settings
|
|
|
5
|
+# the base directory (full path)
|
|
|
6
|
+chdir = /home/paiai/work/pai2
|
|
|
7
|
+# Django's wsgi file
|
|
|
8
|
+module = pai2.wsgi
|
|
|
9
|
+# the virtualenv (full path)
|
|
|
10
|
+# home = /path/to/virtualenv
|
|
|
11
|
+
|
|
|
12
|
+# process-related settings
|
|
|
13
|
+# master
|
|
|
14
|
+master = true
|
|
|
15
|
+# maximum number of worker processes
|
|
|
16
|
+processes = 10
|
|
|
17
|
+# the socket (use the full path to be safe
|
|
|
18
|
+socket = /home/paiai/work/pai2/pai2/uwsgi/pai2.sock
|
|
|
19
|
+# ... with appropriate permissions - may be needed
|
|
|
20
|
+chmod-socket = 777
|
|
|
21
|
+# clear environment on exit
|
|
|
22
|
+vacuum = true
|
|
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+# pai2_nginx.conf
|
|
|
2
|
+
|
|
|
3
|
+# the upstream component nginx needs to connect to
|
|
|
4
|
+upstream pai2 {
|
|
|
5
|
+ # server unix:///home/paiai/work/pai2/pai2/uwsgi/pai2.sock; # for a file socket
|
|
|
6
|
+ server 127.0.0.1:8888; # for a web port socket (we'll use this first)
|
|
|
7
|
+}
|
|
|
8
|
+
|
|
|
9
|
+# configuration of the server
|
|
|
10
|
+server {
|
|
|
11
|
+ # the port your site will be served on
|
|
|
12
|
+ listen 80;
|
|
|
13
|
+ # the domain name it will serve for
|
|
|
14
|
+ server_name .xfoto.com.cn; # substitute your machine's IP address or FQDN
|
|
|
15
|
+ charset utf-8;
|
|
|
16
|
+
|
|
|
17
|
+ # max upload size
|
|
|
18
|
+ client_max_body_size 75M; # adjust to taste
|
|
|
19
|
+
|
|
|
20
|
+ # Django media
|
|
|
21
|
+ location /media {
|
|
|
22
|
+ alias /home/paiai/work/pai2/media; # your Django project's media files - amend as required
|
|
|
23
|
+ }
|
|
|
24
|
+
|
|
|
25
|
+ location /static {
|
|
|
26
|
+ alias /home/paiai/work/pai2/collect_static; # your Django project's static files - amend as required
|
|
|
27
|
+ }
|
|
|
28
|
+
|
|
|
29
|
+ # Finally, send all non-media requests to the Django server.
|
|
|
30
|
+ location / {
|
|
|
31
|
+ # uwsgi_pass pai2;
|
|
|
32
|
+ proxy_pass http://pai2;
|
|
|
33
|
+ include /home/paiai/work/pai2/pai2/uwsgi/uwsgi_params; # the uwsgi_params file you installed
|
|
|
34
|
+ }
|
|
|
35
|
+}
|
|
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+killall -9 uwsgi
|
|
|
2
|
+echo "2敏加油~~~!!!↖(^ω^)↗"
|
|
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+nohup uwsgi --ini pai2.ini &>pai2.log &
|
|
|
2
|
+echo "Start Success !!!"
|
|
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+uwsgi_param QUERY_STRING $query_string;
|
|
|
2
|
+uwsgi_param REQUEST_METHOD $request_method;
|
|
|
3
|
+uwsgi_param CONTENT_TYPE $content_type;
|
|
|
4
|
+uwsgi_param CONTENT_LENGTH $content_length;
|
|
|
5
|
+
|
|
|
6
|
+uwsgi_param REQUEST_URI $request_uri;
|
|
|
7
|
+uwsgi_param PATH_INFO $document_uri;
|
|
|
8
|
+uwsgi_param DOCUMENT_ROOT $document_root;
|
|
|
9
|
+uwsgi_param SERVER_PROTOCOL $server_protocol;
|
|
|
10
|
+uwsgi_param UWSGI_SCHEME $scheme;
|
|
|
11
|
+
|
|
|
12
|
+uwsgi_param REMOTE_ADDR $remote_addr;
|
|
|
13
|
+uwsgi_param REMOTE_PORT $remote_port;
|
|
|
14
|
+uwsgi_param SERVER_PORT $server_port;
|
|
|
15
|
+uwsgi_param SERVER_NAME $server_name;
|
|
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+from django.shortcuts import render
|
|
|
2
|
+
|
|
|
3
|
+# Create your views here.
|
|
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+"""
|
|
|
2
|
+WSGI config for pai2 project.
|
|
|
3
|
+
|
|
|
4
|
+It exposes the WSGI callable as a module-level variable named ``application``.
|
|
|
5
|
+
|
|
|
6
|
+For more information on this file, see
|
|
|
7
|
+https://docs.djangoproject.com/en/1.8/howto/deployment/wsgi/
|
|
|
8
|
+"""
|
|
|
9
|
+
|
|
|
10
|
+import os
|
|
|
11
|
+
|
|
|
12
|
+from django.core.wsgi import get_wsgi_application
|
|
|
13
|
+
|
|
|
14
|
+os.environ.setdefault("DJANGO_SETTINGS_MODULE", "pai2.settings")
|
|
|
15
|
+
|
|
|
16
|
+application = get_wsgi_application()
|
|
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+#!/bin/bash
|
|
|
2
|
+
|
|
|
3
|
+# Ignoring autogenerated files
|
|
|
4
|
+# -- Migration directories
|
|
|
5
|
+# Ignoring error codes
|
|
|
6
|
+# -- E128 continuation line under-indented for visual indent
|
|
|
7
|
+# -- E501 line too long
|
|
|
8
|
+
|
|
|
9
|
+pep8 --exclude=migrations --ignore=E128,E501 .
|
|
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+# -*- coding: utf-8 -*-
|
|
|
2
|
+
|
|
|
3
|
+from django.contrib import admin
|
|
|
4
|
+
|
|
|
5
|
+from photo.models import PhotosInfo
|
|
|
6
|
+
|
|
|
7
|
+
|
|
|
8
|
+class PhotosInfoAdmin(admin.ModelAdmin):
|
|
|
9
|
+ list_display = ('lensman_id', 'session_id', 'photo_id', 'photo_path', 'status', 'created_at', 'updated_at')
|
|
|
10
|
+ list_filter = ('lensman_id', 'status')
|
|
|
11
|
+
|
|
|
12
|
+
|
|
|
13
|
+admin.site.register(PhotosInfo, PhotosInfoAdmin)
|
|
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+# -*- coding: utf-8 -*-
|
|
|
2
|
+from __future__ import unicode_literals
|
|
|
3
|
+
|
|
|
4
|
+from django.db import models, migrations
|
|
|
5
|
+
|
|
|
6
|
+
|
|
|
7
|
+class Migration(migrations.Migration):
|
|
|
8
|
+
|
|
|
9
|
+ dependencies = [
|
|
|
10
|
+ ]
|
|
|
11
|
+
|
|
|
12
|
+ operations = [
|
|
|
13
|
+ migrations.CreateModel(
|
|
|
14
|
+ name='PhotosInfo',
|
|
|
15
|
+ fields=[
|
|
|
16
|
+ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
|
|
|
17
|
+ ('status', models.BooleanField(default=True, help_text='\u72b6\u6001', verbose_name='status')),
|
|
|
18
|
+ ('created_at', models.DateTimeField(help_text='\u521b\u5efa\u65f6\u95f4', verbose_name='created_at', auto_now_add=True)),
|
|
|
19
|
+ ('updated_at', models.DateTimeField(help_text='\u66f4\u65b0\u65f6\u95f4', verbose_name='updated_at', auto_now=True)),
|
|
|
20
|
+ ('lesman_id', models.CharField(max_length=255, blank=True, help_text='\u6444\u5f71\u5e08\u552f\u4e00\u6807\u8bc6', null=True, verbose_name='lesman_id', db_index=True)),
|
|
|
21
|
+ ('session_id', models.CharField(max_length=255, blank=True, help_text='\u7167\u7247\u7ec4\u552f\u4e00\u6807\u8bc6', null=True, verbose_name='session_id', db_index=True)),
|
|
|
22
|
+ ('photo_id', models.CharField(null=True, max_length=255, blank=True, help_text='\u7167\u7247\u552f\u4e00\u6807\u8bc6', unique=True, verbose_name='photo_id', db_index=True)),
|
|
|
23
|
+ ('photo_path', models.CharField(help_text='\u7167\u7247\u5b58\u653e\u8def\u5f84', max_length=255, null=True, verbose_name='photo_path', blank=True)),
|
|
|
24
|
+ ],
|
|
|
25
|
+ options={
|
|
|
26
|
+ 'verbose_name': 'photosinfo',
|
|
|
27
|
+ 'verbose_name_plural': 'photosinfo',
|
|
|
28
|
+ },
|
|
|
29
|
+ ),
|
|
|
30
|
+ migrations.AlterIndexTogether(
|
|
|
31
|
+ name='photosinfo',
|
|
|
32
|
+ index_together=set([('lesman_id', 'session_id')]),
|
|
|
33
|
+ ),
|
|
|
34
|
+ ]
|
|
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+# -*- coding: utf-8 -*-
|
|
|
2
|
+from __future__ import unicode_literals
|
|
|
3
|
+
|
|
|
4
|
+from django.db import models, migrations
|
|
|
5
|
+
|
|
|
6
|
+
|
|
|
7
|
+class Migration(migrations.Migration):
|
|
|
8
|
+
|
|
|
9
|
+ dependencies = [
|
|
|
10
|
+ ('photo', '0001_initial'),
|
|
|
11
|
+ ]
|
|
|
12
|
+
|
|
|
13
|
+ operations = [
|
|
|
14
|
+ migrations.AddField(
|
|
|
15
|
+ model_name='photosinfo',
|
|
|
16
|
+ name='lensman_id',
|
|
|
17
|
+ field=models.CharField(max_length=255, blank=True, help_text='\u6444\u5f71\u5e08\u552f\u4e00\u6807\u8bc6', null=True, verbose_name='lensman_id', db_index=True),
|
|
|
18
|
+ ),
|
|
|
19
|
+ migrations.AlterIndexTogether(
|
|
|
20
|
+ name='photosinfo',
|
|
|
21
|
+ index_together=set([('lensman_id', 'session_id')]),
|
|
|
22
|
+ ),
|
|
|
23
|
+ migrations.RemoveField(
|
|
|
24
|
+ model_name='photosinfo',
|
|
|
25
|
+ name='lesman_id',
|
|
|
26
|
+ ),
|
|
|
27
|
+ ]
|
|
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+# -*- coding: utf-8 -*-
|
|
|
2
|
+
|
|
|
3
|
+from django.conf import settings
|
|
|
4
|
+from django.db import models
|
|
|
5
|
+from django.utils.translation import ugettext_lazy as _
|
|
|
6
|
+
|
|
|
7
|
+from pai2.basemodels import CreateUpdateMixin
|
|
|
8
|
+
|
|
|
9
|
+
|
|
|
10
|
+class PhotosInfo(CreateUpdateMixin):
|
|
|
11
|
+ lensman_id = models.CharField(_(u'lensman_id'), max_length=255, blank=True, null=True, help_text=u'摄影师唯一标识', db_index=True)
|
|
|
12
|
+ session_id = models.CharField(_(u'session_id'), max_length=255, blank=True, null=True, help_text=u'照片组唯一标识', db_index=True)
|
|
|
13
|
+ photo_id = models.CharField(_(u'photo_id'), max_length=255, blank=True, null=True, help_text=u'照片唯一标识', db_index=True, unique=True)
|
|
|
14
|
+ photo_path = models.CharField(_(u'photo_path'), max_length=255, blank=True, null=True, help_text=u'照片存放路径')
|
|
|
15
|
+
|
|
|
16
|
+ class Meta:
|
|
|
17
|
+ verbose_name = _('photosinfo')
|
|
|
18
|
+ verbose_name_plural = _('photosinfo')
|
|
|
19
|
+ index_together = [
|
|
|
20
|
+ ['lensman_id', 'session_id'],
|
|
|
21
|
+ ]
|
|
|
22
|
+
|
|
|
23
|
+ def __unicode__(self):
|
|
|
24
|
+ return u'{0.pk}'.format(self)
|
|
|
25
|
+
|
|
|
26
|
+ @property
|
|
|
27
|
+ def photo_url(self):
|
|
|
28
|
+ return u'{0}/media/{1}'.format(settings.DOMAIN, self.photo_path) if self.photo_path else ''
|
|
|
29
|
+
|
|
|
30
|
+ def _data(self):
|
|
|
31
|
+ return {
|
|
|
32
|
+ 'pk': self.pk,
|
|
|
33
|
+ 'lensman_id': self.lensman_id,
|
|
|
34
|
+ 'session_id': self.session_id,
|
|
|
35
|
+ 'photo_id': self.photo_id,
|
|
|
36
|
+ 'photo_url': self.photo_url,
|
|
|
37
|
+ }
|
|
|
38
|
+
|
|
|
39
|
+ data = property(_data)
|
|
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+# -*- coding: utf-8 -*-
|
|
|
2
|
+
|
|
|
3
|
+from photo.models import PhotosInfo
|
|
|
4
|
+from rest_framework import serializers
|
|
|
5
|
+
|
|
|
6
|
+
|
|
|
7
|
+class PhotosInfoSerializer(serializers.HyperlinkedModelSerializer):
|
|
|
8
|
+ class Meta:
|
|
|
9
|
+ model = PhotosInfo
|
|
|
10
|
+ fields = ('lensman_id', 'session_id', 'photo_id', 'photo_path', 'created_at')
|
|
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+from django.test import TestCase
|
|
|
2
|
+
|
|
|
3
|
+# Create your tests here.
|
|
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+# -*- coding: utf-8 -*-
|
|
|
2
|
+
|
|
|
3
|
+from django.core.files.storage import default_storage
|
|
|
4
|
+from django.http import JsonResponse
|
|
|
5
|
+
|
|
|
6
|
+from rest_framework import viewsets
|
|
|
7
|
+
|
|
|
8
|
+from account.models import LensmanInfo
|
|
|
9
|
+from photo.models import PhotosInfo
|
|
|
10
|
+from photo.serializers import PhotosInfoSerializer
|
|
|
11
|
+
|
|
|
12
|
+import os
|
|
|
13
|
+
|
|
|
14
|
+
|
|
|
15
|
+# [How to do a PUT request with curl?](http://stackoverflow.com/questions/13782198/how-to-do-a-put-request-with-curl)
|
|
|
16
|
+# Unfortunately, the -T is no substitute for -X PUT if you want to specify parameters with -d or -F.
|
|
|
17
|
+# -T sends the content of a file via PUT. To achieve the GET after a redirect, add the parameter --location
|
|
|
18
|
+#
|
|
|
19
|
+# -F, --form <name=content>
|
|
|
20
|
+# (HTTP) This lets curl emulate a filled-in form in which a user has pressed the submit button. This causes curl to POST data
|
|
|
21
|
+# using the Content-Type multipart/form-data according to RFC 2388. This enables uploading of binary files etc. To force the
|
|
|
22
|
+# 'content' part to be a file, prefix the file name with an @ sign. To just get the content part from a file, prefix the file
|
|
|
23
|
+# name with the symbol <. The difference between @ and < is then that @ makes a file get attached in the post as a file upload,
|
|
|
24
|
+# while the < makes a text field and just get the contents for that text field from a file.
|
|
|
25
|
+#
|
|
|
26
|
+# curl -X POST -F lensman_id=123 -F session_id=456 -F photo_id=789 -F photo=@7056288a9ddf2db294cf50a943920989.jpg;filename=789 http://xfoto.com.cn/api/photos/upload
|
|
|
27
|
+def upload_photo(request):
|
|
|
28
|
+ lensman_id = request.POST.get('lensman_id', '')
|
|
|
29
|
+ session_id = request.POST.get('session_id', '')
|
|
|
30
|
+ photo_id = request.POST.get('photo_id', '')
|
|
|
31
|
+
|
|
|
32
|
+ photo = request.FILES.get('photo', '')
|
|
|
33
|
+
|
|
|
34
|
+ if not (lensman_id and session_id and photo_id and photo):
|
|
|
35
|
+ return JsonResponse({
|
|
|
36
|
+ 'status': 400,
|
|
|
37
|
+ 'message': u'参数错误',
|
|
|
38
|
+ })
|
|
|
39
|
+
|
|
|
40
|
+ try:
|
|
|
41
|
+ LensmanInfo.objects.get(lensman_id=lensman_id)
|
|
|
42
|
+ except LensmanInfo.DoesNotExist:
|
|
|
43
|
+ return JsonResponse({
|
|
|
44
|
+ 'status': 400,
|
|
|
45
|
+ 'message': u'参数错误',
|
|
|
46
|
+ })
|
|
|
47
|
+
|
|
|
48
|
+ _, extension = os.path.splitext(photo.name)
|
|
|
49
|
+ photo_path = 'photo/{0}/{1}/{2}{3}'.format(lensman_id, session_id, photo_id, extension)
|
|
|
50
|
+
|
|
|
51
|
+ if default_storage.exists(photo_path):
|
|
|
52
|
+ default_storage.delete(photo_path)
|
|
|
53
|
+ default_storage.save(photo_path, photo)
|
|
|
54
|
+
|
|
|
55
|
+ photo, created = PhotosInfo.objects.get_or_create(
|
|
|
56
|
+ lensman_id=lensman_id,
|
|
|
57
|
+ session_id=session_id,
|
|
|
58
|
+ photo_id=photo_id,
|
|
|
59
|
+ photo_path=photo_path
|
|
|
60
|
+ )
|
|
|
61
|
+
|
|
|
62
|
+ return JsonResponse({
|
|
|
63
|
+ 'status': 200,
|
|
|
64
|
+ 'message': u'照片上传成功',
|
|
|
65
|
+ 'data': photo.data,
|
|
|
66
|
+ })
|
|
|
67
|
+
|
|
|
68
|
+
|
|
|
69
|
+class PhotoInfoViewSet(viewsets.ModelViewSet):
|
|
|
70
|
+ queryset = PhotosInfo.objects.all().order_by('-created_at')
|
|
|
71
|
+ serializer_class = PhotosInfoSerializer
|
|
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+CodeConvert==2.0.3
|
|
|
2
|
+Django==1.8.4
|
|
|
3
|
+MySQL-python==1.2.5
|
|
|
4
|
+TimeConvert==1.0.7
|
|
|
5
|
+django-shortuuidfield==0.1.3
|
|
|
6
|
+djangorestframework==3.3.1
|
|
|
7
|
+ipdb==0.8.1
|
|
|
8
|
+ipython==4.0.0
|
|
|
9
|
+pep8==1.6.2
|
|
|
10
|
+pillow==2.9.0
|
|
|
11
|
+pytz==2015.7
|
|
|
12
|
+uWSGI==2.0.11.1
|