2010-05-30 5 views
4

Django newbie ici. J'ai écrit un formulaire de connexion simplifié qui prend l'email et le mot de passe. Cela fonctionne très bien si le courrier électronique et le mot de passe sont fournis, mais si l'un ou l'autre est manquant, j'obtiens l'exception KeyError. Selon la documentation de django, cela ne devrait jamais arriver:Connexion personnalisée en Django

Par défaut, chaque classe Field suppose que la valeur est requise, donc si vous transmettez une valeur vide - soit None ou la chaîne vide ("") - alors nettoyez() déclenche une exception ValidationError

J'ai essayé d'écrire mes propres validateurs pour les champs (clean_email et clean_password), mais il ne fonctionne pas (c.-à-je obtenir exception KeyError). Qu'est-ce que je fais mal?

class LoginForm(forms.Form): 
    email = forms.EmailField(label=_(u'Your email')) 
    password = forms.CharField(widget=forms.PasswordInput, label=_(u'Password')) 

    def clean_email(self): 
     data = self.cleaned_data['email'] 
     if not data: 
      raise forms.ValidationError(_("Please enter email")) 
     return data 

    def clean_password(self): 
     data = self.cleaned_data['password'] 
     if not data: 
      raise forms.ValidationError(_("Please enter your password")) 
     return data 

    def clean(self): 
     try: 
      username = User.objects.get(email__iexact=self.cleaned_data['email']).username 
     except User.DoesNotExist: 
      raise forms.ValidationError(_("No such email registered")) 
     password = self.cleaned_data['password'] 

     self.user = auth.authenticate(username=username, password=password) 
     if self.user is None or not self.user.is_active: 
      raise forms.ValidationError(_("Email or password is incorrect")) 
     return self.cleaned_data 
+2

Le ['django.contrib.auth.forms.AuthenticationForm'] (http://github.com/jacobian/django/blob/master/django/contrib/auth/forms.py#L54) livré avec django est assez simple et robuste. Si vous n'avez aucun besoin urgent, utilisez-le. – miku

+0

Je m'authentifie par email et mot de passe, pas nom d'utilisateur et mot de passe. – mgs

+1

Plutôt regarder dans quelque chose comme ceci: [Connexion avec des adresses e-mail dans Django] (http://www.davidcramer.net/code/224/logging-in-with-email-addresses-in-django.html) – miku

Répondre

4

Vous pouvez tirer parti de façon intégrée de Django pour remplacer la façon dont l'authentification se produit par la mise AUTHENTICATION_BACKENDS dans votre settings.py

Voici mon EmailAuthBackend:

#settings.py 
AUTHENTICATION_BACKENDS = (
    'auth_backend.auth_email_backend.EmailBackend', 
    'django.contrib.auth.backends.ModelBackend', 
) 

#auth_email_backend.py 
from django.contrib.auth.backends import ModelBackend 
from django.forms.fields import email_re 
from django.contrib.auth.models import User 

class EmailBackend(ModelBackend): 
    """ 
    Authenticate against django.contrib.auth.models.User 
    """ 

    def authenticate(self, **credentials): 
     return 'username' in credentials and \ 
      self.authenticate_by_username_or_email(**credentials) 

    def authenticate_by_username_or_email(self, username=None, password=None): 
     try: 
      user = User.objects.get(email=username) 
     except User.DoesNotExist: 
      try: 
       user = User.objects.get(username=username) 
      except User.DoesNotExist: 
       user = None 
     if user: 
      return user if user.check_password(password) else None 
     else: 
      return None 

    def get_user(self, user_id): 
     try: 
      return User.objects.get(pk=user_id) 
     except User.DoesNotExist: 
      return None 

#forms.py 
#replaces the normal username CharField with an EmailField 
from django import forms 
from django.contrib.auth.forms import AuthenticationForm 

class LoginForm(AuthenticationForm): 
    username = forms.EmailField(max_length=75, label='Email') 
    next = forms.CharField(widget=forms.HiddenInput) 

Hope that helps!

+0

Le script de David Cramer est plus efficace que le mien, puisqu'il définit la recherche kwargs avec l'instruction if '@' dans le nom d'utilisateur. J'ai adopté sa méthode. – Brandon

Questions connexes