I want to restrict my worker users' admin panel - don't want them to create users or delete certain types of models, for instance.
Here's some code in models.py that sets up my custom user, and the post_save signal to add users.
Note that I set default_permissions = () so that users don't start with any permissions, but then I grant them the permissions of the group with name=workers which does NOT include myapp.myuser_add, thus they shouldn't be able to add more users when logged into admin console.
# models.py
from django.db import models
from django.contrib.auth.models import (
BaseUserManager, AbstractBaseUser, PermissionsMixin, Group
)
from django.db.models.signals import post_save
from django.dispatch import receiver
#receiver(post_save, sender=settings.AUTH_USER_MODEL)
def apply_worker_group(sender, instance=None, created=False, **kwargs):
if instance.is_worker:
try:
worker_group = Group.objects.get(name='workers')
if instance not in worker_group.user_set.all():
instance.groups.add(worker_group)
instance.save()
except Group.DoesNotExist:
pass
class MyUser(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(
verbose_name='email address',
max_length=255,
unique=True,)
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
is_worker = models.BooleanField(default=False)
# ... skipping a bunch of stuff
class Meta:
default_permissions = () # (!) ALL USERS HAVE NO PERMS TO START
#property
def is_staff(self):
# so workers can log into the admin panel
return self.is_admin or self.is_worker
Then in my admin.py:
# admin.py
from django.contrib.auth.admin import UserAdmin
from django.contrib import admin
from myapp.models import MyUser
class MyUserAdmin(UserAdmin):
pass
class MyAdminSite(admin.AdminSite):
pass
admin_site = MyAdminSite(name='myadmin')
admin_site.register(MyUser, MyUserAdmin)
But when I create a user under my superuser account with is_worker=True, I can still log in with that created user to admin panel and create more users! Which is not what I want.
Any suggestions for how to restrict user permissions using groups like this?
Related
I created a Django API to create a new user. However, when I try to create a user I get the error message:
IntegrityError at /api/v1/users/register/ NOT NULL constraint failed: accounts_user.user_id
This is what I have in models.py
from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver
class User(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
name = models.CharField(max_length=100, blank=True)
location = models.CharField(max_length=100, blank=True)
password = models.CharField(max_length=32)
email = models.EmailField(max_length=150)
signup_confirmation = models.BooleanField(default=False)
def __str__(self):
return self.user.username
#receiver(post_save, sender=User)
def update_profile_signal(sender, instance, created, **kwargs):
if created:
User.objects.create(user=instance)
instance.profile.save()
In serializers.py
from rest_framework import serializers
from .models import User
class UserSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = User
fields = ('user_id', 'name', 'location', 'password', 'email', 'signup_confirmation')
and my views.py
from rest_framework import viewsets
from .serializers import UserSerializer
from .models import User
from rest_framework.decorators import action
from .forms import SignUpForm
from .tokens import account_activation_token
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all().order_by('name')
serializer_class = UserSerializer
#action (detail=True, methods=['post'])
def register(self, request):
print(request)
Any ideas on what I can do to resolve this error
As John wrote in a comment:
Here you have a problem: fields = ('user_id',...).
I also advise you to change your User model. If you don't need separating (I suppose you don't), it is way better to create your User with inheritance directly from AbstractUser instead of creating in fact doubled User models.
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
...
In this way you will already have username, password and email, but you can add anything else in same model, instead of using user.user etc.
This is the image of the default Django User fields.
models.py:
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class Visitor(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
phone = models.IntegerField()
admin.py:
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from django.contrib.auth.models import User
from accounts.models import Visitor
class VisitorInline(admin.StackedInline):
model = Visitor
can_delete = False
verbose_name_plural = "visitor"
class UserAdmin(BaseUserAdmin):
inlines = (VisitorInline,)
admin.site.unregister(User)
admin.site.register(User, UserAdmin)
This image has the default Django user fields such as username, email address, first name and last name. I want to add a custom field such as a phone number to the existing fields. How can I achieve this? Thank you!
I’m trying to get the username of the current logged in user using OneToOneField to populate in the admin once the user submits a form.
The username should go in the user column of admin.py.
I’ve tried various methods and still no luck. I’m new to this and this is my first Django application I’m building so I’m not sure what I’m missing.
I’m stuck and have no idea what I’m doing so any help is gladly appreciated.
Can someone please help? What am I missing?
Thanks!
Code Below:
user_profile/models
from django.db import models
from django.urls import reverse
from django.contrib.auth.models import AbstractUser, UserManager
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.conf import settings
from users.forms import CustomUserCreationForm, CustomUserChangeForm
from users.models import CustomUser
class Listing (models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, null=True)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
name = models.CharField(max_length=100)
address = models.CharField(max_length=100)
zip_code = models.CharField(max_length=100)
mobile_number = models.CharField(max_length=100)
cc_number = models.CharField(max_length=100)
cc_expiration = models.CharField(max_length=100)
cc_cvv = models.CharField(max_length=100)
def create_profile(sender, **kwargs):
if kwargs['created']:
user_profile = Listing.objects.create(user=kwargs['instance'])
post_save.connect(create_profile, sender=User)
user_profile/admin.py
from django.contrib import admin
from django.contrib.auth import get_user_model
from django.contrib.auth.admin import UserAdmin
from user_profile.forms import HomeForm
from user_profile.models import Listing
# Register models here.
class UserProfileAdmin(admin.ModelAdmin):
list_display = ['name', 'address', 'zip_code', 'mobile_number', 'created', 'updated', 'user']
list_filter = ['name', 'zip_code', 'created', 'updated', 'user']
admin.site.register(Listing, UserProfileAdmin)
#admin.site.unregister(Listing)
master_application/settings.py
AUTH_USER_MODEL = 'users.CustomUser'
AUTH_PROFILE_MODULE = 'users.UserProfile'
users/models.py
from django.contrib.auth.models import AbstractUser, UserManager
from django.contrib.auth.models import User
from django.db import models
from django.urls import reverse
class CustomUserManager(UserManager):
def get_by_natural_key(self, username):
case_insensitive_username_field = '{}__iexact'.format(self.model.USERNAME_FIELD)
return self.get(**{case_insensitive_username_field: username})
class CustomUser(AbstractUser):
objects = CustomUserManager()`
Your signal is broken; kwargs will never have a user key so the profile will never be created. What you actually want to do is to check that the signal is being called on creation (rather than on update), add then create an instance of Listing:
if kwargs['created']:
user_profile = Listing.objects.create(user=kwargs['instance'])
Note, the AUTH_PROFILE_MODULE setting has not been used for years, you should remove it.
I'm trying to make a custom user, but there's one problem, when i get request.user, it’s an instance of User, not an instance of CustomUser, so i don’t get the extra fields and methods. I've found this, but when i'm trying to login in the django admin it won't work anymore.
Here is my code:
models.py
class CustomUser(User):
timezone = models.CharField(max_length=50, default='Europe/Bucharest')
porecla = models.CharField(max_length=50, null=True)
selectat = models.BooleanField(default=False)
objects = UserManager()
auth_backends.py - so i can use the methods of the custom user when using request.user
from django.conf import settings
from django.contrib.auth.backends import ModelBackend
from django.core.exceptions import ImproperlyConfigured
from django.apps import apps
class CustomUserModelBackend(ModelBackend):
def authenticate(self, username=None, password=None):
try:
user = self.user_class.objects.get(username=username)
if user.check_password(password):
return user
except self.user_class.DoesNotExist:
return None
def get_user(self, user_id):
try:
return self.user_class.objects.get(pk=user_id)
except self.user_class.DoesNotExist:
return None
#property
def user_class(self):
if not hasattr(self, '_user_class'):
self._user_class = apps.get_model(*settings.CUSTOM_USER_MODEL.split('.', 2))
if not self._user_class:
raise ImproperlyConfigured('Could not get custom user model')
return self._user_class
settings.py
AUTHENTICATION_BACKENDS = ('football_app.auth_backends.CustomUserModelBackend', )
CUSTOM_USER_MODEL = 'football_app.CustomUser'
admin.py
class CustomUserAdmin(admin.ModelAdmin):
list_display = ('username', 'email', 'first_name', 'last_name', 'is_staff', 'is_active', 'selectat', )
admin.site.register(CustomUser, CustomUserAdmin)
The article you are referring to is outdated. If you want to create a custom User model, the way to go is to subclass AbstractUser in stead of User. This is explained here in the official docs.
Good evening,
I am presently creating a site with Django and I extended the user with a user profile. I have a small problem though. Here is my situation:
I extended the user profile in order to add custom fields.
I added the model to the User Admin Model, so when I am adding a user, I can fill in directly the fields to create the profile.
Now, if I don't add ANYTHING in these new custom user fields, in the user add page, Django Admin won't throw me an error saying these fields are null (and they aren't suppose to be)
I want it to throw me an error in this User Add Admin page, so that the admins will HAVE to fill in a profile when adding a new user.
ALL the users will be added in the Admin Panel.
Is this possible? Thanks a lot!
in admin.py
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin as DjangoUserAdmin
from django.contrib.auth.models import User
from accounts.models import UserProfile
class UserProfileInline(admin.TabularInline):
model = UserProfile
class UserAdmin(DjangoUserAdmin):
inlines = [ UserProfileInline,]
admin.site.unregister(User)
admin.site.register(User, UserAdmin)
In model.py
class UserProfile(models.Model):
user = models.OneToOneField(User)
employee_number = models.PositiveIntegerField(unique=True)
def __unicode__(self):
return 'Number'
By default, empty inline is permitted and thus no further check would be taken for an empty form. You need to override it manually:
class UserProfileForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(UserProfileForm, self).__init__(*args, **kwargs)
if self.instance.pk is None:
self.empty_permitted = False # Here
class Meta:
model = UserProfile
class UserProfileInline(admin.TabularInline):
model = UserProfile
form = UserProfileForm