Django graphql auth not showing all user fields in mutation - django

I have followed below tutorial to introduce user authentication in my django app.
https://django-graphql-auth.readthedocs.io/en/latest/quickstart/
It has created the user mutations as below,
Graphql user mutation
The mutation to update user shows only two fields, first name and last name. However my user model has other fields as well like is_staff, is_superuser, gender.
I would like to get control on updating those fields as well.
Please advise how can I get that done?

I fixed it by adding below code to the app settings,
GRAPHQL_AUTH['UPDATE_MUTATION_FIELDS'] = [
'first_name',
'last_name',
'is_staff',
'is_active',
'gender',
]

Related

How to remove specific fields from the django User Model?

From the Django User Model, I'd like to remove some fields such as 'first_name', 'last_name', 'email', 'date_joined'.
I want no changes in the Auth system of the User Model, i.e. I still want authentication to be done using the username. I just want to remove some unrequired fields.
Will I need to extend the AbstractBaseUser model for this, or can this be achieved just by extending the AbstractUser model?
Or is there any other way also to do this ?
Thanks in advance !

django custom user model groups and permissions

I am trying to implement custom user model in my django application.
If I just copy and paste the code from this article, it works great. But I wish this custom user model to have permissions and groups. So I added this inheritance to models.py:
class MyUser(AbstractBaseUser, PermissionsMixin):
and these fields into the admin.py MyUserAdmin(UserAdmin) class:
('Permissions', {'fields': (
'is_admin', 'is_staff', 'is_active', 'groups', 'user_permissions',
)}),
But it looks strange for me:
As I know, it must be two containers: left (that I have) that shows all available groups and permissions and right (that I don't have) that shows all current user's groups and permissions.
P.S. I tried google for it and found only one post on reddit which is 10 month old but doesn't have a solution.
Deleting this line in MyUserAdmin class fixed the problem up.
filter_horizontal = ()
You must set argument in filter_horizontal(ARGUMENT),
the argument is your field manyToMany in model.
Example:
class CustomUser(PermissionsMixin, AbstractBaseUser):
custom_groups = models.ManyToManyField('CustomUserGroups', blank=True)
class CustomUserAdmin(UserAdmin):
filter_horizontal = ('custom_groups', )

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.

Suppressing SAVE of object in POST - Django Rest Framework

This is related to the question : Assymetric nature of GET and POST in a Django REST framework Serializer . I've put it as a fresh question, instead of putting more questions in that thread, accordingly to SO guidelines
I am writing a Viewset and a ModelSerializer for the User model to provide a /user endpoint
GET - returns list and information about all users, in the standard DRF way
POST - all I want the client to post is the facebook access_token (hence have put all other fields as read_only in serializer. The pre_save() in ViewSet is wired to use this access token and it uses django-facebook to pull data from facebook api (using access token) and automatically create a new user with that information. Since this new user is created automatically, I want to suppress the normal DRF flow during POST and not create another user via DRF. How do i do this?
views.py
from open_facebook import OpenFacebook
from django_facebook.api import FacebookUserConverter
from django_facebook.connect import connect_user
class UserViewSet(viewsets.ModelViewSet):
queryset = models.User.objects.all()
serializer_class = UserSerializer
def pre_save(self, obj):
access_token = obj.access_token
facebook = OpenFacebook(access_token)
conv = FacebookUserConverter(facebook)
action, user = connect_user(self.request, access_token)
# this creates an entire new row, just as required, in the variable "user", so all I want to do is suppress any other row creation in the standard POST method. connect_user fills in data like first_name, last_name, etc from facebook already, and that is exactly what I need to do.
conv.get_and_store_friends(user)
obj = user
user.delete()
# I am trying to do that by copying user to obj and deleting user, but at the end of it i
print obj.username
serializers.py
class UserSerializer(serializers.HyperlinkedModelSerializer):
"""
User Serializer
"""
class Meta:
model = models.User
fields = ('id', 'username', 'first_name', 'last_name', 'activities', 'image_url', 'url', 'access_token')
read_only_fields = ('username', 'first_name', 'last_name', 'image_url', 'activities') #todo: find out a shortcut to invert selection
# show activities with user details rather than separately to remove an extra server call
depth = 1
using the create() function of ModelViewSet worked, instead of pre_save - to suppress saving the object

Django auth - Adding user fields - displaying in admin

I'm a complete n00b to django & python. I come from a PHP background so you'll have to accept my apologies for that :p.
I'm trying to use the admin panel functionality in django to show different options to different people.
The system should allow admins to add "projects" to a list. "Developers" should then be able to view only projects assigned to them, and only change certain fields.
So I guess the question is two fold:
1) Is allowing the "Developers" to login to the admin system the best method of doing it?
1.a) If so, How do I get a boolean field to display on the admin's user form? I just want to flag is_developer. I've added it as a userProfile but don't understand how to make it display on the form
2) Should I disallow them to login (to the admin panel) and make "frontend" whereby they can only see what they're allowed?
I hope that made sense. I'm a bit all over the place at the moment as it's a complete departure to what i'm used to!
Thanks in advance for any help you can offer me :)
There's a lot going on here, so I'm going to piecemeal my answer.
Is allowing the "Developers" to login to the admin system the best method of doing it?
That depends on your setup. Generally, the admin should only be available to "staff": people that are employed by or directly related to your organization. In fact, in order to login to the admin, a user must have is_staff=True. If all of the users belong to your organization (and can be considered "trusted" as a result), then yes, it's fine to allow them to all access the admin. Otherwise, it's not a good idea, as you're opening yourself up to security risks.
If so, How do I get a boolean field to display on the admin's user form?
In the most simplistic sense, you can add a field to a form by literally adding it to the form class, even if it's a ModelForm which pre-populates its fields from the fields on the model.
class MyModelForm(forms.ModelForm):
class Meta:
model = MyModel
is_developer = forms.BooleanField(default=False)
I've added it as a userProfile but don't understand how to make it display on the form
UserProfile is a different model, obviously, so its fields are not made available on a form for a User. However, Django does provide the ability to add/edit related models inline with edit form for another model. This is done through inline formsets. In the admin, these are just called "inlines".
class UserProfileInlineAdmin(admin.StackedInline):
model = UserProfile
max_num = 1
can_delete = False
class UserAdmin(admin.ModelAdmin):
inlines = [UserProfileInlineAdmin]
The view you get from an inline admin is clearly distinct from the main form (in this case, that of User), though. You can try it out to see what I mean. It's not horrible, but it's still a noticeable break in the form. The reason I mentioned how to add a field to a form earlier, is that if you wanted, you can make it look all like one form with a little bit of clever misdirection.
class UserAdminForm(forms.ModelForm):
class Meta:
model = User
is_developer = forms.BooleanField(default=False)
def save(self, commit=True):
user = super(UserAdminForm, self).save(commit=commit)
if user.pk:
profile = user.get_profile()
profile.is_developer = self.cleaned_data.get('is_developer')
profile.save()
That's a simplistic example, but the idea is that you add the field(s) manually to the form, and then use them to actually update the other object manually when the main object being edited is saved.
Special notes related to User
Now, since you're dealing with User here, there's a lot more sticky details. First, User already has a UserAdmin and its own forms -- yes plural, forms. If you want to add new functionality, you need to make sure you keep the existing Django functionality in the process.
from django.contrib.auth.admin import UserAdmin
form django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
class CustomUserCreationForm(UserCreationForm):
# do stuff
class CustomUserChangeForm(UserChangeForm):
# do stuff
class CustomUserAdmin(UserAdmin):
form = CustomUserChangeForm
add_form = CustomUserCreationForm
admin.site.unregister(User)
admin.site.register(User, CustomUserAdmin)
Also, UserAdmin has its own set of fieldsets defined. The defaults are:
fieldsets = (
(None, {'fields': ('username', 'password')}),
(_('Personal info'), {'fields': ('first_name', 'last_name', 'email')}),
(_('Permissions'), {'fields': ('is_active', 'is_staff', 'is_superuser', 'user_permissions')}),
(_('Important dates'), {'fields': ('last_login', 'date_joined')}),
(_('Groups'), {'fields': ('groups',)}),
)
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('username', 'password1', 'password2')}
),
)
If you want to add a field or fields, you'll need to redefine those two attributes with your fields added where you want them.