Django admin inline UserProfile field - django

Every user has (should have) a UserProfile object, and every UserProfile can have Locations against it (foreign key in Location). I want to show these Locations (and allow editing/adding/deleting them) in the User view in the admin site. Nested inlines aren't possible, so I'd like to add a LocationInline to the User page, which I'm unsure how to do.
models.py
from django.db import models
from registration.models import User
class UserProfile(models.Model):
user = models.OneToOneField(User)
# ...
class Location(models.Model):
owner = models.ForeignKey(UserProfile)
# Address and stuff
admin.py
from django.contrib import admin
from django.contrib.auth.models import User
from main.models import UserProfile, Location
from django.contrib.auth.admin import UserAdmin as AuthUserAdmin
class UserProfileInline(admin.StackedInline):
model = UserProfile
max_num = 1
can_delete = False
class LocationInline(admin.TabularInline):
model = Location
extra = 1
class UserAdmin(AuthUserAdmin):
inlines = [UserProfileInline, LocationInline]
# Obviously doesn't work, because Location is from UserProfile, not User
# How can I make it use user.profile instead?
admin.site.unregister(User)
admin.site.register(User, UserAdmin)

Related

Django: Unknown field(s) (avatar) specified for User

So I have this models
from django.db import models
from django.conf import settings
# Create your models here.
class ProfileImage(models.Model):
user = models.OneToOneField(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
editable=False
)
avatar = models.ImageField()
def user_avatar(self):
return self.profileimage.avatar
And my admin.py
from django.contrib import admin
# Register your models here.
from django.contrib.auth.admin import UserAdmin
UserAdmin.fieldsets += ('Custom fields set', {'fields': ('avatar',)}),
I am using the User model, and I add to it a imagefield, but I want to see the image field in the admin page so a did that in admin.py but when I enter to the users admin this error appear:
Unknown field(s) (avatar) specified for User. Check fields/fieldsets/exclude attributes of class UserAdmin.
Well, what you should try to do is change your admin code and your models a little bit. Try this:
models.py
class Profile(models.Model):
user = models.OneToOneField(
verbose_name=_('User'),
to=settings.AUTH_USER_MODEL,
related_name='profile',
on_delete=models.CASCADE
)
avatar = models.ImageField()
and admin.py
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth import get_user_model
from django.contrib.auth.models import Group
from accounts.models import ProfileImage
User = get_user_model()
class ProfileInline(admin.StackedInline):
model = ProfileImage
max_num = 1
can_delete = False
class MyUserAdmin(UserAdmin):
inlines = [ProfileInline]
# unregister old user admin
admin.site.unregister(User)
admin.site.unregister(Group)
# register new user admin that includes a UserProfile
admin.site.register(User, MyUserAdmin)
Your code should look like this
updated
Models.py
from django.contrib.auth.models import User
from django.db import models
class ProfileImage(models.Model):
user = models.OneToOneField(User,
on_delete=models.CASCADE,
editable=False)
avatar = models.ImageField()
def user_avatar(self):
return self.profileimage.avatar
User.add_to_class('user_avatar', user_avatar)
admin.py
UserAdmin.fieldsets += ('Custom fields set', {'fields': ('user_avatar',)}),

How do i add other fields on Abstract User

This is my model. When i make migrations it is not showing up on my admin page.
class User(AbstractUser):
# TODO User will be associated with one or more chama accounts
id_number = models.IntegerField(default=0)
phone_number = models.IntegerField(default=0)
active_chama = models.ManyToManyField("Chama")
You will have to set the AUTH_USER_MODEL setting in your settings.py if you use the AbstractUser model to create a custom one.
AUTH_USER_MODEL = "myApp.User"
Here is the relevant part in the docs
Edit:
Like stated in the comments you will have to register your custom model in your custom user apps admin.py
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .models import User
admin.site.register(User, UserAdmin)

Adding extra field in admin for custom user in Django 1.11

I have a custom user model which is subclassed by AbstractUser with an added custom field.
# model.py
from django.db import models
from django.contrib.auth.models import AbstractUser
class CustomUser(AbstractUser):
ADM = 'admin'
MEMBER = 'member'
ROLE_CH = ((ADM, 'Administrator'), (MEMBER, 'Member'))
role = models.CharField(max_length=20, choices=ROLE_CH, blank=True)
This model is also registered as the default auth model in settings.py
# settings.py
AUTH_USER_MODEL = "main.CustomUser"
Then in admin.py as per the documentation, I create a custom form which extends UserCreationForm and then register it to the custom user.
# admin.py
from django.contrib import admin
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.admin import UserAdmin
from .models import CustomUser
class CustomUserCreationForm(UserCreationForm):
class Meta(UserCreationForm.Meta):
model = CustomUser
fields = UserCreationForm.Meta.fields + ('role',)
class CustomUserAdmin(UserAdmin):
add_form = CustomUserCreationForm
admin.site.register(CustomUser, CustomUserAdmin)
However, it does not work as expected. The Add User form remains the default one i.e. only username, password and password confirmation fields are present. The role field does not appear.
Use form attribute instead of add_form:
class CustomUserAdmin(ModelAdmin):
form = CustomUserCreationForm
admin.site.register(CustomUser, CustomUserAdmin)
UPD
First answer is correct only for ModelAdmin base class, since it doesn't have add_form attribute.
For UserAdmin you should update add_fieldsets attribute:
class CustomUserAdmin(UserAdmin):
add_fieldsets = UserAdmin.add_fieldsets + (
(None, {
'fields': ('role',),
}),
)
admin.site.register(CustomUser, CustomUserAdmin)
In this case you dont even required add_form.

