当尝试使用 Tastypie 登录 Django 时,可能会遇到“error_message”: “column username is not unique”错误。这是因为 Tastypie 将尝试使用要验证的用户名创建一个新用户,但这会引发数据库错误,因为用户名已经存在。
解决方案
有两种方法可以解决这个问题:
-
创建一个 UserResource,并添加一个方法,允许用户登录并传递用户名和密码。这种方法更加安全,因为它不会创建新用户。
-
将 authentication 类更改为
Authorization()
。这将允许用户登录,而不会创建新用户。
代码示例
方法 1:
from django.contrib.auth.models import User
from django.contrib.auth import authenticate, login, logout
from tastypie.http import HttpUnauthorized, HttpForbidden
from django.conf.urls import url
from tastypie.utils import trailing_slash
class UserResource(ModelResource):
class Meta:
queryset = User.objects.all()
fields = ['first_name', 'last_name', 'email']
allowed_methods = ['get', 'post']
resource_name = 'user'
def override_urls(self):
return [
url(r"^(?P<resource_name>%s)/login%s$" %
(self._meta.resource_name, trailing_slash()),
self.wrap_view('login'), name="api_login"),
url(r'^(?P<resource_name>%s)/logout%s$' %
(self._meta.resource_name, trailing_slash()),
self.wrap_view('logout'), name='api_logout'),
]
def login(self, request, **kwargs):
self.method_check(request, allowed=['post'])
data = self.deserialize(request, request.raw_post_data, format=request.META.get('CONTENT_TYPE', 'application/json'))
username = data.get('username', '')
password = data.get('password', '')
user = authenticate(username=username, password=password)
if user:
if user.is_active:
login(request, user)
return self.create_response(request, {
'success': True
})
else:
return self.create_response(request, {
'success': False,
'reason': 'disabled',
}, HttpForbidden )
else:
return self.create_response(request, {
'success': False,
'reason': 'incorrect',
}, HttpUnauthorized )
def logout(self, request, **kwargs):
self.method_check(request, allowed=['get'])
if request.user and request.user.is_authenticated():
logout(request)
return self.create_response(request, { 'success': True })
else:
return self.create_response(request, { 'success': False }, HttpUnauthorized)
方法 2:
from django.contrib.auth.models import User
from django.contrib.auth import authenticate, login, logout
from tastypie.http import HttpUnauthorized, HttpForbidden
from django.conf.urls import url
from tastypie.utils import trailing_slash
class UserResource(ModelResource):
class Meta:
queryset = User.objects.all()
resource_name = 'user'
allowed_methods = ['post']
def prepend_urls(self):
return [
url(r"^user/login/$", self.wrap_view('login'), name="api_login"),
url(r"^user/logout/$", self.wrap_view('logout'), name='api_logout'),
]
def login(self, request, **kwargs):
self.method_check(request, allowed=['post'])
data = self.deserialize(request, request.raw_post_data, format=request.META.get('CONTENT_TYPE', 'application/json'))
username = data.get('username', '')
password = data.get('password', '')
user = authenticate(username=username, password=password)
if user:
if user.is_active:
login(request, user)
return self.create_response(request, {
'success': True
})
else:
return self.create_response(request, {
'success': False,
'reason': 'disabled',
}, HttpForbidden )
else:
return self.create_response(request, {
'success': False,
'reason': 'incorrect',
}, HttpUnauthorized )
def logout(self, request, **kwargs):
self.method_check(request, allowed=['post'])
if request.user and request.user.is_authenticated():
logout(request)
return self.create_response(request, { 'success': True })
else:
return self.create_response(request, { 'success': False }, HttpUnauthorized)
在任一种方法中,您都可以通过向端点 http://hostname/api/user/login 发送 POST 请求来登录。请求数据应具有以下格式:
{
"username": "username",
"password": "password"
}
如果登录成功,您将收到以下响应:
{
"success": True
}
如果登录失败,您将收到以下响应:
{
"success": False,
"reason": "incorrect"
}