Django Customizing authentication user results in 2 fields in admin - django

I've followed https://docs.djangoproject.com/en/1.5/topics/auth/customizing/#extending-the-existing-user-model to add a ManyToMany field for what games a user has played.
class Profile(models.Model):
""" Extended authentication profile storing specific info """
user = models.OneToOneField(User)
owned = models.ManyToManyField(OwnedStruct)
then add to admin by the following
class ProfileInline(admin.StackedInline):
""" Show profile inline with user """
model = Profile
verbose_name_plural = 'profile'
class UserProfileAdmin(UserAdmin):
""" Add inline to User """
inlines = (ProfileInline,)
...
admin.site.unregister(User)
admin.site.register(User, UserProfileAdmin)
In the database things look fine, but in the admin I see two fields representing the ManyToMany OwnedStruct. Before messing with the user, it shows the first as "Profile #1" and the second as "Profile #2". After selecting some options from Profile 1's M2M and clicking save, it appears to update that field correctly. If I update Profile#2, it does not save or work or appear to change anything. I'd expect it to only show one. What could cause two Profiles?

If I understand correctly the problem is that for some reason django admin doesn't care about OneToOneField and create more than one inline forms for the Profile. You can try to fix that with adding max_num = 1 to your ProfileInline class.
It must look something like:
class ProfileInline(admin.StackedInline):
""" Show profile inline with user """
model = Profile
max_num = 1
verbose_name_plural = 'profile'

Related

why can't I log in into any account until I reset its password in django admin?

I have a Profile model that has a one to one relationship with the User model from django.contrib.auth.models , when I add a new profile from the admin panel I noticed that the password field is not transformed into dots when typing , it shows the actual password , that's not the issue though , the issue is , when ever I create a new profile which in turns creates a new User , and mark the is staff attribute as true, I can't log in into the admin panel with that created account, unless I reset the password manually with
python manage.py changepassword the-user-name
after I have reset the password and only then even with the same password, I can log in into the account normally, does anybody know why is that happening ?
I made sure it's not a mistake in typing the password and I tried it several times until I made sure that this is what is actually happening
Update
when I enter the Users model from the Authentication and Authorization section opposed to entering it from the app name, I find that written besides the password section
Invalid password format or unknown hashing algorithm
how can I fix it ?
I forgot to say that I am using an UpdateView from generic views , and using the model Profile as the the model attribute set on that view
the code of my update view
class ProfileUpdate(UpdateView):
model = Profile
fields= [
'username',
'bio',
'avatar_thumbnail',
'location',
'tags',
'contact_information'
]
def get_object(self):
return Profile.objects.get(pk = self.kwargs.get('user_pk'))
def get_queryset(self):
base_qs = super(ProfileUpdate, self).get_queryset()
return base_qs.filter(username=self.request.user.username)
That would inherit from ModelAdmin instead of UserAdmin in your admin.py.
Can you instead try this:
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import User
from app.models import Profile
class ProfileAdmin(UserAdmin):
def __init__(self, *args, **kwargs):
super(UserAdmin,self).__init__(*args, **kwargs)
UserAdmin.fieldsets += (('profile', {'fields': ('attr1', 'attr2')}),)
admin.site.unregister(User)
admin.site.register(Profile, ProfileAdmin)
Explanation
When you registered the Profile admin like so, admin.site.register(models.Profile), internally it was inheriting from ModelAdmin class which is perfect for all other classes. But for User we need hashing for saving the passwrd field, so there is a separate class UserAdmin that must be inherited from.
Once you inherited, the password issue was resolved but since the base model was UserAdmin, only user related fields were showing. We needed to append the profile fields for which we added the __init__ method and appended the profile fields to the admin section.

Django 1.11 admin form add search box to oneToOne field

I have a user, admin and employee models, both employee and admin are related to the user model with a oneToOne field what i would like to do is in the admin form i have one field "user"
instead of having a drop down field with all users i would like to have a search box so that when i search for a specific user i find him and choose him to be an admin.
how?
i also tried to add user's fields to admin's form but i couldn't
i tried the inline thing, the parent_link in the admin's model... but i couldn't find a solution
Now i would like to minimise the search through the long users list by adding a search box to the field
I have solved this type of problem using django-ajax-selects package. Hope this will help you.
app/admin.py:
from ajax_select import register, LookupChannel
#register('users')
class UsersLookup(LookupChannel):
model = User
def get_query(self, q, request):
return self.model.objects.filter(username__icontains=q)
class EmployeeAdminForm(forms.ModelForm):
user = AutoCompleteSelectField('users', required=False,
help_text=None)
class Meta:
model = Employee
fields = '__all__'
settings.py
AJAX_LOOKUP_CHANNELS = {
'users' : {'model': 'auth.user', 'search_field': 'username'},
}
Use django's raw_id_fields. With that you can declare a foreign key object searchable.

list_display in admin behave nothing

