es-num lines-num-old"> 12
+    MALE = 0
13
+    FEMALE = 1
14
+
15
+    SEX_TYPE = (
16
+        (MALE, u'男'),
17
+        (FEMALE, u'女'),
18
+    )
19
+
20
+    lensman_id = ShortUUIDField(_(u'lensman_id'), max_length=255, help_text=u'摄影师唯一标识', db_index=True)
21
+    name = models.CharField(_(u'name'), max_length=255, blank=True, null=True, help_text=u'摄影师姓名')
22
+    sex = models.IntegerField(_(u'sex'), choices=SEX_TYPE, default=MALE, help_text=u'摄影师性别')
23
+    phone = models.CharField(_(u'phone'), max_length=255, blank=True, null=True, help_text=u'摄影师电话', db_index=True, unique=True)
24
+    location = models.CharField(_(u'location'), max_length=255, blank=True, null=True, help_text=u'摄影师地址')
25
+
26
+    proportion = models.FloatField(_(u'proportion'), default=1.0, help_text=u'摄影师分成比例(0.0 ~ 1.0)')
27
+
28
+    class Meta:
29
+        verbose_name = _(u'lensmaninfo')
30
+        verbose_name_plural = _(u'lensmaninfo')
31
+
32
+    def __unicode__(self):
33
+        return unicode(self.pk)

+ 24 - 0
account/serializers.py

@@ -0,0 +1,24 @@
1
+# -*- coding: utf-8 -*-
2
+
3
+from django.contrib.auth.models import User, Group
4
+from rest_framework import serializers
5
+
6
+from account.models import LensmanInfo
7
+
8
+
9
+class UserSerializer(serializers.HyperlinkedModelSerializer):
10
+    class Meta:
11
+        model = User
12
+        fields = ('url', 'username', 'email', 'groups')
13
+
14
+
15
+class GroupSerializer(serializers.HyperlinkedModelSerializer):
16
+    class Meta:
17
+        model = Group
18
+        fields = ('url', 'name')
19
+
20
+
21
+class LensmanInfoSerializer(serializers.HyperlinkedModelSerializer):
22
+    class Meta:
23
+        model = LensmanInfo
24
+        fields = ('lensman_id', 'name', 'sex', 'phone', 'location', 'proportion', 'created_at')

+ 3 - 0
account/tests.py

@@ -0,0 +1,3 @@
1
+from django.test import TestCase
2
+
3
+# Create your tests here.

+ 28 - 0
account/views.py

@@ -0,0 +1,28 @@
1
+# -*- coding: utf-8 -*-
2
+
3
+from django.contrib.auth.models import User, Group
4
+from rest_framework import viewsets
5
+
6
+from account.models import LensmanInfo
7
+from account.serializers import UserSerializer, GroupSerializer, LensmanInfoSerializer
8
+
9
+
10
+class UserViewSet(viewsets.ModelViewSet):
11
+    """
12
+    API endpoint that allows users to be viewed or edited.
13
+    """
14
+    queryset = User.objects.all().order_by('-date_joined')
15
+    serializer_class = UserSerializer
16
+
17
+
18
+class GroupViewSet(viewsets.ModelViewSet):
19
+    """
20
+    API endpoint that allows groups to be viewed or edited.
21
+    """
22
+    queryset = Group.objects.all()
23
+    serializer_class = GroupSerializer
24
+
25
+
26
+class LensmanInfoViewSet(viewsets.ModelViewSet):
27
+    queryset = LensmanInfo.objects.all().order_by('-created_at')
28
+    serializer_class = LensmanInfoSerializer

+ 0 - 0
api/__init__.py


+ 3 - 0
api/admin.py

@@ -0,0 +1,3 @@
1
+from django.contrib import admin
2
+
3
+# Register your models here.

+ 0 - 0
api/migrations/__init__.py


+ 3 - 0
api/models.py

@@ -0,0 +1,3 @@
1
+from django.db import models
2
+
3
+# Create your models here.

+ 3 - 0
api/tests.py

@@ -0,0 +1,3 @@
1
+from django.test import TestCase
2
+
3
+# Create your tests here.

+ 10 - 0
api/urls.py

@@ -0,0 +1,10 @@
1
+# -*- coding: utf-8 -*-
2
+
3
+from django.conf.urls import url
4
+
5
+from photo import views as photo_views
6
+
7
+
8
+urlpatterns = [
9
+    url(r'^photos/upload$', photo_views.upload_photo, name='upload_photo'),
10
+]

+ 3 - 0
api/views.py

