i want give access to users to admin panel
i have a table :
class Todo(models.Model):
user = models.ForeignKey(User,on_delete=models.CASCADE)
title = models.CharField(max_length=100)
date = models.DateTimeField()
def __str__(self):
return self.title
i want just allow users to see,edit,add and delete their own objects in admin panel not others.
i wrote this:
class TodoAdmin(admin.ModelAdmin):
def queryset(self, request):
queryset = super(TodoAdmin, self).queryset(request)
queryset = queryset.filter(user = request.user)
return queryset
but didnt work.
how can i do that?
You have to override get_queryset method as documented
The get_queryset method on a ModelAdmin returns a QuerySet of all
model instances that can be edited by the admin site. One use case for
overriding this method is to show objects owned by the logged-in user:
class MyModelAdmin(admin.ModelAdmin):
def get_queryset(self, request):
qs = super().get_queryset(request)
if request.user.is_superuser:
return qs
return qs.filter(author=request.user)
Related
I have created Models UserProfile, serilzers and ModelViewSet like below. From below models I want to fetch loged in User profile details like state, city and adress etc
class UserProfile(models.Model):
user= models.OneToOneField(User,on_delete=models.CASCADE,related_name='userprofile');
state= models.CharField(max_length=200)
city= models.CharField(max_length=200)
add1= models.CharField(max_length=200)
add2= models.CharField(max_length=200)
postalcode= models.IntegerField()
country= models.CharField(max_length=200)
class UserProfileSerializer(serializers.ModelSerializer):
class Meta:
model = UserProfile
fields = ('state','city','country')
class UserProfileViewSet(viewsets.ModelViewSet):
queryset=UserProfile.objects.all()
serializer_class=UserProfileSerializer
def get(self, request):
userProfileObj = queryset.objects.filter(user_id=request.user.id)
serializer = self.get_serializer(userProfileObj)
return Response(serializer.data)
But for some reason, I am getting all user profile data instead of logged in user data, please let me know where I am doing wrong.
You can do it by overriding the get_queryset() method, as below
class UserProfileViewSet(viewsets.ModelViewSet):
queryset = UserProfile.objects.all()
serializer_class = UserProfileSerializer
def get_queryset(self):
if self.action == 'list':
return self.queryset.filter(user=self.request.user)
return self.queryset
Here the 'list' refferes the api type, which is list api. That means, it will return logged-in user's profile while you accessing the list api
ModelViewSet implements the methods list/retrieve not get.
Just overwrite get_queryset instead. No need for creating serializer yourself. (There's no need to set queryset attribute as well.)
I have a django model and and i want that model to be accessed only by its owner(user who created the model). So i created a permission class as follows
class IsOwnerOnly(permissions.BasePermission):
def has_object_permission(self, request, view, obj):
# Write permissions are only allowed to the owner of the snippet.
return obj.owner == request.user
and applied this permission on modelviewset
class ItemViewSet(viewsets.ModelViewSet):
queryset = Item.objects.all()
serializer_class = ItemSerializer
permission_classes = (IsOwnerOnly,)
def perform_create(self, serializer):
serializer.save(owner=self.request.user)
While accessing a single item it works, But even then every authenticated user can access the list of items. So how could i limit the item access to only its owner?
I have included Tokenauthentication in settings page as shown
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
),
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.TokenAuthentication',
),
}
and the item looks like
class Item(models.Model):
name=models.CharField(max_length=30)
address=models.TextField()
owner = models.ForeignKey('auth.User', related_name='items', on_delete=models.CASCADE)
def __str__(self):
return self.name
You can't control who can access item list by owner,if you what,you need to override has_permission to class IsOwnerOnly, like:
class IsAuthenticatedOwner(permissions.BasePermission):
def has_permission(self, request, view):
# work when your access /item/
if request.user and is_authenticated(request.user):
if request.user.id in [1, 2, 3]:
return True
else:
return False
else:
return False
def has_object_permission(self, request, view, obj):
# work when your access /item/item_id/
# Instance must have an attribute named `owner`.
return obj.owner == request.user
Notice:has_permission work when your access /item/(list),has_object_permission work when your access /item/item_id/(retrieve and update).
If you want to let user see the items only he created,simple as:
class ItemsViewSet(ModelViewSet):
queryset = Items.objects.all()
serializer_class = ItemsSerializer
permission_classes = (IsAuthenticated)
def get_queryset(self):
queryset = self.get_queryset().filter(owner=self.request.user)
return queryset
You can override the method get_queryset on your View
class ItemViewSet(viewsets.ModelViewSet):
queryset = Item.objects.all()
serializer_class = ItemSerializer
permission_classes = (IsOwnerOnly,)
def perform_create(self, serializer):
serializer.save(owner=self.request.user)
def get_queryset(self):
return self.queryset.filter(owner=self.request.user)
This way the method list (from ModelViewSet) will call your "get_queryset" to build the pagination with the data.
In Django, I have created another separate Admin site. This is what my SiteUserAdmin class looks like:
class SiteUserAdmin(UserAdmin):
form = UserChangeForm
add_form = UserCreationForm
list_display = ('username' ,'email',)
fieldsets = (
(None,{'fields':('username','email','password')}),('Permissions',{'fields':('is_active','is_admin_user','groups')})
)
Among all the users, there are superusers whose "is_superuser = True". Is there anyway to hide such superusers from the list of editable users of the admin site?
In another word, I am not excluding other fields from the Admin site, but rather hide some instances of User from being edited in the Admin site.
How about just overriding the get_queryset() method.
class SiteUserAdmin(admin.ModelAdmin):
def get_queryset(self, request):
qs = super(SiteUserAdmin, self).get_queryset(request)
if request.user.is_superuser:
return qs
return qs.filter(is_superuser=False)
Docs: https://docs.djangoproject.com/en/1.8/ref/contrib/admin/#django.contrib.admin.ModelAdmin.get_queryset
Override the get_queryset() method:
class SiteUserAdmin(UserAdmin):
...
def get_queryset(self, request):
qs = super(SiteUserAdmin, self).get_queryset(request)
return qs.exclude(is_superuser=True)
I'm new to Django and for a small project I need to open changelist of some models without any data. How we can prevent initial populating of some models?
You have to create your own ChangeList subclass. For example the following code will open an empty changelist but if you will search for name then the list will be populated by the search results:
from django.contrib.admin.views.main import ChangeList
class MyChangeList(ChangeList):
def get_queryset(self, request):
queryset = super(MyChangeList, self).get_queryset(request)
if not request.GET.get('q', ''):
queryset = queryset.none()
return queryset
class MyAdmin(admin.ModelAdmin):
search_fields = ['name']
def get_changelist1(self, request, **kwargs):
return MyChangeList
I am trying to define a proxy model for my admin view and have it only show objects that have a certain amount of foreign key values.
This is what I'm trying, but I'm not able to filter on yVotes:
class Post(models.Model):
title = models.CharField(max_length=512)
class PostVote(models.Model):
post = models.ForeignKey(Post)
vote = models.CharField(max_length=1)
class VotedPost(models.Post):
def _yVotes(self):
return models.PostVote.objects.filter(post=self, vote='Y').count()
yVotes = property(_yVotes)
class Meta:
proxy = True
class VotedPostAdmin(PostAdmin):
list_display = ('title', 'yVotes')
def queryset(self, request):
return self.model.objects.filter(yVotes__gt=0)
So my end result would be when you browse to /admin page for VotedPost, it would only show posts that have more than 0 'Y' votes. Commenting out the queryset in VotedPostAdmin, the proper value for yVotes will display in the list_display.
Thanks in advance!
Here is the solution I've ended up with so far to get me the results I need. If anyone has a more elegant solution I will wait to accept:
class VotedPostAdmin(PostAdmin):
list_display = ('title', 'yVotes')
def queryset(self, request):
return VotedPost.objects.all().annotate(count = Count('postvote')).order_by('-count').filter(count__gt=0).filter(postvote__vote='Y')
Why don't you overwrite get_queryset or use the admin filters to create such display. What you're trying todo seems overly complex tbh
class PostAdmin(admin.ModelAdmin):
def queryset(self, request):
qs = super(ThisAdmin, self).queryset(request)
# do stuff and return whatever