Search code examples
djangodjango-modelsdjango-authentication

Django: make all models user dependent?


I have many models for very different things. Now I have added user authentication with django-allauth. What I want to do is to make all models user dependent. I mean that only the user can see their own model data that they have stored. What is the best way to achieve this? Do I need to add a ForeignKey to each model I have?

model.py:

class images(models.Model):
    ...

class things(models.Model):
    ...

class devices(models.Model):
    ...

class messages(models.Model):
    ...

#and so on...

Solution

  • Do I need to add a ForeignKey to each model I have?

    Yes, but you do not have to alter all models, you can work with an abstract base model:

    from django.conf import settings
    
    class OwnedModel(models.Model):
        owner = models.ForeignKey(
            settings.AUTH_USER_MODEL,
            on_delete=models.CASCADE
        )
        
        class Meta:
            abstract = True

    and then use it in all subclasses:

    class Image(OwnedModel, models.Model):
        # …
        pass
    
    class Thing(OwnedModel, models.Model):
        # …
        pass
    
    class Device(OwnedModel, models.Model):
        # …
        pass
    
    class Message(OwnedModel, models.Model):
        # …
        pass

    In your views you will have to filter on the user. On class-based views, you can probably do this easily with a mixin:

    from django.contrib.auth.mixins import LoginRequiredMixin
    
    class OwnedMixin(LoginRequiredMixin):
        def get_queryset(self, *args, **kwargs):
            return super().get_queryset(*args, **kwargs).filter(
                owner=self.request.user
            )
    
        def form_valid(self, form):
            form.instance.owner = self.request.user
            return super().form_valid(form)

    This mixin can also be used for the CreateView and UpdateView to automatically set the owner for the created/updated objects.

    then you can use these in ListViews, DetailViews, etc.:

    class ImageListView(OwnedMixin, ListView):
        # …
    
    class DeviceDetailView(OwnedMixin, DetailView):
        # …
    
    class ThingCreateView(OwnedMixin, CreateView):
        # …