@@ -0,0 +1,3 @@
1
+from django.shortcuts import render
2
+
3
+# Create your views here.

+ 10 - 0
manage.py

@@ -0,0 +1,10 @@
1
+#!/usr/bin/env python
2
+import os
3
+import sys
4
+
5
+if __name__ == "__main__":
6
+    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "pai2.settings")
7
+
8
+    from django.core.management import execute_from_command_line
9
+
10
+    execute_from_command_line(sys.argv)

+ 0 - 0
pai2/__init__.py


+ 14 - 0
pai2/basemodels.py

@@ -0,0 +1,14 @@
1
+#!/usr/bin/env python
2
+# -*- coding: utf-8 -*-
3
+
4
+from django.db import models
5
+from django.utils.translation import ugettext_lazy as _
6
+
7
+
8
+class CreateUpdateMixin(models.Model):
9
+    status = models.BooleanField(_(u'status'), default=True, help_text=_(u'状态'))
10
+    created_at = models.DateTimeField(_(u'created_at'), auto_now_add=True, editable=True, help_text=_(u'创建时间'))
11
+    updated_at = models.DateTimeField(_(u'updated_at'), auto_now=True, editable=True, help_text=_(u'更新时间'))
12
+
13
+    class Meta:
14
+        abstract = True

+ 147 - 0
pai2/settings.py

@@ -0,0 +1,147 @@
1
+# -*- coding: utf-8 -*-
2
+
3
+"""
4
+Django settings for pai2 project.
5
+
6
+Generated by 'django-admin startproject' using Django 1.8.4.
7
+
8
+For more information on this file, see
9
+https://docs.djangoproject.com/en/1.8/topics/settings/
10
+
11
+For the full list of settings and their values, see
12
+https://docs.djangoproject.com/en/1.8/ref/settings/
13
+"""
14
+
15
+# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
16
+import os
17
+
18
+BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
19
+PROJ_DIR = os.path.abspath(os.path.dirname(os.path.abspath(__file__)))
20
+
21
+
22
+# Quick-start development settings - unsuitable for production
23
+# See https://docs.djangoproject.com/en/1.8/howto/deployment/checklist/
24
+
25
+# SECURITY WARNING: keep the secret key used in production secret!
26
+SECRET_KEY = 'aam6@6bh17d87bn-ax1@mcdrtbfm02y)_twd&!ewrr2^4581!c'
27
+
28
+# SECURITY WARNING: don't run with debug turned on in production!
29
+DEBUG = True
30
+
31
+ALLOWED_HOSTS = []
32
+
33
+
34
+# Application definition
35
+
36
+INSTALLED_APPS = (
37
+    'django.contrib.admin',
38
+    'django.contrib.auth',
39
+    'django.contrib.contenttypes',
40
+    'django.contrib.sessions',
41
+    'django.contrib.messages',
42
+    'django.contrib.staticfiles',
43
+    'rest_framework',
44
+    'api',
45
+    'account',
46
+    'photo',
47
+)
48
+
49
+MIDDLEWARE_CLASSES = (
50
+    'django.contrib.sessions.middleware.SessionMiddleware',
51
+    'django.middleware.common.CommonMiddleware',
52
+    # 'django.middleware.csrf.CsrfViewMiddleware',
53
+    'django.contrib.auth.middleware.AuthenticationMiddleware',
54
+    'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
55
+    '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

+ 48 - 0
pai2/urls.py

@@ -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)

+ 22 - 0
pai2/uwsgi.bak/pai2.ini

@@ -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

+ 35 - 0
pai2/uwsgi.bak/pai2_nginx.conf

@@ -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
+}

+ 2 - 0
pai2/uwsgi.bak/shutdown.sh

@@ -0,0 +1,2 @@
1
+killall -9 uwsgi
2
+echo "2敏加油~~~!!!↖(^ω^)↗"

+ 2 - 0
pai2/uwsgi.bak/startup.sh

@@ -0,0 +1,2 @@
1
+nohup uwsgi --ini pai2.ini &>pai2.log &
2
+echo "Start Success !!!"

+ 15 - 0
pai2/uwsgi.bak/uwsgi_params

@@ -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;

+ 3 - 0
pai2/views.py

@@ -0,0 +1,3 @@
1
+from django.shortcuts import render
2
+
3
+# Create your views here.

+ 16 - 0
pai2/wsgi.py

@@ -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()

+ 9 - 0
pep8.sh

@@ -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
photo/__init__.py


+ 13 - 0
photo/admin.py

@@ -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)

+ 34 - 0
photo/migrations/0001_initial.py

@@ -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
+    ]

