Django override default functionalities - python

In django/django/contrib/auth/forms.py how to override the default method
and include the same in the users module ?
So my intention is that i want to change the username field length to 64 characters but this would not be correct to do this in django directories,because whenever new version is downloaded this file has to changed....
What exactly shoudl be changed to do this
class AuthenticationForm(forms.Form):
"""
Base class for authenticating users. Extend this to get a form that accepts
username/password logins.
"""
username = forms.CharField(label=_("Username"), max_length=30)
password = forms.CharField(label=_("Password"), widget=forms.PasswordInput)

#Deniz Dogan: You also have to convince login view to use the custom form:
login(request, authentication_form=MyAuthenticationForm)

If I understand you correctly, you may be able to change it by sub-classing AuthenticationForm into e.g. MyAuthenticationForm:
class MyAuthenticationForm(AuthenticationForm):
username = forms.CharField(label=_("Username"), max_length=64)
This way, you would keep the validators from AuthenticationForm, but still let the username be 64 characters long.

Related

Django email field invalid for international email (in non-english)

I am using django REST framework.
This is my user model extended from AbstractUser
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(_('email address'), unique=True)
I am now trying to check for multiple languages my models can work.
When I validate the user object serializer using if user_serializer.is_valid(): it gives me false.
I tried entering the user details by django admin panel but there it says Email is invalid
All other fields like models.CharField work perfectly fine with other languages. But this email field does not work.
EmailField is using EmailValidator class by default which might result in an unexpected outcome. You can simply pass a custom validator class that whitelisted the domains you want. Here is the default class you might want to extend or overwrite. There is an answer with more details in StackOverflow in case you need more details.

In Django, is it possible for superusers to have different required fields than non-superusers?

I know that superusers and regular users are both just django's User objects, but how can I write a custom user class that requires some fields for plain users and doesn't require those fields for superusers?
No structure in the database is tricky. JSONFields for example may prove to be extremely hard to tame when the app grows.
I would go and try to make it "simple" - more maintainable (I imagine if you need to do stuff like that you may want to extend the model in the future). If this is a new project you can easily change the default user model. But that may or may not help you with your case.
You can always make two models:
from django.db import models
from django.contrib.auth.models import AbstractBaseUser
class Mortal(AbstractBaseUser):
is_superuser = False
username = models.CharField(max_length=256)
first_name = models.CharField(max_length=256)
last_name = models.CharField(max_length=256)
class Admin(AbstractBaseUser):
is_superuser = True
username = models.CharField(max_length=256)
and then make your own authentication backend:
class MyBackend(object):
"""
Danger! A backend to authenticate only via username
"""
def authenticate(self, username=None):
try:
return Mortal.objects.get(username=username)
except Mortal.DoesNotExist:
try:
return Admin.objects.get(username=username)
except Admin.DoesNotExist:
return None
You can have a profile class (say UserProfile) with foreign key to the user that is to be created only when user signs up using the website's registration form. That way, superuser which is created on admin site or through command line wouldn't need an extra profile instance attached to it.

Django Forms - Different Versions

