15

I want to make my User objects all have the same base behaviour and to do so I need to add a couple of methods / properties to Anonymous User.

I've already subclassed User to make richer user objects but I was wondering if anyone has done the same for Anonymous User? And if there are any preferred ways of doing it!

Ross
  • 17,861
  • 2
  • 55
  • 73
  • 2
    I think the preferred way to extend the user model is not to subclass the `User` class but to create a separate `UserProfile` class, then add the desired fields to it and establish a ForeignKey relation to the `User` class. – Johannes Charra May 11 '10 at 07:53
  • 2
    Yeah I can see why that would be preferable, but AnonymousUser wouldn't have a UserProfile anyway as theres no where to FK to. – Ross May 11 '10 at 09:38

6 Answers6

14

Your middleware suggestion got me thinking, and I now think the best idea is to overwrite the standard AuthenticationMiddleware. That class assigns a LazyUser object to the request, which is resolved to the correct user, when accessed, by calling contrib.auth.get_user. This is probably the right place to override things, so that it calls your customised get_user function which returns your subclassed AnonymousUser.

Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895
  • 2
    Works a treat cheers Daniel! Heres a copy for prosperity: [custom auth backend](http://gist.github.com/397817) – Ross May 11 '10 at 20:29
5

A simpler and more general (but less safe) solution would be to just replace django.contrib.auth.models.AnonymousUser with your own class:

class YourAnonymousUser(...):
    ...


import django.contrib.auth.models as django_auth_models
django_auth_models.AnonymousUser = YourAnonymousUser

As of 1.10.5, Django lazily imports the anonymous user class, so you won't run into issues with core Django. You also rarely interact with AnonymousUser directly, since you could just use .is_anonymous(), so you should be fine as long as you know how your dependencies use AnonymousUser.

Blender
  • 289,723
  • 53
  • 439
  • 496
  • 1
    Your method works also for both WSGI requests and DRF requests, whilst the middleware method doesn't work for DRF. – Fadi Bakoura Oct 27 '19 at 21:32
2

The best way is to use a python package (or write your own) which will swap Django default AnonymousUser class with your own class. You can implement a middleware for this (I think it's the best place).

For example, you can use django-custom-anonymous to provide customization of AnonymousUser. Also you can find it on pypi.

bugov
  • 106
  • 5
1

I'm starting to think a middleware is probably the easiest solution that checks the request.user class and if is AnonymousUser then replaces it with a subclassed AnonymousUser that has the extra properties.

That sound reasonable?

Ross
  • 17,861
  • 2
  • 55
  • 73
0

You could probably use django-rest-framework which allows you to customise AnonymousUser through UNAUTHENTICATED_USER in settings likes this

REST_FRAMEWORK = {
    'UNAUTHENTICATED_USER': 'application.AnonymousUser',
}

Keep in mind that this user class will only be available from DRF views

Radical Ed
  • 178
  • 2
  • 13
-1

You should subclass or create a model that has a one to one relationship with the AnonymousUser class.

Olivier Verdier
  • 46,998
  • 29
  • 98
  • 90
  • subclassing would be ideal, but is more about the practicalities of doing it, as the AnonymousUser class is imported directly in a number of places. – Ross May 11 '10 at 09:42