Django admin show only current user for User field as ForeignKey while creating and object

Question:

I’m working on a Django ( 4.0 +) project, where I have a model named Post in which we have a ForignKey field as Author, a user with is_staff and in Authors group can create an object of Post from admin.

Now the problem is when user click on Add Post as the Author field it should only display the current user not the others.

Here’s what i have tried:

From models.py:

class Post(models.Model):
    title = models.CharField(max_length=200, unique=True)
    slug = models.SlugField(max_length=200, unique=True)
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    updated_on = models.DateTimeField(auto_now= True)
    content = models.TextField()
    created_on = models.DateTimeField(auto_now_add=True)
    thumbnail = models.ImageField()
    category = models.ForeignKey(Category, on_delete=models.DO_NOTHING, related_name='category')
    featured = models.BooleanField()
    status = models.IntegerField(choices=STATUS, default=0)

    class Meta:
        ordering = ['-created_on']

    def __str__(self):
        return self.title

From admin.py:

class PostAdmin(admin.ModelAdmin):
    list_display = ('title', 'slug', 'status','created_on')
    list_filter = ("status",)
    search_fields = ['title', 'content']
    prepopulated_fields = {'slug': ('title',)}

    def get_queryset(self, request):
        qs = super().get_queryset(request)
        if request.user.is_superuser:
            return qs
        return qs.filter(author=request.user)

How can I achieve that?

Asked By: Abdul Rehman

||

Answers:

I would advise to simply exclude the field from the form, and assign the user when you save the model with the .save_model(…) method [Django-doc]:

class PostAdmin(admin.ModelAdmin):
    list_display = ('title', 'slug', 'status', 'created_on')
    list_filter = ('status',)
    search_fields = ['title', 'content']
    prepopulated_fields = {'slug': ('title',)}
    exclude = ('author',)

    def get_queryset(self, request):
        qs = super().get_queryset(request)
        if not request.user.is_superuser:
            qs = qs.filter(author=request.user)
        return qs

    def save_model(self, request, obj, form, change):
        obj.author = request.user
        return super().save_model(request, obj, form, change)
Answered By: Willem Van Onsem

Try formfield_for_foreignkey()

It overrides the default formfield for a foreign keys field. In your case, to return only current user for author foreign key field:

class PostAdmin(admin.ModelAdmin):
    ...

    def formfield_for_foreignkey(self, db_field, request, **kwargs):
        if db_field.name == 'author':
            kwargs['queryset'] = User.objects.filter(id=request.user.id)
        return super().formfield_for_foreignkey(db_field, request, **kwargs)
Answered By: weAreStarsDust