Eray Erdin
Eray Erdin

Reputation: 3149

How to Create A User Model Only Including Username in Django?

Well, this is a bit complicated, but let me explain myself. I want to create a RESTful service. This service will contain users, but not in a classic way.

I want to create users based on random hashes, I will use uuid to do that. And the most important thing is that I will not need username, password, email or full_name (?). This type of user will authenticate via a GET parameter on a view, only using its username, not anything else.

I read some articles on extending Django user, yet I couldn't find satisfying explanation especially for this case.

Further Explanations

Now, I can hear questions like "Why would anyone ever need especially passwordless User model, and especially thinking that it is quite insecure.". So, this part is especially for the ones who needs a logical explanation to understand such a request.

In service, I want to have three group of users:

  1. anonymous users: the ones who do request some data on server
  2. uuid users: the ones who have a unique id. Why do I need this type? Because I want to track those users' requests and response special data for them. These kind of users will also be removed if they are inactive for specific several days. I think I can do it by cron jobs.
  3. admin: This is me, reaching admin panel. That is all.

I think this explains enough.


Environment

Upvotes: 1

Views: 974

Answers (1)

Romaan
Romaan

Reputation: 2757

Django supports multiple backend authentications. As Luis Masuelli suggested you can extend the model to add more fields. But in your scenario, specifically you want to implement a custom authentication method. I woudl go about treating uuid as username and setting password as None.

So, in my settings.py:

 AUTH_USER_MODEL = 'app_name.MyUUIDModel'
 # REMOVE ALL PASSWORD Validators

In my app_name/models.py:

from django.contrib.auth.models import BaseUserManager

class MyUUIDManager(BaseUserManager):

def create_user(self, uuid):
    user = self.model(
        uuid=self.normalize_email(email),
    )
    user.set_password(None)
    user.save(using=self._db)
    return user

def create_superuser(self, uuid):
    user = self.create_user(uuid)
    user.save(using=self._db)
    return user

def get_by_natural_key(self, email):
    return self.get(**{self.model.USERNAME_FIELD: email})   

 class MyUUIDModel(AbstractBaseUser):
       uuid = models.CharField(max_length=36, unique=True)
       USERNAME_FIELD = 'uuid'
       objects = UUIDModelManager()
       def save(self, *args, **kwargs):
           super(MyUUIDModel, self).save(*args, **kwargs)

At this point, if you run createuser or createsuperuser Django command, you may be able to create the user. The next bit is where the authentication needs to be done. You can simply check if the UUID exists in your DB and return true when authenticate() is called from the view.

Add authentication backend in the settings.py file:

AUTHENTICATION_BACKENDS = [
  'django.contrib.auth.backends.ModelBackend',
  'app_name.auth.MyBackend'
]

Create a file app_name/auth.py with contents SIMILAR to below:

class MyBackend(object):
    def authenticate(self, username=None, password=None):

        # Check if username i.e. UUID exists
        try:
            my_uuid = MyUUIDModel.objects.get(uuid=username)
        except MyUUIDModel.DoesNotExist:
            return None
        return my_uuid

More more details refer to: https://docs.djangoproject.com/en/1.9/topics/auth/customizing/

Upvotes: 1

Related Questions