I am learning django so i looked over a tutorial and then i am looking over another one now. So there are two versions of Signup form i came acrosss.
1st Version:
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
class MyRegForm(UserCreationForm):
email=forms.EmailField(required=True)
class Meta:
model = User
fields =('username','email','password','password2')
def save(self, commit=True):
user=super(UserCreationForm,self).save(commit=False)
if commit:
user.save()
return user
Looking at the first version i was able to understand that i can even make a new form by just making this simple class extending from class like this:
from django import forms
from models import Article
class ArtForm(forms.ModelForm):
class Meta:
model = Article
fields = ('title', 'body', 'pub_data', 'thumb')
2nd Version:
from django import forms
from django.contrib.auth.models import User
class SignupForm(forms.Forms):
username = forms.CharField(max_length=20)
email = forms.EmailField()
pass1 = forms.CharField(max_length=20,widget=forms.PasswordInput(render_value=False))
pass2 = forms.CharField(max_length=20,widget=forms.PasswordInput(render_value==False))
def clean_username(self):
try:
User.objects.get(username=self.cleaned_data['username'])
except User.DoesNotExist:
return self.cleaned_data['username']
raise forms.ValidationError("The Username is already in use. Please Choose Another")
def clean_pass2(self):
if self.cleaned_data['pass2']!=self.cleaned_data['pass1']:
raise forms.ValidationError("The two passwords should match")
return self.cleaned_data['pass2']
def save(self):
new_user = User.objects.create_user(username=self.cleaned_data['username'],
email=self.cleaned_data['email'],
password=self.cleaned_data['pass1'])
return new_user
In this second version we have to setup everything on our own, seems we are having a bit more power being able to add custom validation to it. The save function here seems weird , i dont see in object.save() call in it. It just returns the object.
So which version should be used professionally?
The second version does not have any Meta data in it. I think we can actually mix both kind of versions, but what is missing from both of them and which ones is more generally used?
The second version is a plain form, not a model form. It creates the User object by calling create_user, which instantiates and saves it, so there is no need to call save explicitly.
Generally if you are dealing with model objects, it's usually better to use a ModelForm. In the case of the User object, there is the additional complication that you need to deal with hashing the password - create_user calls user.set_password, which does this. The first version inherits from UserCreationForm which calls set_password directly on the newly-created User instance. If you're creating Users, I would always say to subclass that UserCreationForm if possible.
I'd say the first one is a lot cleaner, but if you need to do special User creation that involves data that can't be attained from the form, or you want to clean your data in a very specific way, it might be worth to use some of the methods from the second, but even with those changes, there is probably not a need to use something other than a ModelForm

Writing user.get_profile() custom function which should create auth profile if there is not any

I am trying to write custom get_profile() function which should create user profile for users who are registered thru admin or any other way where post_save was not called.
How can I start this?
I guess that you have a model to handle user profile like this:
class UserProfile(models.Model):
"""Contains user profile fields not provided by User model"""
user = models.OneToOneField(User)
# Defined User profile fields like picture, phone, etc
So adding following line (maybe in your models.py after UserProfile model):
User.profile = property(lambda u: UserProfile.objects.get_or_create(user=u)[0])
Allows access to the profile of a user (i.e. in templates: {% user.profile.phone %}) by creating it if not exists.
This is the way I solved in my site a problem like you describe.
Hope this helps
I am a bit confused. Are you trying to let users create account and sign in? Then use django-registration which is easy and works out of the box.

Django: Is it a correct way to override form field of AuthenticationForm?

I find it's convenient to use AuthenticationForm of Django
But since the username of our client is a little bit long to remember, and the amount of our client is not much, we want to use select widget in the login page. So I use the following code to achieve it. It works.
from django.contrib.auth.forms import AuthenticationForm
class SignInForm(AuthenticationForm):
username = forms.ModelChoiceField(queryset=User.objects.all())
in the views.py:
def post(self, request):
form = SignInForm(data=request.POST)
if form.is_valid():
login(request, form.get_user())
return HttpResponseRedirect(reverse('account:signin'))
return render(request, 'account/sign-in.html', {'form': form})
However, I can't find any similar usage in documentation. So I'm not sure whether it's correct to do that.
I don't know whether it's similar to ModelForm:
https://docs.djangoproject.com/en/1.5/topics/forms/modelforms/#overriding-the-default-field-types-or-widgets
I want to know what happen here. Does the username I declare in SignInForm prevent AuthenticationForm from generating its username like ModelForm? But the AuthenticationForm successfully treat the username I declare just like the username it should have generate?
It looks good.
The source of AuthenticationForm defined username and password field. Your subclass overrided the username field as normal.
All the form fields are actually implementations of the Python descriptor protocol. They are only general class members there.

Categories