This is my github repo Inout. I am learning django and i worked Very very simple django registration & login system.
My question is:
How to list all the usernames in admin using list_display. But nothing display in admin panel. May i know why ?
Inside my working code:
# models.py
username = models.OneToOneField(User)
first_name = models.CharField(max_length=100)
# admin.py
class SignupAdmin(admin.ModelAdmin):
list_display = ['username']
admin.site.register(Signup, SignupAdmin)
Information for you Reference :
if i am using list_filter in admin i can see all the username in the filter panel
Then if i am accessing this page http://127.0.0.1:8000/admin/system/signup/
Select signup to change
0 signups
And also if i am accessing this page http://127.0.0.1:8000/admin/frontend/profile/add/ i can see the drop down of username shows all the username i registered before.
What i missing ? or can somebody clone my repo and see yourself.
Are you sure it's not working correctly? list_display is supposed to take a tuple/list of fields and then display those fields as columns of the main table like in the picture shown below taken from the django admin documentation, where each entry in the main table has a username, email address, first name, last name, staff status. This would be created by
list_display = ['username', 'email', 'first_name', 'last_name', 'is_staff']
in a ModelAdmin for the built in User model (taken from django.contrib.auth.models). The side-column on the right side (with the label "Filter") is populated only when you define fields under list_filter.
Note if you only defined one field, and your model has a __unicode__ function that returns the username, you will not see a significant difference with just adding list_display = ('username',). I suggest you try list_display = ('username', 'first_name',). In this case, for every SignUp you will see two columns in the main table -- one with the username and one with the first_name.
EDIT
You have two errors.
First, you don't seem to have created any SignUp objects anywhere. Before the admin change list will display any entries, you must create some entries.
Second, your __unicode__ method of your SignUp model refers to non-existent fields (self.user is never defined -- in your SignUp class you used username = models.OneToOneField(User)
, hence you refer to it as username) and furthermore it doesn't return a unicode string as required.
Try:
def __unicode__(self):
if self.username:
return unicode(self.username)
then create some SignUp and then it will work. Again, the list_display part was working perfectly.

Django Interleaving UserProfile with Profile in Admin

I have a User Profile which is currently shown in the Admin via a Stacked Inline. However because I have fields such as last_name_prefix and last_name_suffix (for foreign names such as Piet van Dijk to cover proper sorting by last name) I would like to be able interleave the user profile fields with the normal change user fields. So in the Change User admin interface it would appear like this:
First Name:
Last Name Prefix:
Last Name
Last Name Suffix:
I have tried this solution: http://groups.google.com/group/django-users/browse_thread/thread/bf7f2a0576e4afd1/5e3c1e98c0c2a5b1. But that just created extra fields in the user form that weren't actually coming from the user profile (they stayed empty even though they should get values from the user profile).
Could someone explain to me if this could be done and how?
Thanks very much!
I'm pretty sure you'd need to overwrite normal User admin.
What I would actually do is create a special forms.ModelForm for UserProfile called, say UserProfileAdminForm which included fields from the User model as well. Then you'd register UserProfile for admin and the save function for the UserProfileAdminForm would capture the user-specific fields and either create or update the User record (This is left as an exercise to the OP).
More info
When I say add more fields to a form, I mean manually add them:
class UserProfileAdminForm(forms.ModelForm):
username = forms.CharField(...)
email = forms.EmailField(...)
first_name = ...
last_name = ...
def __init__(self, *args, **kwargs):
super(UserProfileAdminForm, self).__init__(*args, **kwargs)
profile = kwargs.get('instance', None)
if profile and profile.user:
self.user = profile.user
self.fields['username'].initial = self.user.username
self.fields['last_name'].initial = ...
...
class Meta:
model = UserProfile
This question has been solved by the new Django version 1.5: https://docs.djangoproject.com/en/1.5/topics/auth/customizing/#auth-custom-user.

Automatic author in Django admin

all. I'm working on the admin for my django site, and I've run into an obstacle.
I've got an Entry model and a Related model. The Related model has two foreign key fields: one to the Entry model (entry) and one to django's User model (author). The Related model is considered a "sub-model" of the Entry model, and each user can only have one Related per Entry.
In the admin, Related is edited inline with Entry. As I have it, the admin shows only one extra Related at a time, and it automatically fills the author field with the current user:
from django.contrib import models
from django.contrib.auth.models import User
class Entry(models.Model):
pass
class Related(models.Model):
entry = models.ForeignKey(Entry)
author = models.ForeignKey(User)
class Meta:
unique_together = ('entry', 'author')
from django.contrib import admin
class RelatedInline(admin.StackedInline):
model = Related
exclude = ('author',)
max_num = 1
class EntryAdmin(admin.ModelAdmin):
inlines = (RelatedInline,)
def save_formset(self, request, form, formset, change):
instances = formset.save(commit=False)
for instance in filter(lambda obj: isinstance(obj, Related), instances):
if instance.__dict__.get('author', None) is None:
instance.author = request.user
instance.save()
formset.save_m2m()
The problem is that if a user wants to edit an entry which already has a Related by anyone, then only that one related field will be shown.
If possible, I wonder if anyone has any ideas about how I could keep a setup similar to this, but have the admin automatically display the user's related if it exists and an empty form if it doesn't. Barring that, I would just get rid of the line max_num = 1 and replace it with extra = 1. Of course, this would mean that a "new related" form would show even if the user already had one for the current entry, so I wonder if anyone has any idea about how I would catch a possible IntegrityError and let the user know that an error had occurred.
It turns out this is pretty simple. You just need to add a queryset function to your RelatedInline class, specifying which inline to show. If the returned queryset has at least one member, the first will be shown. If the queryset is empty, a single blank inline will be shown!
class RelatedInline(admin.StackedInline):
model = Related
exclude = ('author',)
max_num = 1
def queryset(request):
return Related.objects.filter(author = request.user)