0

I surfed the web for something like this but I find only frontend solutions or obsolete guides. I wish to allow staff users to edit some default info such as first_name, last_name, email but also other extra info such bio, telephone, etc. I created a Profile class with a OneToOneField relation to User as suggested here but in this way only superuser can edit these informations. If I give can_change_user permission to the staff group each "staff" user can edit any profile.

edit these are the files of my app named users

#admin.py - users

class ProfileInline(admin.StackedInline):
    model = Profile
    can_delete = False
    verbose_name_plural = 'Profile'
    fk_name = 'user'

class CustomUserAdmin(UserAdmin):
    inlines = (ProfileInline, )

    def get_inline_instances(self, request, obj=None):
        if not obj:
            return list()
        return super(CustomUserAdmin, self).get_inline_instances(request, obj)


admin.site.unregister(User)
admin.site.register(User, CustomUserAdmin)  

#models.py - users

class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    extra_info = models.CharField(max_length=30, blank=True)    

@receiver(post_save, sender=User)
def create_or_update_user_profile(sender, instance, created, **kwargs):
    if created:
        Profile.objects.create(user=instance)
    instance.profile.save() 

EDIT 1: I edited the two classes in this way

class ProfileInline(admin.StackedInline):
    model = Profile
    can_delete = False
    verbose_name_plural = 'Profilo'
    fk_name = 'user'

    def has_change_permission(self, request, obj=None):
        print("utente:")
        print(request.user)
        if obj == request.user:
            return True
        else:
            return False    


class CustomUserAdmin(UserAdmin):
    inlines = (ProfileInline, )

    # this function prints error *"get_queryset() missing 1 required positional argument: 'request'"*  
    '''
    def get_queryset(self, request):
        queryset = super(CustomUserAdmin, self).get_queryset()
        queryset = queryset.filter(user=self.request.user)
        return queryset
    '''

    def get_fieldsets(self, request, obj=None):
        if not request.user.is_superuser:
            if obj == request.user:
                fieldsets = (
                (('Personal info'), {'fields': ('first_name', 'last_name', 'email')}),
                )
            else:
                fieldsets = ()
        else:
            fieldsets = self.fieldsets

        return fieldsets


    def get_inline_instances(self, request, obj=None):
        if not obj:
            return list()
        return super(CustomUserAdmin, self).get_inline_instances(request, obj)


admin.site.unregister(User)
admin.site.register(User, CustomUserAdmin)  

why does "#1" appears until the user fills in the field? #1 is is shown until the user fills in the field

bit
  • 427
  • 1
  • 6
  • 14
  • and what do want? you say you want to "allow staff users to edit some info..." and then complain "each staff user can edit any profile". Isn't that what you want? note "can_change_user" means changing the `User` model, not the `Profile` model. you probably want to give "can_change_profile". – dirkgroten May 07 '19 at 12:57
  • hi @dirkgroten I updated my original post. I simply wish to allow each user with "staff role" to update **only** his profile via backend, as it happens for "change_password" page. I also tried to give "can_change_profile" (users | profile | Can change profile) but there is not any link to theri profile page. – bit May 07 '19 at 15:48
  • override the [`has_change_permission()`](https://docs.djangoproject.com/en/2.2/ref/contrib/admin/#django.contrib.admin.ModelAdmin.has_change_permission) method on the `ModelAdmin`. Since it has the `request`, you can check if `obj == request.user.profile` – dirkgroten May 07 '19 at 15:51
  • I tried to add `def has_change_permission(request, obj): if obj == request.user.profile: return True else: return False` in CustomUserAdmin but it returns "'CustomUserAdmin' object has no attribute 'user' ". – bit May 07 '19 at 16:27
  • That error shows you’re doing `self.user` somewhere. But you should do this in `ProfileInline` if you’re testing for the profile. In `customUserAdmin` you should test `obj == request.user` to test for the actual user. – dirkgroten May 07 '19 at 16:31
  • @bit Either write the decorator, or give everyone the opportunity to edit the profile, but in the template to do type checking (f.e. `if request.user == user`) –  May 07 '19 at 18:10
  • I updated my original post. So, I have some issues: 1) in "extra_info" field, why does "#1" appears until the user fills in the field? 2) If I try to update my profile I have the error __"KeyError at /admin/auth/user/7/change/ 'password' "__ 3) I tried to implement get_queryset function to show only the logged users in /admin/auth/user list but it doesn't works – bit May 09 '19 at 12:06

0 Answers0