Customizing the user model: how to show related info in the admin

Django 1.10.2
Studying customization of the User model.
Trying to follow the documentaion https://docs.djangoproject.com/en/1.10/topics/auth/customizing/#extending-the-existing-user-model
I wish to store that department and show it in the admin.
The problem is that department doesn't appear.
I played with fieldsets and list_display, but failed.
Could you help me understand how to show the department in the admin?
admin.py
from django.contrib.auth.models import User
from django.db import models
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from django.contrib.auth.models import User
class Employee(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
department = models.CharField(max_length=100)
# Define an inline admin descriptor for Employee model
# which acts a bit like a singleton
class EmployeeInline(admin.StackedInline):
model = Employee
can_delete = False
verbose_name_plural = 'employee'
# Define a new User admin
class UserAdmin(BaseUserAdmin):
inlines = (EmployeeInline, )
# Re-register UserAdmin
admin.site.unregister(User)
admin.site.register(User, UserAdmin)

AbstractUser Django full example

I am new to Django and I have been trying this for weeks, but could not find a way to solve this problem.
I want to store additional information like user mobile number, bank name, bank account. And want to store the mobile number while user registers and wants user to login with either (mobile number and password) or (email and password).
This is my UserProfile model
from django.db import models
from django.contrib.auth.models import User
from django.contrib.auth.models import AbstractUser
# Create your models here.
class UserProfile(AbstractUser):
user_mobile = models.IntegerField(max_length=10, null=True)
user_bank_name=models.CharField(max_length=100,null=True)
user_bank_account_number=models.CharField(max_length=50, null=True)
user_bank_ifsc_code = models.CharField(max_length=30,null=True)
user_byt_balance = models.IntegerField(max_length=20, null=True)
And this is my forms.py
from django import forms
from django.contrib.auth.models import User # fill in custom user info then save it
from django.contrib.auth.forms import UserCreationForm
from models import UserProfile
from django.contrib.auth import get_user_model
class MyRegistrationForm(UserCreationForm):
email = forms.EmailField(required = True)
mobile = forms.IntegerField(required=True)
class Meta:
model = UserProfile
fields = ('username', 'email', 'password1', 'password2','mobile' )
def save(self,commit = False):
user = super(MyRegistrationForm, self).save(commit = False)
user.email = self.cleaned_data['email']
user.user_mobile = self.cleaned_data['mobile']
user.set_password(self.cleaned_data["password1"])
user_default = User.objects.create_user(self.cleaned_data['username'],
self.cleaned_data['email'],
self.cleaned_data['password1'])
user_default.save()
if commit:
user.save()
return user
In my settings.py I have included
AUTH_USER_MODEL = "registration.UserProfile"
admin.py of my app is
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import User
from models import UserProfile
class UserProfileInline(admin.StackedInline):
model = UserProfile
can_delete = False
verbose_name_plural = 'userprofile'
class UserProfileAdmin(UserAdmin):
inlines = (UserProfileInline, )
admin.site.register(UserProfile, UserProfileAdmin)
While adding the user from admin I get this error
Exception at /admin/registration/userprofile/1/
<class 'registration.models.UserProfile'> has no ForeignKey to <class 'registration.models.UserProfile'>
Can someone help me with this or point out to the full working exapmle, I have seen Django documentation but didn't find any luck. Or if there is another way to do this.
Thanks in advance
Edit 1:
While registering from the registration form I'm also getting this error
DatabaseError at /register
(1146, "Table 'django_auth_db.auth_user' doesn't exist")
You have confused yourself a bit here. The idea of subclassing AbstractUser - and defining AUTH_USER_MODEL as your subclass - is that the new model completely replaces auth.models.User. You shouldn't be importing the original User at all, and you certainly should be calling User.objects.create_user(): your new model's manager now has its own create_user method.
Because of this, there's no reason to muck about with inline admins. Your UserProfile should be registered in the admin using the existing django.contrib.auth.admin.UserAdmin class.
Inlines forms assume that you have a Generic ForeignKey on your model, in this case, the UserProfileAdmin expect a Generic ForeignKey of the UserProfile, that does not exists. Try to do a regular Model Admin, like:
class UserProfileAdmin(admin.ModelAdmin):
can_delete = False
verbose_name_plural = 'userprofile'
admin.site.register(UserProfile, UserProfileAdmin)