| @@ -3,14 +3,14 @@ | ||
| 3 | 3 | from django.contrib import admin | 
| 4 | 4 | from django.contrib.auth.hashers import make_password | 
| 5 | 5 |  | 
| 6 | -from account.models import LensmanInfo | |
| 6 | +from account.models import LensmanInfo, LensmanLoginLogInfo, UserInfo, UserLoginLogInfo | |
| 7 | 7 |  | 
| 8 | 8 | from utils.uuid_utils import curtailUUID | 
| 9 | 9 |  | 
| 10 | 10 |  | 
| 11 | 11 | class LensmanInfoAdmin(admin.ModelAdmin): | 
| 12 | 12 |      readonly_fields = ('lensman_id', 'encryption', ) | 
| 13 | -    list_display = ('lensman_id', 'name', 'sex', 'phone', 'location', 'proportion', 'status', 'created_at', 'updated_at') | |
| 13 | +    list_display = ('lensman_id', 'username', 'name', 'sex', 'phone', 'location', 'proportion', 'status', 'created_at', 'updated_at') | |
| 14 | 14 |      search_fields = ('name', 'phone', 'location') | 
| 15 | 15 |      list_filter = ('sex', 'status') | 
| 16 | 16 |  | 
| @@ -23,4 +23,22 @@ class LensmanInfoAdmin(admin.ModelAdmin): | ||
| 23 | 23 | obj.save() | 
| 24 | 24 |  | 
| 25 | 25 |  | 
| 26 | +class LensmanLoginLogInfoAdmin(admin.ModelAdmin): | |
| 27 | +    list_display = ('lensman_id', 'login_ip', 'login_result', 'status', 'created_at', 'updated_at') | |
| 28 | + | |
| 29 | + | |
| 30 | +class UserInfoAdmin(admin.ModelAdmin): | |
| 31 | +    readonly_fields = ('user_id', ) | |
| 32 | +    list_display = ('user_id', 'username', 'name', 'sex', 'phone', 'location', 'user_status', 'status', 'created_at', 'updated_at') | |
| 33 | +    search_fields = ('name', 'phone', 'location') | |
| 34 | +    list_filter = ('sex', 'status', 'user_status') | |
| 35 | + | |
| 36 | + | |
| 37 | +class UserLoginLogInfoAdmin(admin.ModelAdmin): | |
| 38 | +    list_display = ('user_id', 'login_ip', 'login_result', 'status', 'created_at', 'updated_at') | |
| 39 | + | |
| 40 | + | |
| 26 | 41 | admin.site.register(LensmanInfo, LensmanInfoAdmin) | 
| 42 | +admin.site.register(UserInfo, UserInfoAdmin) | |
| 43 | +admin.site.register(LensmanLoginLogInfo, LensmanLoginLogInfoAdmin) | |
| 44 | +admin.site.register(UserLoginLogInfo, UserLoginLogInfoAdmin) | 
| @@ -0,0 +1,85 @@ | ||
| 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 | +        ('account', '0004_auto_20151207_1811'), | |
| 11 | + ] | |
| 12 | + | |
| 13 | + operations = [ | |
| 14 | + migrations.CreateModel( | |
| 15 | + name='LensmanLoginLogInfo', | |
| 16 | + fields=[ | |
| 17 | +                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), | |
| 18 | +                ('status', models.BooleanField(default=True, help_text='\u72b6\u6001', verbose_name='status')), | |
| 19 | +                ('created_at', models.DateTimeField(help_text='\u521b\u5efa\u65f6\u95f4', verbose_name='created_at', auto_now_add=True)), | |
| 20 | +                ('updated_at', models.DateTimeField(help_text='\u66f4\u65b0\u65f6\u95f4', verbose_name='updated_at', auto_now=True)), | |
| 21 | +                ('lensman_id', 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)), | |
| 22 | +                ('login_ip', models.CharField(help_text='\u767b\u5f55IP', max_length=255, null=True, verbose_name='login_ip', blank=True)), | |
| 23 | +                ('login_result', models.IntegerField(default=0, verbose_name='login_result', choices=[(0, '\u767b\u5f55\u6210\u529f'), (1, '\u5bc6\u7801\u9519\u8bef'), (2, '\u5176\u4ed6')])), | |
| 24 | + ], | |
| 25 | +            options={ | |
| 26 | + 'verbose_name': 'lensmanloginloginfo', | |
| 27 | + 'verbose_name_plural': 'lensmanloginloginfo', | |
| 28 | + }, | |
| 29 | + ), | |
| 30 | + migrations.CreateModel( | |
| 31 | + name='UserInfo', | |
| 32 | + fields=[ | |
| 33 | +                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), | |
| 34 | +                ('status', models.BooleanField(default=True, help_text='\u72b6\u6001', verbose_name='status')), | |
| 35 | +                ('created_at', models.DateTimeField(help_text='\u521b\u5efa\u65f6\u95f4', verbose_name='created_at', auto_now_add=True)), | |
| 36 | +                ('updated_at', models.DateTimeField(help_text='\u66f4\u65b0\u65f6\u95f4', verbose_name='updated_at', auto_now=True)), | |
| 37 | +                ('user_id', models.CharField(null=True, max_length=255, blank=True, help_text='\u7528\u6237\u552f\u4e00\u6807\u8bc6', unique=True, verbose_name='user_id', db_index=True)), | |
| 38 | +                ('username', models.CharField(null=True, max_length=255, blank=True, help_text='\u7528\u6237\u7528\u6237\u540d', unique=True, verbose_name='username', db_index=True)), | |
| 39 | +                ('password', models.CharField(help_text='\u7528\u6237\u5bc6\u7801', max_length=255, null=True, verbose_name='password', blank=True)), | |
| 40 | +                ('name', models.CharField(help_text='\u7528\u6237\u59d3\u540d', max_length=255, null=True, verbose_name='name', blank=True)), | |
| 41 | +                ('sex', models.IntegerField(default=0, help_text='\u7528\u6237\u6027\u522b', verbose_name='sex', choices=[(0, '\u7537'), (1, '\u5973')])), | |
| 42 | +                ('phone', models.CharField(null=True, max_length=255, blank=True, help_text='\u7528\u6237\u7535\u8bdd', unique=True, verbose_name='phone', db_index=True)), | |
| 43 | +                ('location', models.CharField(help_text='\u7528\u6237\u5730\u5740', max_length=255, null=True, verbose_name='location', blank=True)), | |
| 44 | +                ('user_status', models.IntegerField(default=0, verbose_name='user_status', choices=[(0, '\u672a\u9a8c\u8bc1'), (1, '\u5df2\u6fc0\u6d3b'), (2, '\u5df2\u7981\u7528'), (3, '\u5df2\u5220\u9664')])), | |
| 45 | +                ('signup_ip', models.CharField(help_text='\u6ce8\u518cIP', max_length=255, null=True, verbose_name='signup_ip', blank=True)), | |
| 46 | +                ('login_ip', models.CharField(help_text='\u767b\u5f55IP', max_length=255, null=True, verbose_name='login_ip', blank=True)), | |
| 47 | +                ('login_at', models.DateTimeField(help_text='\u767b\u5f55\u65f6\u95f4', null=True, verbose_name='login_at', blank=True)), | |
| 48 | + ], | |
| 49 | +            options={ | |
| 50 | + 'verbose_name': 'userinfo', | |
| 51 | + 'verbose_name_plural': 'userinfo', | |
| 52 | + }, | |
| 53 | + ), | |
| 54 | + migrations.CreateModel( | |
| 55 | + name='UserLoginLogInfo', | |
| 56 | + fields=[ | |
| 57 | +                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), | |
| 58 | +                ('status', models.BooleanField(default=True, help_text='\u72b6\u6001', verbose_name='status')), | |
| 59 | +                ('created_at', models.DateTimeField(help_text='\u521b\u5efa\u65f6\u95f4', verbose_name='created_at', auto_now_add=True)), | |
| 60 | +                ('updated_at', models.DateTimeField(help_text='\u66f4\u65b0\u65f6\u95f4', verbose_name='updated_at', auto_now=True)), | |
| 61 | +                ('user_id', models.CharField(max_length=255, blank=True, help_text='\u7528\u6237\u552f\u4e00\u6807\u8bc6', null=True, verbose_name='user_id', db_index=True)), | |
| 62 | +                ('login_ip', models.CharField(help_text='\u767b\u5f55IP', max_length=255, null=True, verbose_name='login_ip', blank=True)), | |
| 63 | +                ('login_result', models.IntegerField(default=0, verbose_name='login_result', choices=[(0, '\u767b\u5f55\u6210\u529f'), (1, '\u5bc6\u7801\u9519\u8bef'), (2, '\u5176\u4ed6')])), | |
| 64 | + ], | |
| 65 | +            options={ | |
| 66 | + 'verbose_name': 'userloginloginfo', | |
| 67 | + 'verbose_name_plural': 'userloginloginfo', | |
| 68 | + }, | |
| 69 | + ), | |
| 70 | + migrations.AddField( | |
| 71 | + model_name='lensmaninfo', | |
| 72 | + name='login_at', | |
| 73 | + field=models.DateTimeField(help_text='\u767b\u5f55\u65f6\u95f4', null=True, verbose_name='login_at', blank=True), | |
| 74 | + ), | |
| 75 | + migrations.AddField( | |
| 76 | + model_name='lensmaninfo', | |
| 77 | + name='login_ip', | |
| 78 | + field=models.CharField(help_text='\u767b\u5f55IP', max_length=255, null=True, verbose_name='login_ip', blank=True), | |
| 79 | + ), | |
| 80 | + migrations.AddField( | |
| 81 | + model_name='lensmaninfo', | |
| 82 | + name='signup_ip', | |
| 83 | + field=models.CharField(help_text='\u6ce8\u518cIP', max_length=255, null=True, verbose_name='signup_ip', blank=True), | |
| 84 | + ), | |
| 85 | + ] | 
| @@ -28,9 +28,112 @@ class LensmanInfo(CreateUpdateMixin): | ||
| 28 | 28 |  | 
| 29 | 29 | proportion = models.FloatField(_(u'proportion'), default=1.0, help_text=u'摄影师分成比例(0.0 ~ 1.0)') | 
| 30 | 30 |  | 
| 31 | + signup_ip = models.CharField(_(u'signup_ip'), max_length=255, blank=True, null=True, help_text=_(u'注册IP')) | |
| 32 | + login_ip = models.CharField(_(u'login_ip'), max_length=255, blank=True, null=True, help_text=_(u'登录IP')) | |
| 33 | + login_at = models.DateTimeField(_(u'login_at'), blank=True, null=True, help_text=_(u'登录时间')) | |
| 34 | + | |
| 31 | 35 | class Meta: | 
| 32 | 36 | verbose_name = _(u'lensmaninfo') | 
| 33 | 37 | verbose_name_plural = _(u'lensmaninfo') | 
| 34 | 38 |  | 
| 35 | 39 | def __unicode__(self): | 
| 36 | 40 | return unicode(self.pk) | 
| 41 | + | |
| 42 | + | |
| 43 | +class LensmanLoginLogInfo(CreateUpdateMixin): | |
| 44 | + SUCCESS = 0 | |
| 45 | + PWD_ERROR = 1 | |
| 46 | + OTHER = 2 | |
| 47 | + | |
| 48 | + LOGIN_RESULT = ( | |
| 49 | + (SUCCESS, u'登录成功'), | |
| 50 | + (PWD_ERROR, u'密码错误'), | |
| 51 | + (OTHER, u'其他'), | |
| 52 | + ) | |
| 53 | + | |
| 54 | + lensman_id = models.CharField(_(u'lensman_id'), max_length=255, blank=True, null=True, help_text=u'摄影师唯一标识', db_index=True) | |
| 55 | + login_ip = models.CharField(_(u'login_ip'), max_length=255, blank=True, null=True, help_text=_(u'登录IP')) | |
| 56 | + login_result = models.IntegerField(_(u'login_result'), choices=LOGIN_RESULT, default=SUCCESS) | |
| 57 | + | |
| 58 | + class Meta: | |
| 59 | + verbose_name = _(u'lensmanloginloginfo') | |
| 60 | + verbose_name_plural = _(u'lensmanloginloginfo') | |
| 61 | + | |
| 62 | + def __unicode__(self): | |
| 63 | + return unicode(self.pk) | |
| 64 | + | |
| 65 | + | |
| 66 | +class UserInfo(CreateUpdateMixin): | |
| 67 | + UNVERIFIED = 0 | |
| 68 | + ACTIVATED = 1 | |
| 69 | + DISABLED = 2 | |
| 70 | + DELETED = 3 | |
| 71 | + | |
| 72 | + USER_STATUS = ( | |
| 73 | + (UNVERIFIED, u'未验证'), | |
| 74 | + (ACTIVATED, u'已激活'), | |
| 75 | + (DISABLED, u'已禁用'), | |
| 76 | + (DELETED, u'已删除'), | |
| 77 | + ) | |
| 78 | + | |
| 79 | + MALE = 0 | |
| 80 | + FEMALE = 1 | |
| 81 | + | |
| 82 | + SEX_TYPE = ( | |
| 83 | + (MALE, u'男'), | |
| 84 | + (FEMALE, u'女'), | |
| 85 | + ) | |
| 86 | + | |
| 87 | + user_id = models.CharField(_(u'user_id'), max_length=255, blank=True, null=True, help_text=u'用户唯一标识', db_index=True, unique=True) | |
| 88 | + | |
| 89 | + username = models.CharField(_(u'username'), max_length=255, blank=True, null=True, help_text=u'用户用户名', db_index=True, unique=True) | |
| 90 | + password = models.CharField(_(u'password'), max_length=255, blank=True, null=True, help_text=u'用户密码') | |
| 91 | + | |
| 92 | + name = models.CharField(_(u'name'), max_length=255, blank=True, null=True, help_text=u'用户姓名') | |
| 93 | + sex = models.IntegerField(_(u'sex'), choices=SEX_TYPE, default=MALE, help_text=u'用户性别') | |
| 94 | + phone = models.CharField(_(u'phone'), max_length=255, blank=True, null=True, help_text=u'用户电话', db_index=True, unique=True) | |
| 95 | + location = models.CharField(_(u'location'), max_length=255, blank=True, null=True, help_text=u'用户地址') | |
| 96 | + | |
| 97 | + user_status = models.IntegerField(_(u'user_status'), choices=USER_STATUS, default=UNVERIFIED) | |
| 98 | + | |
| 99 | + signup_ip = models.CharField(_(u'signup_ip'), max_length=255, blank=True, null=True, help_text=_(u'注册IP')) | |
| 100 | + login_ip = models.CharField(_(u'login_ip'), max_length=255, blank=True, null=True, help_text=_(u'登录IP')) | |
| 101 | + login_at = models.DateTimeField(_(u'login_at'), blank=True, null=True, help_text=_(u'登录时间')) | |
| 102 | + | |
| 103 | + class Meta: | |
| 104 | + verbose_name = _(u'userinfo') | |
| 105 | + verbose_name_plural = _(u'userinfo') | |
| 106 | + | |
| 107 | + def __unicode__(self): | |
| 108 | + return unicode(self.pk) | |
| 109 | + | |
| 110 | + def _data(self): | |
| 111 | +        return { | |
| 112 | + 'user_id': self.user_id, | |
| 113 | + 'username': self.username, | |
| 114 | + } | |
| 115 | + | |
| 116 | + data = property(_data) | |
| 117 | + | |
| 118 | + | |
| 119 | +class UserLoginLogInfo(CreateUpdateMixin): | |
| 120 | + SUCCESS = 0 | |
| 121 | + PWD_ERROR = 1 | |
| 122 | + OTHER = 2 | |
| 123 | + | |
| 124 | + LOGIN_RESULT = ( | |
| 125 | + (SUCCESS, u'登录成功'), | |
| 126 | + (PWD_ERROR, u'密码错误'), | |
| 127 | + (OTHER, u'其他'), | |
| 128 | + ) | |
| 129 | + | |
| 130 | + user_id = models.CharField(_(u'user_id'), max_length=255, blank=True, null=True, help_text=u'用户唯一标识', db_index=True) | |
| 131 | + login_ip = models.CharField(_(u'login_ip'), max_length=255, blank=True, null=True, help_text=_(u'登录IP')) | |
| 132 | + login_result = models.IntegerField(_(u'login_result'), choices=LOGIN_RESULT, default=SUCCESS) | |
| 133 | + | |
| 134 | + class Meta: | |
| 135 | + verbose_name = _(u'userloginloginfo') | |
| 136 | + verbose_name_plural = _(u'userloginloginfo') | |
| 137 | + | |
| 138 | + def __unicode__(self): | |
| 139 | + return unicode(self.pk) | 
| @@ -3,7 +3,7 @@ | ||
| 3 | 3 | from django.contrib.auth.models import User, Group | 
| 4 | 4 | from rest_framework import serializers | 
| 5 | 5 |  | 
| 6 | -from account.models import LensmanInfo | |
| 6 | +from account.models import LensmanInfo, UserInfo | |
| 7 | 7 |  | 
| 8 | 8 |  | 
| 9 | 9 | class UserSerializer(serializers.HyperlinkedModelSerializer): | 
| @@ -22,3 +22,9 @@ class LensmanInfoSerializer(serializers.HyperlinkedModelSerializer): | ||
| 22 | 22 | class Meta: | 
| 23 | 23 | model = LensmanInfo | 
| 24 | 24 |          fields = ('lensman_id', 'name', 'sex', 'phone', 'location', 'proportion', 'created_at') | 
| 25 | + | |
| 26 | + | |
| 27 | +class UserInfoSerializer(serializers.HyperlinkedModelSerializer): | |
| 28 | + class Meta: | |
| 29 | + model = UserInfo | |
| 30 | +        fields = ('user_id', 'name', 'sex', 'phone', 'location', 'user_status', 'created_at') | 
| @@ -1,17 +1,22 @@ | ||
| 1 | 1 | # -*- coding: utf-8 -*- | 
| 2 | 2 |  | 
| 3 | -from django.contrib.auth.hashers import check_password | |
| 3 | +from django.contrib.auth.hashers import make_password, check_password | |
| 4 | 4 | from django.contrib.auth.models import User, Group | 
| 5 | 5 | from django.http import JsonResponse | 
| 6 | 6 |  | 
| 7 | 7 | from rest_framework import viewsets | 
| 8 | 8 |  | 
| 9 | -from account.models import LensmanInfo | |
| 10 | -from account.serializers import UserSerializer, GroupSerializer, LensmanInfoSerializer | |
| 9 | +from account.models import LensmanInfo, UserInfo, UserLoginLogInfo | |
| 10 | +from account.serializers import UserSerializer, GroupSerializer, LensmanInfoSerializer, UserInfoSerializer | |
| 11 | + | |
| 12 | +from utils.ip_utils import ip_addr | |
| 13 | +from utils.uuid_utils import curtailUUID | |
| 14 | + | |
| 15 | +from TimeConvert import TimeConvert as tc | |
| 11 | 16 |  | 
| 12 | 17 |  | 
| 13 | 18 | # curl -X POST -F username=xxxxxxx -F password=xxxxxxx http://api.xfoto.com.cn/login | 
| 14 | -def user_login(request): | |
| 19 | +def lesman_login_api(request): | |
| 15 | 20 |      username = request.POST.get('username', '') | 
| 16 | 21 |      password = request.POST.get('password', '') | 
| 17 | 22 |  | 
| @@ -38,6 +43,84 @@ def user_login(request): | ||
| 38 | 43 | }) | 
| 39 | 44 |  | 
| 40 | 45 |  | 
| 46 | +def user_is_registered_api(request): | |
| 47 | +    username = request.POST.get('username', '') | |
| 48 | +    return JsonResponse({ | |
| 49 | + 'status': 200, | |
| 50 | + 'message': '', | |
| 51 | +        'data': { | |
| 52 | + 'registered': UserInfo.objects.filter(username=username).exists(), | |
| 53 | + } | |
| 54 | + }) | |
| 55 | + | |
| 56 | + | |
| 57 | +def user_signup_api(request): | |
| 58 | +    username = request.POST.get('username', '') | |
| 59 | +    password = request.POST.get('password', '') | |
| 60 | + | |
| 61 | + if UserInfo.objects.filter(username=username).exists(): | |
| 62 | +        return JsonResponse({ | |
| 63 | + 'status': 4010, | |
| 64 | + 'message': u'该用户名已注册', | |
| 65 | + }) | |
| 66 | + | |
| 67 | + user = UserInfo.objects.create( | |
| 68 | + user_id=curtailUUID(UserInfo, 'user_id'), | |
| 69 | + username=username, | |
| 70 | + password=make_password(password, None, 'pbkdf2_sha256'), | |
| 71 | + user_status=UserInfo.ACTIVATED, | |
| 72 | + signup_ip=ip_addr(request), | |
| 73 | + ) | |
| 74 | + | |
| 75 | +    return JsonResponse({ | |
| 76 | + 'status': 200, | |
| 77 | + 'message': u'注册成功', | |
| 78 | + 'data': user.data, | |
| 79 | + }) | |
| 80 | + | |
| 81 | + | |
| 82 | +def user_login_api(request): | |
| 83 | +    username = request.POST.get('username', '') | |
| 84 | +    password = request.POST.get('password', '') | |
| 85 | + | |
| 86 | + try: | |
| 87 | + user = UserInfo.objects.get(username=username) | |
| 88 | + except UserInfo.DoesNotExist: | |
| 89 | +        return JsonResponse({ | |
| 90 | + 'status': 4011, | |
| 91 | + 'message': u'用户不存在', | |
| 92 | + }) | |
| 93 | + | |
| 94 | + login_ip, login_at = ip_addr(request), tc.utc_datetime() | |
| 95 | + | |
| 96 | + if not check_password(password, user.password): | |
| 97 | + UserLoginLogInfo.objects.create( | |
| 98 | + user_id=user.user_id, | |
| 99 | + login_ip=login_ip, | |
| 100 | + login_result=UserLoginLogInfo.PWD_ERROR | |
| 101 | + ) | |
| 102 | +        return JsonResponse({ | |
| 103 | + 'status': 4012, | |
| 104 | + 'message': u'用户密码错误', | |
| 105 | + }) | |
| 106 | + | |
| 107 | + UserLoginLogInfo.objects.create( | |
| 108 | + user_id=user.user_id, | |
| 109 | + login_ip=login_ip, | |
| 110 | + login_result=UserLoginLogInfo.SUCCESS | |
| 111 | + ) | |
| 112 | + | |
| 113 | + user.login_ip = login_ip | |
| 114 | + user.login_at = login_at | |
| 115 | + user.save() | |
| 116 | + | |
| 117 | +    return JsonResponse({ | |
| 118 | + 'status': 200, | |
| 119 | + 'message': u'登录成功', | |
| 120 | + 'data': user.data, | |
| 121 | + }) | |
| 122 | + | |
| 123 | + | |
| 41 | 124 | class UserViewSet(viewsets.ModelViewSet): | 
| 42 | 125 | """ | 
| 43 | 126 | API endpoint that allows users to be viewed or edited. | 
| @@ -57,3 +140,8 @@ class GroupViewSet(viewsets.ModelViewSet): | ||
| 57 | 140 | class LensmanInfoViewSet(viewsets.ModelViewSet): | 
| 58 | 141 |      queryset = LensmanInfo.objects.all().order_by('-created_at') | 
| 59 | 142 | serializer_class = LensmanInfoSerializer | 
| 143 | + | |
| 144 | + | |
| 145 | +class UserInfoViewSet(viewsets.ModelViewSet): | |
| 146 | +    queryset = UserInfo.objects.all().order_by('-created_at') | |
| 147 | + serializer_class = UserInfoSerializer | 
| @@ -7,16 +7,19 @@ from photo import views as photo_views | ||
| 7 | 7 |  | 
| 8 | 8 |  | 
| 9 | 9 | urlpatterns = [ | 
| 10 | - url(r'^login$', account_views.user_login, name='user_login'), | |
| 10 | + url(r'^login$', account_views.lesman_login_api, name='lesman_login_api'), | |
| 11 | + url(r'^u/is_registered$', account_views.user_is_registered_api, name='user_is_registered_api'), # 用户是否已经注册 | |
| 12 | + url(r'^u/signup$', account_views.user_signup_api, name='user_signup_api'), # 用户注册 | |
| 13 | + url(r'^u/login$', account_views.user_login_api, name='user_login_api'), # 用户登录 | |
| 11 | 14 | ] | 
| 12 | 15 |  | 
| 13 | 16 | urlpatterns += [ | 
| 14 | - url(r'^uuid_init$', photo_views.uuid_init, name='uuid_init'), | |
| 15 | - url(r'^uuid$', photo_views.uuid, name='uuid'), | |
| 16 | - url(r'^photos/upload$', photo_views.upload_photo, name='upload_photo'), | |
| 17 | + url(r'^uuid_init$', photo_views.uuid_init, name='uuid_init'), # 生成唯一标识 | |
| 18 | + url(r'^uuid$', photo_views.uuid, name='uuid'), # 获取唯一标识 | |
| 19 | + url(r'^photos/upload$', photo_views.upload_photo, name='upload_photo'), # 上传图片 | |
| 17 | 20 | ] | 
| 18 | 21 |  | 
| 19 | 22 | urlpatterns += [ | 
| 20 | - url(r'^s/(?P<session>\w+)$', photo_views.session_detail_api, name='session_detail_api'), | |
| 23 | + url(r'^s/(?P<session>\w+)$', photo_views.session_detail_api, name='session_detail_api'), # Session 详情 | |
| 21 | 24 | url(r'^p/(?P<photo>\w+)$', photo_views.photo_standard_api, name='photo_standard_api'), # standard thumbnail, available for free | 
| 22 | 25 | ] | 
| @@ -1,6 +1,10 @@ | ||
| 1 | 1 | 1、用户信息 —— 400 | 
| 2 | - 4000 —— 用户不存在 | |
| 3 | - 4001 —— 用户密码错误 | |
| 2 | + 4000 —— 摄影师不存在 | |
| 3 | + 4001 —— 摄影师密码错误 | |
| 4 | + | |
| 5 | + 4010 —— 用户名已注册 | |
| 6 | + 4011 —— 用户名不存在 | |
| 7 | + 4012 —— 用户密码错误 | |
| 4 | 8 |  | 
| 5 | 9 | 2、照片上传 —— 401 | 
| 6 | 10 | 4010 —— 参数错误 | 
| @@ -1,3 +1,5 @@ | ||
| 1 | +# -*- coding: utf-8 -*- | |
| 2 | + | |
| 1 | 3 | """pai2 URL Configuration | 
| 2 | 4 |  | 
| 3 | 5 | The `urlpatterns` list routes URLs to views. For more information please see: | 
| @@ -26,6 +28,7 @@ router = routers.DefaultRouter() | ||
| 26 | 28 | # router.register(r'users', account_views.UserViewSet) | 
| 27 | 29 | # router.register(r'groups', account_views.GroupViewSet) | 
| 28 | 30 | router.register(r'lensmans', account_views.LensmanInfoViewSet) | 
| 31 | +router.register(r'users', account_views.UserInfoViewSet) | |
| 29 | 32 | router.register(r'photos', photo_views.PhotoInfoViewSet) | 
| 30 | 33 |  | 
| 31 | 34 | urlpatterns = [ | 
| @@ -34,7 +37,7 @@ urlpatterns = [ | ||
| 34 | 37 |  | 
| 35 | 38 | urlpatterns += [ | 
| 36 | 39 |      # url(r'^api/', include('api.urls', namespace='api')), | 
| 37 | - url(r'^s/(?P<session>\w+)$', photo_views.session_detail, name='session_detail'), | |
| 40 | + url(r'^s/(?P<session>\w+)$', photo_views.session_detail, name='session_detail'), # Session 详情 | |
| 38 | 41 | url(r'^p/(?P<photo>\w+)$', photo_views.photo_standard, name='photo_standard'), # standard thumbnail, available for free | 
| 39 | 42 | url(r'^m/(?P<photo>\w+)$', photo_views.photo_medium, name='photo_medium'), # medium/mobile version, without watermark, login or paid by others | 
| 40 | 43 | url(r'^l/(?P<photo>\w+)$', photo_views.photo_large, name='photo_large'), # large, might support server side panning later, login required | 
| @@ -1,6 +1,5 @@ | ||
| 1 | 1 | # -*- coding: utf-8 -*- | 
| 2 | 2 |  | 
| 3 | - | |
| 4 | 3 | from django.conf import settings | 
| 5 | 4 | from django.conf.urls import include, url | 
| 6 | 5 |  | 
| @@ -1,7 +1,7 @@ | ||
| 1 | 1 | CodeConvert==2.0.3 | 
| 2 | 2 | Django==1.8.4 | 
| 3 | 3 | MySQL-python==1.2.5 | 
| 4 | -TimeConvert==1.0.7 | |
| 4 | +TimeConvert==1.1.3 | |
| 5 | 5 | django-multidomain==1.1.4 | 
| 6 | 6 | django-shortuuidfield==0.1.3 | 
| 7 | 7 | djangorestframework==3.3.1 | 
| @@ -0,0 +1,5 @@ | ||
| 1 | +# -*- coding: utf-8 -*- | |
| 2 | + | |
| 3 | + | |
| 4 | +def ip_addr(request): | |
| 5 | + return request.META['HTTP_X_FORWARDED_FOR'] if 'HTTP_X_FORWARDED_FOR' in request.META else request.META['REMOTE_ADDR'] | 
| @@ -2,8 +2,6 @@ | ||
| 2 | 2 |  | 
| 3 | 3 | from django.conf import settings | 
| 4 | 4 |  | 
| 5 | -from photo.models import UUIDInfo | |
| 6 | - | |
| 7 | 5 | import shortuuid | 
| 8 | 6 |  | 
| 9 | 7 |  |