Making different registration forms in Django? - django

I'm trying to create two different types of users in Django using AbstractUser. I've created two models that inherit from my AbstractUser model.
How do I update the UserCreationForm so that it has a field for user type?

Just override the built-in UserCreationForm and adjust the fields as necessary.
class CustomUserCreationForm(UserCreationForm):
class Meta:
model = CustomUser
fields = UserCreationForm.Meta.fields + ('type',)

Related

Django model formset : customize empty form fields

If I have a view that shows a formset of users for administration purpose (easy CRUD approach for admin like admin page).
I want the instance forms to show normal data like 'username', 'first_name', 'last_name', 'email', but in empty form (adding new user) I want to add extra field for 'password'.
To be precise, in formset model table view, the admin can give password to new user but can't change or view password of existing user.
how to achieve that ?
I've tried to split fields in forms like this:
from django.forms import ModelForm, Form
class UserForm(ModelForm):
class Meta:
model = User
# change to user data only fields
fields = ['username','first_name','last_name', 'email']
class UserControlForm(ModelForm):
class Meta:
model = User
# add user permissions fields
fields = ['password','groups','is_active', 'is_superuser']
but still can't figure out how to apply the approach within formset table view

django-import-export to export User model

I'm using the django-import-export library with success to provide a data download option via the django admin for some of my defined models.
I'm having difficulty however providing the same export option via the User Admin.
For my other models I've done something like the following to my admin.py:
class OtherResource(resources.ModelResource):
class Meta:
model = Other
class OtherAdmin(ExportMixin, admin.ModelAdmin):
# Other admin definition here
My problem is providing the same Export functionality to pre-packaged Django models like User.
I tried the following...
class UserResource(resources.ModelResource):
class Meta:
model = User
class UserAdmin(ExportMixin, UserAdmin):
pass
But this has a couple problems,
It drops a bunch of the User model fields from the list display (like is_active and groups)
I can see that something is not fully connected because adding exclude's to the UserResource is not excluding those fields from the export
I could re-create the UserAdmin on my end, but I'm hoping (and guessing) that's unnecessary.
Any ideas?
So I was making a couple of mistakes.
I was being an idiot (I was importing the django UserAdmin rather than the UserAdmin I had created as an override a couple years ago in a dependency to this project -- this explains why fields were dropped when overriding the UserAdmin)
I was failing to manually link the OtherResource to the OtherAdmin as explained in the django-import-export docs
The solution to both of the above code samples is as follows:
For the Other model
class OtherResource(resources.ModelResource):
class Meta:
model = Other
class OtherAdmin(ExportMixin, admin.ModelAdmin):
resource_class = OtherResource
# Other admin definition here
and for the User model
class UserResource(resources.ModelResource):
class Meta:
model = User
fields = ('first_name', 'last_name', 'email')
class UserAdmin(ExportMixin, UserAdmin):
resource_class = UserResource
pass
admin.site.unregister(User)
admin.site.register(User, UserAdmin)
Viola.
Everything works as intended.
Other model is exported in full.
User model is exported as 3 columns (first name, last name, and email).
Imports required
from import_export import resources
from import_export.admin import ExportMixin
from django.contrib.auth.models import User
from django.contrib.auth.admin import UserAdmin
if you want to import export in user models in Django then override this code in your application admin.py
from import_export import resources
from import_export.admin import ExportMixin
from django.contrib.auth.models import User
from django.contrib.auth.admin import UserAdmin
from import_export.admin import ImportExportModelAdmin
# Register your models here.
class UserResource(resources.ModelResource):
class Meta:
model = User
fields = ('id','username','first_name', 'last_name', 'email')
# class UserAdmin(ExportMixin, UserAdmin):
# resource_class = UserResource
# pass
class UserAdmin(ImportExportModelAdmin):
list_display = ('id','username','first_name', 'last_name', 'email')
# list_filter = ('created_at',)
resource_class = UserResource
pass
admin.site.unregister(User)
admin.site.register(User, UserAdmin)

How to extend UserCreationForm with fields from UserProfile

