I have customize Django 1.5 (from djangoproject docs) authentication to login with email instead of username and its working perfect, but I am using Django-registration 1.0 to register users.
How do I remove the username field from django registration so users will only need to enter e-mail & password when registering.
Thank you all in advance.
Yaniv M
This should get you started.
Create your own form that is a subclass of RegistrationForm.
In forms.py
from registration.forms import RegistrationForm
class MyRegistrationForm(RegistrationForm):
# Override RegistrationForm
def __init__(self, *args, **kwargs):
super(RegistrationForm, self).__init__(*args, **kwargs)
self.fields.pop('username')
In views.py
from registration.views import RegistrationView
from yourapp.forms import MyRegistrationForm
class MyRegistrationView(RegistrationView):
form_class = MyRegistrationForm
In urls.py
url(r'^accounts/register/$', MyRegistrationView.as_view(),
name='registration'),
You can create a custom form class based on default RegistrationForm and use that class in the RegistrationView view.
As-is, it's complicated. You need to:
apply this patch because in d-r-1.0, models.py assumes your User model has a "username" field
create your own "backend" by copy/pasting/editing registration/backends/default/views.py
copy/paste/edit the registration form as well from registration/forms.py
most of the time you can use the registration views without modification
Related
I extend the default user model with a proxy model to add an extra method.
from django.contrib.auth.models import User
class Person(User):
class Meta:
proxy = True
def custom_method(self):
pass
The main purpose is to use the method in templates.
<div>{{ user.custom_method }}</div>
But since the user is pointing to the default user model, it has no access to the custom_method.
Is there any way to achieve this other than create a subclass of the User model?
=== UPDATE ==============
I ended up with custom backends:
(not sure if this solution has any drawbacks)
# user proxy
class ExtendedUser(get_user_model()):
class Meta:
proxy = True
def custom_method(self):
...
# backends
from django.contrib.auth.backends import ModelBackend
# since I'm using allauth
from allauth.account.auth_backends import AuthenticationBackend
from .models import ExtendedUser
class DjangoModelBackend(ModelBackend):
def get_user(self, user_id):
print("\n\n\ncustom user!!!")
try:
user = ExtendedUser.objects.get(pk=user_id)
except ExtendedUser.DoesNotExist:
return None
return user if self.user_can_authenticate(user) else None
class AuthModelBackend(DjangoModelBackend, AuthenticationBackend):
pass
And in settings.py, add these to AUTHENTICATION_BACKENDS.
It might be better to monkey patch the user model. Indeed, in one of the AppConfigs [Django-doc] we can implement this with:
# app_name/apps.py
from django.apps import AppConfig
from django.contrib.auth import get_user_model
def custom_method(self):
return 'Some value'
class MyAppConfig(AppConfig):
name = 'app_name'
def ready(self):
User = get_user_model()
User.custom_method = custom_method
Here we thus add a method to the user model that can then be called in views, templates, etc.
hi everyone i'm trying to make a blog and i want to associate a user to post .. and to comment , it's a multi-user blog and i don't know how to do it , any help guys ? !
here is the model file :
from django.db import models
from django.utils import timezone
from django.conf import settings
from django.utils.text import slugify
# Create your models here.
#this is for categories
class Category(models.Model):
title=models.CharField(max_length=100,default='')
def __str__(self):
return self.title
#this is where a user can create his own gigs
class Gigposter(models.Model):
title=models.CharField(default='',max_length=100,blank=False)
user=models.OneToOneField(settings.AUTH_USER_MODEL,on_delete=models.CASCADE,null=False)
categories=models.OneToOneField(Category,on_delete=models.PROTECT,default='',null=False)
published_at=models.DateTimeField(auto_now_add=True)
description=models.TextField(default='',max_length=None,blank=False)
mainphoto=models.ImageField(default='')
photo=models.ImageField()
def __str__(self):
return self.title
#this is where a user can comment and say what he thinks about others work
class Comment_area(models.Model):
user=models.OneToOneField(settings.AUTH_USER_MODEL,on_delete=models.CASCADE,blank=False)
comment=models.TextField(max_length=None,default='')
commented_at=models.DateTimeField(auto_now_add=True)
and the views file is empty as you can see :
from django.shortcuts import render
# Create your views here.
Wouldn't recommend using a OneToOneField here, as it tells Django the user is tied to exactly one comment/post (when, a user is likely to post more than once).
You could use models.ForeignKey:
from django.contrib.auth.models import User
class Gigposter(models.Model):
# Other properties...
user = models.ForeignKey(
'User'
on_delete=models.CASCADE
)
If you want to automatically associate a user to a post when working on the admin page, you should redefine save_model method of your model. This method describes everything what should be done when you save your model. In your case you should add something like
class GigposterAdmin(admin.ModelAdmin):
def save_model(self, request, obj, form, change):
obj.user = `request.user`
super().save_model(request, obj, form, change)
admin.site.register(Gigposter, GigposterAdmin)
to your admin.py. You should also exclude the user field from fieldset in GigposterAdmin. See this for reference.
If you need to identify user in your views, you can always use request.user. In particular, you can pass it as a part of the context for generating a view. Hope this helps.
I create registration form:
#urls.py
from django.conf.urls import patterns, url
from django.views.generic import TemplateView
from account.views import Register
urlpatterns = patterns('',
url(r'^register/$', Register.as_view(template_name='account/register.html')),
)
#views.py
from django.views.generic import CreateView
from django.contrib.auth.models import User
class Register(CreateView):
model = User
success_url = '/account/'
And i have question: how I can add that email be require (now I must only enter username, password and 2 times time).
#edit
And how "repair" password? When i create user (in this form) and then go to admin panel, in user i see "Invalid password format or unknown hashing algorithm.". How i can repair this?
The reason that email is not required is because you're using a ModelForm, which takes a lot of cues from the underlying User model. Specifically, the required=True attribute is not present on the email field of the model.
One solution is to create your own form with the necessary attributes, perhaps by using a ModelForm and adding a required email field.
Another solution, and probably the better one, is to use something like django-registration as mentioned by Aamir Adnan in the comments to your question. It'll simplify things a lot for you.
As far as your repair password goes, you can't set the password to a raw string value as you're doing with your CreateView. To set a password, you have to call user.set_password(raw_string) which will take care of hashing and salting for you. Look how the built in UserCreationForm works, and try to mimic it if you decide to build the form yourself, rather than using a library (you shouldn't).
To solve these two problems you can use form like:
class UserCreationForm(forms.ModelForm):
class Meta:
model = User
def __init__(self, *args, **kwargs):
super(UserCreationForm).__init__(*args, **kwargs)
self.fields['email'].required = True
def save(self, commit=True):
user = super(UserCreationForm, self).save(commit=False)
user.set_password(self.cleaned_data["password"])
if commit:
user.save()
return user
class Register(CreateView):
model = User
form_class = UserCreationForm
success_url = '/account/'
But there'll be other problems like duplication of username.
I want to display only custom permissions (which I have created with Meta class in Model) in Django admin interface. Is that possible and how?
I would consider creating your own custom view to add the custom permissions, instead of trying to modify the Django admin. However, if you're sure you want to use the Django admin, you could try the following approach:
Start by subclass UserChangeForm, and override the __init__ method. Set self.fields['user_permissions'].queryset with a queryset containing your custom permissions.
from django.contrib.auth.forms import UserChangeForm
class MyUserChangeForm(UserChangeForm):
def __init__(self, *args, **kwargs):
super(MyUserChangeForm, self).__init__(*args, **kwargs)
custom_permissions = ????
self.fields['user_permissions'].queryset = custom_permissions
Next, subclass django.contrib.auth.admin.UserAdmin, and use your form instead of the UserChangeForm.
from django.contrib.auth.admin import UserAdmin
class MyUserAdmin(UserAdmin):
form = MyUserChangeForm
Finally, unregister the default UserAdmin, and register your own.
admin.site.unregister(User)
admin.site.register(User, MyUserAdmin)
I have a django site using the basic django registration framework. I have my login page working fine, but I want to change the css class on the inputs. The form passed to the login page looks to be an AuthenticationForm class.
What would be a good way to add a css class to the username, and password fields?
Sub class your auth form
forms.py
from django import forms
from django.contrib.auth.forms import AuthenticationForm
from django.forms.widgets import PasswordInput, TextInput
class RFPAuthForm(AuthenticationForm):
username = forms.CharField(widget=TextInput(attrs={'class': 'span2','placeholder': 'Email'}))
password = forms.CharField(widget=PasswordInput(attrs={'class': 'span2','placeholder':'Password'}))
I do what you want like this:
def login(request):
form = AuthenticationForm(request)
form.fields['username'].widget.attrs['class'] = "custom_css"
form.fields['password'].widget.attrs['style'] = "background:red"
return render_to_response("login.html", {'form':form},
context_instance=RequestContext(request))