我为登录系统创建了自定义身份验证后端。当然,当我在python shell中尝试它时,自定义后端工作。但是,当我在服务器中运行它时出错。错误显示“此模型中不存在以下字段,或者是m2m字段:last_login”。我是否需要在客户模型中包含last_login字段,或者是否有其他解决方案来解决问题? 这是我的示例代码:
In my models.py
class Customer(models.Model):
yes_or_no = ((True, 'Yes'),(False, 'No'))
male_or_female = ((True,'Male'),(False,'Female'))
name = models.CharField(max_length=100)
email = models.EmailField(max_length=100,blank = False, null = False)
password = models.CharField(max_length=100)
gender = models.BooleanField(default = True, choices = male_or_female)
birthday = models.DateField(default =None,blank = False, null = False)
created = models.DateTimeField(default=datetime.now, blank=True)
_is_active = models.BooleanField(default = False,db_column="is_active")
@property
def is_active(self):
return self._is_active
# how to call setter method, how to pass value ?
@is_active.setter
def is_active(self,value):
self._is_active = value
def __str__(self):
return self.name
在backends.py中
from .models import Customer
from django.conf import settings
class CustomerAuthBackend(object):
def authenticate(self, name=None, password=None):
try:
user = Customer.objects.get(name=name)
if password == getattr(user,'password'):
# Authentication success by returning the user
user.is_active = True
return user
else:
# Authentication fails if None is returned
return None
except Customer.DoesNotExist:
return None
def get_user(self, user_id):
try:
return Customer.objects.get(pk=user_id)
except Customer.DoesNotExist:
return None
在views.py
中@login_required(login_url='/dataInfo/login/')
def login_view(request):
if request.method == 'POST':
username = request.POST['username']
password = request.POST['password']
user = authenticate(name=username,password=password)
if user is not None:
if user.is_active:
login(request,user)
#redirect to user profile
print "suffcessful login!"
return HttpResponseRedirect('/dataInfo/userprofile')
else:
# return a disable account
return HttpResponse("User acount or password is incorrect")
else:
# Return an 'invalid login' error message.
print "Invalid login details: {0}, {1}".format(username, password)
# redirect to login page
return HttpResponseRedirect('/dataInfo/login')
else:
login_form = LoginForm()
return render_to_response('dataInfo/login.html', {'form': login_form}, context_instance=RequestContext(request))
在setting.py
中AUTHENTICATION_BACKENDS = ('dataInfo.backends.CustomerAuthBackend', 'django.contrib.auth.backends.ModelBackend',)
答案 0 :(得分:2)
这是因为你使用django的login()
函数来记录用户。
Django的login
函数使用您提供的user_logged_in
实例作为参数发出名为user
的信号。 See login()
source
这个信号在django的contrib.auth.models
中被收听。它尝试更新名为last_login
的字段,假设您提供的用户实例是django的默认AbstractUser
模型的子类。
为了解决这个问题,您可以执行以下操作之一:
答案 1 :(得分:0)
谢谢,我定义了一个自定义login
方法,以在自动测试中解决此问题,默认情况下,我不会关闭信号。
这是一个工作代码示例。
def login(client: Client, user: User) -> None:
"""
Disconnect the update_last_login signal and force_login as `user`
Ref: https://stackoverflow.com/questions/38156681/error-about-django-custom-authentication-and-login
Args:
client: Django Test client instance to be used to login
user: User object to be used to login
"""
user_logged_in.disconnect(receiver=update_last_login)
client.force_login(user=user)
user_logged_in.connect(receiver=update_last_login)
依次将其用于测试中,如下所示:
class TestSomething(TestCase):
"""
Scenarios to validate:
....
"""
@classmethod
@factory.django.mute_signals(signals.pre_save, signals.post_save)
def setUpTestData(cls):
"""
Helps keep tests execution time under control
"""
cls.client = Client()
cls.content_type = 'application/json'
def test_a_scenario(self):
"""
Scenario details...
"""
login(client=self.client, user=<User object>)
response = self.client.post(...)
...
希望有帮助。