I found this post on how to extend the UserCreationForm with extra fields such as "email." However, the email field is already defined in the pre-built user model.
I created an extra model (called UserProfile) that futher extends Django's pre-built User class. How do I get these fields I defined in UserProfile to appear in my UserCreationForm?
Add fields as appropriate for your UserProfile model (it's not too easy to use a ModelForm to avoid Repeating Yourself, unfortunately), then create and save a new UserProfile instance in the over-ridden save() function. Adapted from the post you linked to:
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
class UserCreateForm(UserCreationForm):
job_title = forms.CharField(max_length=100, required=True)
age = forms.IntegerField(required=True)
class Meta:
model = User
def save(self, commit=True):
if not commit:
raise NotImplementedError("Can't create User and UserProfile without database save")
user = super(UserCreateForm, self).save(commit=True)
user_profile = UserProfile(user=user, job_title=self.cleaned_data['job_title'],
age=self.cleaned_data['age'])
user_profile.save()
return user, user_profile

Django Admin: how to display fields from two different models in same view?

My site makes use of Django's User Authentication User model and a custom UserProfile model to store some additional data (birthday, etc.). Is there a way to create a view in Django admin that weaves together fields from both the User and UserProfile models?
I suspect that this code snippet is not even close, but maybe it will help illustrate what I'm trying to do:
from django.contrib import admin
from django.contrib.auth.models import User
from userprofile.models import UserProfile
class UserProfileAdmin(admin.ModelAdmin):
list_display = ('name', 'gender', 'User.email') #user.email creates the error - tried some variations here, but no luck.
admin.site.register(UserProfile, UserProfileAdmin)
Error message:
ImproperlyConfigured: UserProfileAdmin.list_display[2], 'User.email' is not a callable or an attribute of 'UserProfileAdmin' or found in the model 'UserProfile'.
Ultimately, I'm trying to create an admin view that has first & last name from UserProfile and email from User.
for displaying user email you need to have a method on UserProfile or UserProfileAdmin that returns the email
on UserProfile
def user_email(self):
return self.user.email
or on UserProfileAdmin
def user_email(self, instance):
return instance.user.email
then change your list_display to
list_display = ('name', 'gender', 'user_email')
Related docs: ModelAdmin.list_display
You could try using InlineModelAdmin to display both User and UserPofile forms in a admin view.
To display user profile information in change list you can create a new method that delegates the values from UserProfile to User model.
For example this should work more or less :)
from django.contrib import admin
from django.contrib.auth.models import User
from my_models import UserProfile
class UserProfileInline(admin.StackedInline):
model = UserProfile
fk_name = 'user'
class UserAdmin(admin.ModelAdmin):
list_display = ['get_userprofile_name', 'email']
list_select_related = True
inlines = [
UserProfileInline,
]
def get_userprofile_name(self, instance):
# instance is User instance
return instance.get_profile().name
admin.site.unregister(User)
admin.site.register(User, UserAdmin)
Using Ashoks top answer i made snippet that simplifies this process for large number of fields
class ColumnViewer(object):
pass
column_list = ('name', 'surname', )
for col in column_list:
setattr(ColumnViewer, col, lambda s,i : getattr(i, col))
#admin.register(UserProfile)
class UserProfileAdmin(admin.ModelAdmin, ColumnViewer):
list_display = column_list

After extending the User model in django, how do you create a ModelForm?

I extended the User model in django to include several other variables, such as location, and employer. Now I'm trying to create a form that has the following fields:
First name (from User)
Last name (from User)
Location (from UserProfile, which extends User via a foreign key)
Employer (also from UserProfile)
I have created a modelform:
from django.forms import ModelForm
from django.contrib import auth
from alert.userHandling.models import UserProfile
class ProfileForm(ModelForm):
class Meta:
# model = auth.models.User # this gives me the User fields
model = UserProfile # this gives me the UserProfile fields
So, my question is, how can I create a ModelForm that has access to all of the fields, whether they are from the User model or the UserProfile model?
Hope this makes sense. I'll be happy to clarify if there are any questions.
You can either create two model forms (one for User and one for UserProfile) or create a custom form with all your fields and dispatch them in your view.
from django import forms
class ContactForm(forms.Form):
first_name = forms.CharField()
last_name = forms.CharField()
location = forms.CharField()
employer = forms.CharField()
You can't. ModelForm expects all its fields to come from a single model. Create a child of Form and pull the field definitions from the models.