+ 27 - 0
photo/migrations/0002_auto_20151113_1419.py

@@ -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
photo/migrations/__init__.py


+ 39 - 0
photo/models.py

@@ -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)

+ 10 - 0
photo/serializers.py

@@ -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')

+ 3 - 0
photo/tests.py

@@ -0,0 +1,3 @@
1
+from django.test import TestCase
2
+
3
+# Create your tests here.

+ 0 - 0
photo/urls.py


+ 71 - 0
photo/views.py

@@ -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

+ 12 - 0
requirements.txt

@@ -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

kodo - Gogs: Go Git Service

No Description

models.py 26KB

    # -*- coding: utf-8 -*- from django.db import models from django.utils.translation import ugettext_lazy as _ from django_models_ext import BaseModelMixin, SexModelMixin from jsonfield import JSONField from TimeConvert import TimeConvert as tc from kodo.basemodels import LensmanTypeBoolMixin from mch.models import MaintenancemanInfo, SaleclerkInfo, ConsumeInfoSubmitLogInfo from sales.models import SalesResponsibilityInfo class LensmanInfo(BaseModelMixin, LensmanTypeBoolMixin): MALE = 1 FEMALE = 0 SEX_TYPE = ( (MALE, u'男'), (FEMALE, u'女'), ) REFUSED = -1 UNVERIFIED = 0 ACTIVATED = 1 DISABLED = 2 DELETED = 3 ASSIGN = 10 USER_STATUS = ( (REFUSED, u'已拒绝'), (UNVERIFIED, u'未验证'), (ACTIVATED, u'已激活'), (DISABLED, u'已禁用'), (DELETED, u'已删除'), (ASSIGN, u'已分配'), ) lensman_id = models.CharField(_(u'lensman_id'), max_length=32, blank=True, null=True, help_text=u'摄影师唯一标识', db_index=True, unique=True) unionid = models.CharField(_(u'unionid'), max_length=32, blank=True, null=True, help_text=u'微信 Union ID', db_index=True, unique=True) username = models.CharField(_(u'username'), max_length=255, blank=True, null=True, help_text=u'摄影师用户名', db_index=True, unique=True) password = models.CharField(_(u'password'), max_length=255, blank=True, null=True, help_text=u'摄影师密码') encryption = models.CharField(_(u'encryption'), max_length=255, blank=True, null=True, help_text=u'摄影师密码') name = models.CharField(_(u'name'), max_length=255, blank=True, null=True, help_text=u'摄影师姓名') sex = models.IntegerField(_(u'sex'), choices=SexModelMixin.SEX_TUPLE, default=SexModelMixin.UNKNOWN, help_text=u'摄影师性别') phone = models.CharField(_(u'phone'), max_length=11, blank=True, null=True, help_text=u'摄影师电话', db_index=True) location = models.CharField(_(u'location'), max_length=255, blank=True, null=True, help_text=u'摄影师地址') proportion = models.FloatField(_(u'proportion'), default=1.0, help_text=u'摄影师分成比例(0.0 ~ 1.0)') nomark = models.IntegerField(_(u'nomark'), default=299, help_text=u'摄影师无水印价格(分)') origin = models.IntegerField(_(u'origin'), default=999, help_text=u'摄影师高清图价格(分)') balance = models.IntegerField(_(u'balance'), default=0, help_text=u'摄影师余额(分)') freeze_income_balance = models.IntegerField(_(u'freeze_income_balance'), default=0, help_text=u'摄影师收入冻结余额(分)') freeze_expense_balance = models.IntegerField(_(u'freeze_expense_balance'), default=0, help_text=u'摄影师支出冻结余额(分)') user_status = models.IntegerField(_(u'user_status'), choices=USER_STATUS, default=UNVERIFIED, help_text=u'普通摄影师审核状态') outtake_status = models.IntegerField(_(u'outtake_status'), choices=USER_STATUS, default=UNVERIFIED, help_text=u'花絮摄影师审核状态') refused_reason = models.TextField(_(u'refused_reason'), blank=True, null=True, help_text=u'审核拒绝原因') signup_ip = models.CharField(_(u'signup_ip'), max_length=32, blank=True, null=True, help_text=_(u'注册IP')) login_ip = models.CharField(_(u'login_ip'), max_length=32, blank=True, null=True, help_text=_(u'登录IP')) login_at = models.DateTimeField(_(u'login_at'), blank=True, null=True, help_text=_(u'登录时间')) class Meta: verbose_name = _(u'lensmaninfo') verbose_name_plural = _(u'lensmaninfo') def __unicode__(self): return unicode(self.pk) def final_status(self, lensman_type): if lensman_type == self.COMMON: # 普通摄影师校验 return self.user_status elif lensman_type == self.OUTTAKE: # 花絮摄影师校验 return self.outtake_status return self.user_status def data(self, lensman_type): return { 'name': self.name, 'sex': self.sex, 'phone': self.phone, 'location': self.location, 'status': self.final_status(lensman_type), 'refused_reason': self.refused_reason, } def modified(self, lensman_type): if lensman_type == self.COMMON: # 普通摄影师校验 return self.user_status in [self.UNVERIFIED, self.REFUSED] elif lensman_type == self.OUTTAKE: # 花絮摄影师校验 return self.outtake_status in [self.UNVERIFIED, self.REFUSED] return False class LensmanLoginLogInfo(BaseModelMixin): SUCCESS = 0 PWD_ERROR = 1 OTHER = 2 LOGIN_RESULT = ( (SUCCESS, u'登录成功'), (PWD_ERROR, u'密码错误'), (OTHER, u'其他'), ) lensman_id = models.CharField(_(u'lensman_id'), max_length=32, blank=True, null=True, help_text=u'摄影师唯一标识', db_index=True) login_ip = models.CharField(_(u'login_ip'), max_length=32, blank=True, null=True, help_text=_(u'登录IP')) login_result = models.IntegerField(_(u'login_result'), choices=LOGIN_RESULT, default=SUCCESS) class Meta: verbose_name = _(u'lensmanloginloginfo') verbose_name_plural = _(u'lensmanloginloginfo') def __unicode__(self): return unicode(self.pk) class LensmanIncomeExpensesInfo(BaseModelMixin): INCOME = 0 EXPENSE = 1 UNFREEZE = 2 TYPE = ( (INCOME, u'收入'), (EXPENSE, u'支出'), (UNFREEZE, u'解冻'), ) lensman_id = models.CharField(_(u'lensman_id'), max_length=32, blank=True, null=True, help_text=u'摄影师唯一标识', db_index=True) photo_id = models.CharField(_(u'photo_id'), max_length=32, blank=True, null=True, help_text=u'照片唯一标识', db_index=True) type = models.IntegerField(_(u'type'), choices=TYPE, default=INCOME, help_text=u'收支类别') amount = models.IntegerField(_(u'amount'), default=0, help_text=u'余额增减数量(分)') balance = models.IntegerField(_(u'balance'), default=0, help_text=u'余额增减后数量(分)') freeze_income_amount = models.IntegerField(_(u'freeze_income_amount'), default=0, help_text=u'收入冻结余额增减数量(分)') freeze_income_balance = models.IntegerField(_(u'freeze_income_balance'), default=0, help_text=u'收入冻结余额增减后数量(分)') freeze_expense_amount = models.IntegerField(_(u'freeze_expense_amount'), default=0, help_text=u'支出冻结余额增减数量(分)') freeze_expense_balance = models.IntegerField(_(u'freeze_expense_balance'), default=0, help_text=u'支出冻结余额增减后数量(分)') remark = models.CharField(_(u'remark'), max_length=255, blank=True, null=True, help_text=u'备注') class Meta: verbose_name = _(u'lensmanincomeexpensesinfo') verbose_name_plural = _(u'lensmanincomeexpensesinfo') def __unicode__(self): return unicode(self.pk) class TourGuideInfo(BaseModelMixin): MALE = 1 FEMALE = 0 SEX_TYPE = ( (MALE, u'男'), (FEMALE, u'女'), ) REFUSED = -1 UNVERIFIED = 0 ACTIVATED = 1 DISABLED = 2 DELETED = 3 ASSIGN = 10 USER_STATUS = ( (REFUSED, u'已拒绝'), (UNVERIFIED, u'未验证'), (ACTIVATED, u'已激活'), (DISABLED, u'已禁用'), (DELETED, u'已删除'), (ASSIGN, u'已分配'), ) tourguide_id = models.CharField(_(u'tourguide_id'), max_length=32, blank=True, null=True, help_text=u'导游唯一标识', db_index=True, unique=True) unionid = models.CharField(_(u'unionid'), max_length=32, blank=True, null=True, help_text=u'微信 Union ID', db_index=True, unique=True) name = models.CharField(_(u'name'), max_length=255, blank=True, null=True, help_text=u'导游姓名') sex = models.IntegerField(_(u'sex'), choices=SexModelMixin.SEX_TUPLE, default=SexModelMixin.UNKNOWN, help_text=u'导游性别') phone = models.CharField(_(u'phone'), max_length=11, blank=True, null=True, help_text=u'导游电话', db_index=True) location = models.CharField(_(u'location'), max_length=255, blank=True, null=True, help_text=u'导游地址') no = models.CharField(_(u'no'), max_length=16, blank=True, null=True, help_text=u'导游证编号') user_status = models.IntegerField(_(u'user_status'), choices=USER_STATUS, default=UNVERIFIED) refused_reason = models.TextField(_(u'refused_reason'), blank=True, null=True, help_text=u'审核拒绝原因') class Meta: verbose_name = _(u'tourguideinfo') verbose_name_plural = _(u'tourguideinfo') def __unicode__(self): return unicode(self.pk) @property def photo_url(self): return '' @property def data(self): return { 'name': self.name, 'sex': self.sex, 'phone': self.phone, 'location': self.location, 'no': self.no, 'photo': self.photo_url, 'status': self.user_status, 'refused_reason': self.refused_reason, } @property def modified(self): return self.user_status in [self.UNVERIFIED, self.REFUSED] class WechatInfo(BaseModelMixin): MALE = 1 FEMALE = 0 SEX_TYPE = ( (MALE, u'男'), (FEMALE, u'女'), ) unionid = models.CharField(_(u'unionid'), max_length=32, blank=True, null=True, help_text=u'微信 Union ID') openids = JSONField(_(u'openids'), blank=True, null=True, help_text=u'微信 Open IDs') sex = models.IntegerField(_(u'sex'), choices=SexModelMixin.SEX_TUPLE, default=SexModelMixin.UNKNOWN, help_text=u'用户性别') nickname = models.CharField(_(u'nickname'), max_length=255, blank=True, null=True, help_text=u'用户昵称') headimgurl = models.CharField(_(u'headimgurl'), max_length=255, blank=True, null=True, help_text=u'用户头像') country = models.CharField(_(u'country'), max_length=255, blank=True, null=True, help_text=u'用户国家') province = models.CharField(_(u'province'), max_length=255, blank=True, null=True, help_text=u'用户省份') city = models.CharField(_(u'city'), max_length=255, blank=True, null=True, help_text=u'用户城市') location = models.CharField(_(u'location'), max_length=255, blank=True, null=True, help_text=u'用户地址') class Meta: verbose_name = _(u'wechatinfo') verbose_name_plural = _(u'wechatinfo') def __unicode__(self): return unicode(self.pk) class UserInfo(BaseModelMixin, LensmanTypeBoolMixin): APP_USER = 0 WX_USER = 1 USER_USER = 8 GUEST_USER = 9 LENSMAN_USER = 10 TOURGUIDE_USER = 11 MINIAPP_USER = 12 QYMINIAPP_USER = 22 OAUTH_USER = 13 USER_FROM = ( (APP_USER, u'APP 创建用户'), (WX_USER, u'微信授权用户'), (USER_USER, u'用户端用户'), (GUEST_USER, u'游客用户'), (LENSMAN_USER, u'摄影师端用户'), (TOURGUIDE_USER, u'导游端用户'), (MINIAPP_USER, u'小程序端用户'), (QYMINIAPP_USER, u'企业微信小程序端用户'), (OAUTH_USER, u'网页授权用户'), ) UNVERIFIED = 0 ACTIVATED = 1 DISABLED = 2 DELETED = 3 ASSIGN = 10 USER_STATUS = ( (UNVERIFIED, u'未验证'), (ACTIVATED, u'已激活'), (DISABLED, u'已禁用'), (DELETED, u'已删除'), (ASSIGN, u'已分配'), ) MALE = 1 FEMALE = 0 SEX_TYPE = ( (MALE, u'男'), (FEMALE, u'女'), ) MEMBER_NO = 0 MEMBER_LRC = 1 MEMBER_SILVER = 2 MEMBER_GOLD = 3 MEMBER_WHITE_GOLD = 4 MEMBER_BLACK_GOLD = 5 LEVEL_TUPLE = ( (MEMBER_NO, u'非会员'), (MEMBER_LRC, u'LRC会员'), (MEMBER_SILVER, u'银卡会员'), (MEMBER_GOLD, u'金卡会员'), (MEMBER_WHITE_GOLD, u'白金卡会员'), (MEMBER_BLACK_GOLD, u'黑金卡会员'), ) user_id = models.CharField(_(u'user_id'), max_length=32, blank=True, null=True, help_text=u'用户唯一标识', db_index=True, unique=True) user_from = models.IntegerField(_(u'user_from'), choices=USER_FROM, default=APP_USER, help_text=u'用户来源', db_index=True) uuid = models.CharField(_(u'uuid'), max_length=255, blank=True, null=True, help_text=u'通用唯一识别码 (Universally Unique Identifier)', db_index=True) # APP 创建用户 username = models.CharField(_(u'username'), max_length=255, blank=True, null=True, help_text=u'用户用户名', db_index=True, unique=True) password = models.CharField(_(u'password'), max_length=255, blank=True, null=True, help_text=u'用户密码') # 微信授权用户 appid = models.CharField(_(u'appid'), max_length=32, blank=True, null=True, help_text=u'appId', db_index=True) unionid = models.CharField(_(u'unionid'), max_length=32, blank=True, null=True, help_text=u'微信 Unionid', db_index=True, unique=True) openid = models.CharField(_(u'openid'), max_length=32, blank=True, null=True, help_text=u'微信 Openid', db_index=True, unique=True) openid_lensman = models.CharField(_(u'openid_lensman'), max_length=32, blank=True, null=True, help_text=u'微信 Openid', db_index=True, unique=True) openid_tourguide = models.CharField(_(u'openid_tourguide'), max_length=32, blank=True, null=True, help_text=u'微信 Openid', db_index=True, unique=True) openid_miniapp = models.CharField(_(u'openid_miniapp'), max_length=32, blank=True, null=True, help_text=u'微信 Openid', db_index=True, unique=True) openid_oauth = models.CharField(_(u'openid_oauth'), max_length=32, blank=True, null=True, help_text=u'微信 Openid', db_index=True, unique=True) # 企业微信授权用户 userid = models.CharField(_(u'userid'), max_length=32, blank=True, null=True, help_text=u'企业微信 userid', db_index=True) # 用户基本信息 name = models.CharField(_(u'name'), max_length=255, blank=True, null=True, help_text=u'用户姓名') sex = models.IntegerField(_(u'sex'), choices=SexModelMixin.SEX_TUPLE, default=SexModelMixin.UNKNOWN, help_text=u'用户性别') nickname = models.CharField(_(u'nickname'), max_length=255, blank=True, null=True, help_text=u'用户昵称') avatar = models.CharField(_(u'avatar'), max_length=255, blank=True, null=True, help_text=u'用户头像') phone = models.CharField(_(u'phone'), max_length=11, blank=True, null=True, help_text=u'用户电话', db_index=True) country = models.CharField(_(u'country'), max_length=255, blank=True, null=True, help_text=u'用户国家') province = models.CharField(_(u'province'), max_length=255, blank=True, null=True, help_text=u'用户省份') city = models.CharField(_(u'city'), max_length=255, blank=True, null=True, help_text=u'用户城市') location = models.CharField(_(u'location'), max_length=255, blank=True, null=True, help_text=u'用户地址') province_code = models.CharField(_(u'province_code'), max_length=255, blank=True, null=True, help_text=u'用户省份编码') province_name = models.CharField(_(u'province_name'), max_length=255, blank=True, null=True, help_text=u'用户省份信息') # 用户身份 islensman = models.BooleanField(_(u'islensman'), default=False, help_text=_(u'摄影师?'), db_index=True) istourguide = models.BooleanField(_(u'istourguide'), default=False, help_text=_(u'导游?'), db_index=True) balance = models.IntegerField(_(u'balance'), default=0, help_text=u'用户余额(分)') freeze_income_balance = models.IntegerField(_(u'freeze_income_balance'), default=0, help_text=u'用户收入冻结余额(分)') freeze_expense_balance = models.IntegerField(_(u'freeze_expense_balance'), default=0, help_text=u'用户支出冻结余额(分)') user_status = models.IntegerField(_(u'user_status'), choices=USER_STATUS, default=UNVERIFIED, help_text=u'用户状态') outtake_status = models.IntegerField(_(u'outtake_status'), choices=USER_STATUS, default=UNVERIFIED, help_text=u'花絮摄影师状态') assign_ip = models.CharField(_(u'assign_ip'), max_length=32, blank=True, null=True, help_text=_(u'分配IP')) assign_at = models.DateTimeField(_(u'assign_at'), blank=True, null=True, help_text=_(u'分配时间')) signup_ip = models.CharField(_(u'signup_ip'), max_length=32, blank=True, null=True, help_text=_(u'注册IP')) signup_at = models.DateTimeField(_(u'signup_at'), blank=True, null=True, help_text=_(u'注册时间')) login_ip = models.CharField(_(u'login_ip'), max_length=32, blank=True, null=True, help_text=_(u'登录IP')) login_at = models.DateTimeField(_(u'login_at'), blank=True, null=True, help_text=_(u'登录时间')) subscribe = models.IntegerField(_(u'subscribe'), default=0, help_text=u'是否关注', db_index=True) new_subscribe = models.BooleanField(_(u'new_subscribe'), default=False, help_text=_(u'是否新增关注'), db_index=True) code_version = models.IntegerField(_(u'code_version'), default=1, help_text=u'统览码版本', db_index=True) has_membercard = models.BooleanField(_(u'has_membercard'), default=False, help_text=_(u'是否激活会员卡'), db_index=True) membercardid = models.CharField(_(u'membercardid'), max_length=32, blank=True, null=True, help_text=_(u'会员卡编号'), db_index=True) memberusercardcode = models.CharField(_(u'memberusercardcode'), max_length=32, blank=True, null=True, help_text=_(u'用户会员卡编号'), db_index=True) test_user = models.BooleanField(_(u'test_user'), default=False, help_text=_(u'是否为测试用户'), db_index=True) # 会员信息 integral = models.IntegerField(_(u'integral'), default=0, help_text=u'会员积分') freeze_integral = models.IntegerField(_(u'freeze_integral'), default=0, help_text=u'会员冻结积分') shots_num = models.IntegerField(_(u'shots_num'), default=0, help_text=u'主持镜头数') level = models.IntegerField(_(u'level'), choices=LEVEL_TUPLE, default=MEMBER_NO, help_text=u'会员等级') # 维修员信息 is_maintenance = models.BooleanField(_(u'is_maintenance'), default=False, help_text=_(u'是否维修员'), db_index=True) class Meta: verbose_name = _(u'userinfo') verbose_name_plural = _(u'userinfo') unique_together = ( ('appid', 'userid'), ) def __unicode__(self): return unicode(self.pk) @property def final_integral(self): return self.integral + self.freeze_integral @property def final_nickname(self): if self.user_from == self.APP_USER: return self.username elif self.user_from == self.WX_USER: return self.nickname elif self.user_from == self.GUEST_USER: return self.nickname elif self.user_from == self.LENSMAN_USER: return self.name elif self.user_from == self.TOURGUIDE_USER: return self.name elif self.user_from == self.MINIAPP_USER: return self.nickname return self.nickname @property def data(self): return { 'user_id': self.user_id, 'name': self.name, 'username': self.username, 'nickname': self.nickname, 'avatar': self.avatar, 'phone': self.phone, } @property def cardList(self): return [ { 'cardId': self.membercardid, 'code': self.memberusercardcode } ] def srinfo(self, brand_id=None): try: sr = SalesResponsibilityInfo.objects.get(brand_id=brand_id, unionid=self.unionid, user_status=SalesResponsibilityInfo.ACTIVATED) except SalesResponsibilityInfo.DoesNotExist: sr = None return sr.base_data if sr else { 'sr_id': '', 'is_sr': False, 'is_super_sr': False, } def brandata(self, brand_id=None): if self.unionid: try: saleclerk = SaleclerkInfo.objects.get(brand_id=brand_id, unionid=self.unionid, status=True) except SaleclerkInfo.DoesNotExist: saleclerk = None saleclerk_info = saleclerk.data if saleclerk and saleclerk.is_auth else {} else: saleclerk_info = {} return { 'has_unionid': bool(self.unionid), 'user_id': self.user_id, 'name': self.name, 'username': self.username, 'nickname': self.nickname, 'avatar': self.avatar, 'phone': self.phone, 'subscribe': self.subscribe, 're_membercard': True if self.has_membercard and not self.memberusercardcode else False, 'has_membercard': self.has_membercard, 'membercardid': self.membercardid, 'memberusercardcode': self.memberusercardcode, 'cardList': self.cardList, 'saleclerk': bool(saleclerk_info), 'saleclerk_info': saleclerk_info, 'sr_info': self.srinfo(brand_id), # 会员信息 'integral': self.integral, 'freeze_integral': self.freeze_integral, 'shots_num': self.shots_num, 'level': self.level, } def brand_qydata(self, brand_id=None): if self.phone: try: saleclerk = SaleclerkInfo.objects.get(brand_id=brand_id, clerk_phone=self.phone, status=True) except SaleclerkInfo.DoesNotExist: saleclerk = None saleclerk_info = saleclerk.data if saleclerk and saleclerk.is_auth else {} else: saleclerk_info = {} try: maintenance = MaintenancemanInfo.objects.get(brand_id=brand_id, user_id=self.user_id, status=True) except MaintenancemanInfo.DoesNotExist: maintenance = {} maintenance_info = maintenance.data if maintenance and self.is_maintenance else {} return { 'has_unionid': bool(self.unionid), 'user_id': self.user_id, 'name': self.name, 'username': self.username, 'nickname': self.nickname, 'avatar': self.avatar, 'phone': self.phone, 'subscribe': self.subscribe, 're_membercard': True if self.has_membercard and not self.memberusercardcode else False, 'has_membercard': self.has_membercard, 'membercardid': self.membercardid, 'memberusercardcode': self.memberusercardcode, 'cardList': self.cardList, 'saleclerk': bool(saleclerk_info), 'saleclerk_info': saleclerk_info, 'sr_info': self.srinfo(brand_id), # 会员信息 'integral': self.integral, 'freeze_integral': self.freeze_integral, 'shots_num': self.shots_num, 'level': self.level, # 维修员信息 'is_maintenance': bool(maintenance_info), 'maintenance': maintenance_info, } @property def sendcustomwxamessage(self): # 关注公众号 + 未领保修卡 + 已绑定镜头 return self.subscribe and not self.has_membercard and self.shots_num @property def admindata(self): models = ConsumeInfoSubmitLogInfo.objects.filter(user_id=self.user_id, dupload=False, status=True).values_list('model_uni_name', flat=True) return { 'user_id': self.user_id, 'nickname': self.nickname, 'avatar': self.avatar, 'phone': self.phone, 'sex': self.sex, 'province': self.province, 'city': self.city, 'province_name': self.province_name, 'subscribe': self.subscribe, 'membercardid': self.membercardid, 'memberusercardcode': self.memberusercardcode, 'created_at': tc.local_string(utc_dt=self.created_at, format='%Y-%m-%d %H:%M:%S'), 'code_version': self.code_version, #商品信息 'models': list(models), # 会员信息 'integral': self.integral, 'shots_num': self.shots_num, 'level': self.level, } @property def cardata(self): return { # 'brand_id': self.brand_id, 'card_id': self.membercardid, 'code': self.memberusercardcode, } class UserLoginLogInfo(BaseModelMixin): SUCCESS = 0 PWD_ERROR = 1 OTHER = 2 LOGIN_RESULT = ( (SUCCESS, u'登录成功'), (PWD_ERROR, u'密码错误'), (OTHER, u'其他'), ) user_id = models.CharField(_(u'user_id'), max_length=32, blank=True, null=True, help_text=u'用户唯一标识', db_index=True) login_ip = models.CharField(_(u'login_ip'), max_length=32, blank=True, null=True, help_text=_(u'登录IP')) login_result = models.IntegerField(_(u'login_result'), choices=LOGIN_RESULT, default=SUCCESS) class Meta: verbose_name = _(u'userloginloginfo') verbose_name_plural = _(u'userloginloginfo') def __unicode__(self): return unicode(self.pk) class UserIncomeExpensesInfo(BaseModelMixin): INCOME = 0 EXPENSE = 1 UNFREEZE = 2 TYPE = ( (INCOME, u'收入'), (EXPENSE, u'支出'), (UNFREEZE, u'解冻'), ) user_id = models.CharField(_(u'user_id'), max_length=32, blank=True, null=True, help_text=u'用户唯一标识', db_index=True) photo_id = models.CharField(_(u'photo_id'), max_length=32, blank=True, null=True, help_text=u'照片唯一标识', db_index=True) type = models.IntegerField(_(u'type'), choices=TYPE, default=INCOME, help_text=u'收支类别') amount = models.IntegerField(_(u'amount'), default=0, help_text=u'余额增减数量(分)') balance = models.IntegerField(_(u'balance'), default=0, help_text=u'余额增减后数量(分)') freeze_income_amount = models.IntegerField(_(u'freeze_income_amount'), default=0, help_text=u'收入冻结余额增减数量(分)') freeze_income_balance = models.IntegerField(_(u'freeze_income_balance'), default=0, help_text=u'收入冻结余额增减后数量(分)') freeze_expense_amount = models.IntegerField(_(u'freeze_expense_amount'), default=0, help_text=u'支出冻结余额增减数量(分)') freeze_expense_balance = models.IntegerField(_(u'freeze_expense_balance'), default=0, help_text=u'支出冻结余额增减后数量(分)') remark = models.CharField(_(u'remark'), max_length=255, blank=True, null=True, help_text=u'备注') class Meta: verbose_name = _(u'userincomeexpensesinfo') verbose_name_plural = _(u'userincomeexpensesinfo') def __unicode__(self): return unicode(self.pk)