Inheritance from an AbstractUser based Model in django 2.7 - django

I have a Custom User Model extending the AbstractUser and it works fine. But now i want to create another Model that is extending my Custom User Model like this in models.py:
class CustomUser(AbstractUser):
phone = models.CharField(max_length=10, null=False, unique=True)
town = models.CharField(max_length=25, null=False)
class DeleveryPerson(CustomUser):
code = models.CharField(max_length=10, null=False, unique=True)
The problem is that the table DeleveryPerson is created with just the field "code"
when I expected it to also have fields coming from the CustomUser model.
So how can i achieve that kind of inheretane between CustomUser and DeleveryPerson. Thk!

Related

Django Rest Framework authentication with Custom User Model

I have multiple types of user in my django app: Employee and Patient. They have fields that are specific to each of them. They are implemented using the AbstractBaseUser model as below:
from django.db import models
from django.contrib.auth.models import AbstractBaseUser
class User(AbstractBaseUser):
username = models.CharField(max_length=40, unique=True)
USERNAME_FIELD = 'identifier'
first_name = models.CharField(
max_length=50, null=False, blank=False)
last_name = models.CharField(
max_length=50, null=False, blank=False)
date_of_birth = models.DateField(null=False, blank=False)
USER_TYPE_CHOICES = (
(1, 'Patient'),
(2, 'Employee'),
)
user_type = models.PositiveSmallIntegerField(
choices=USER_TYPE_CHOICES, default=1, blank=False, null=False)
class Role(models.Model):
RoleName = models.CharField(max_length=50, null=False, blank=False)
class Employee(models.Model):
user = models.OneToOneField(
User, on_delete=models.CASCADE, primary_key=True)
employment_start_date = models.DateField(null=False, blank=True)
employment_end_date = models.DateField(null=False, blank=True)
role = models.ForeignKey(
Role, on_delete=models.CASCADE, related_name='assigned_employees')
class Patient(models.Model):
user = models.OneToOneField(
User, on_delete=models.CASCADE, primary_key=True)
I have a few questions with how to go forward with this:
How does just the choice in the User class limit the fields that a user has access to? If I had a HTML page would I create an Employee then a User would be created, or the other way round?
When I'm using Django Rest Framework, how can I implement a sign up and log in with the two different types?
I'm struggling to understand how this would work conceptually. Is like Employee and Patient a subclass of User? Or are they separate models? Any help or advice would be greatly appreciated
In your code you don't have two types of User. You have only one type - class User(AbstractBaseUser). Employee and Patient are normal models that are only related to User.
If you wanted to create two types of User with actual inheritence, then you should do following:
class AbstractUser(AbstractBaseUser):
class Meta:
abstract = True
# main user fields here
class Employee(AbstractUser):
# employee fields here
class Patient(AbstractUser):
# patient fields here
If you don't want to do this, your current approach is good. You can simply authenticate User in standard way. During creation you can make seperate forms for registering employee User, that creates automatically related Employee class. Similar for Patient. They will share only fields of User class with either approach.
To authenticate in different ways you can use custom authentication with authenticate() function. Read specifics in Django Docs

How to keep fields in user model in Django and add some extra field

I want to add some extra fields to my user model and I read custom user model with inherit from abstractuser class but when I implement user model Django username field and etc was gone.
A solution is use another model like profile but I want add extra fields to Django user model. Is this possible?
You can use a custom User model:
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
"""
Custom User Model
"""
TIMEZONES = tuple(zip(pytz.all_timezones, pytz.all_timezones))
username = models.CharField(max_length=255, unique=True)
full_name = models.CharField(max_length=255, blank=True, null=True)
email = models.CharField(max_length=255, unique=True)
image = models.ImageField(upload_to=get_image_path, blank=True, null=True)
timezone = models.CharField(max_length=32, choices=TIMEZONES, default="UTC")
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
USERNAME_FIELD = "email"
REQUIRED_FIELDS = ["username"]
def __str__(self):
return self.email
You will have to register your custom model in the settings.py file:
# Registering the Custom User Model
AUTH_USER_MODEL = 'my_app.User'

Obtaining queryset based on unrelated models

I've got the following models. I need to obtain a queryset of orders where the user's userprofile.setupstatus == 1. Is this possible or should I just add a foreign key field on the Order model to the UserProfile?
class Order(models.Model):
user = models.ForeignKey(UserCheckout, null=True, on_delete=models.CASCADE)
class UserCheckout(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, null=True, blank=True)
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
setupstatus = models.IntegerField(default=0)
It is surely possible with Django ORM
Your query should look somewhat like this
Order.objects.filter(user__user__userprofile__setupstatus=1)

Add ForeignKey field to default User without modifying it?

I am using the default User model, and created a custom model called Team. A user can only be on one team, but a team can have many users. Therefore, I must create the ForeignKey field within the User model.
The thing is, I'm using the default User by simply importing User with from django.contrib.auth.models import User
What is the easiest way of adding a ForeignKey field into the default User model? Do I have to extend the default User model?
Or is there a way for me to add a ForeignKey field into Team, and swap the relationship between User and Team?
Honestly when you are working with the default Django user model, it's always better to create a custom user model that you can modify easier. Below is a simple example on how you can modify your User class with the AbtractBaseUser. If you'd like to add a foreign key just use ForeignKey instead of the data types below.
from __future__ import unicode_literals
from django.utils import timezone
from django.contrib.auth.models import (AbstractBaseUser,PermissionsMixin)
from django.db import models
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(unique=True)
username = models.CharField(max_length=7, unique=True)
formattedusername = models.CharField(max_length=11, unique=True, primary_key = True)
first_name = models.CharField(max_length=40)
last_name = models.CharField(max_length=140)
date_joined = models.DateTimeField(default=timezone.now)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
facility = models.CharField(max_length=140)
jobdescription = models.CharField(max_length=140)
positiondescription = models.CharField(max_length=140)
coid = models.CharField(max_length=5)
streetaddress = models.CharField(max_length=140)
USERNAME_FIELD = 'username'
class Meta:
app_label = 'accounts'
db_table = "user"
# REQUIRED_FIELDS = "username"
def __str__(self):
return "#{}".format(self.username)
In my opinion, the best way of achieving what you want is to use an in-between table. Therefore, you would create your Team model as normal and then create another model with two foreign keys to both User and Team. This is an example, it may change, feel free to change it to your needs.
class Group(models.Model):
group = models.ForeignKey(User, on_delete=models.CASCADE)
group = models.ForeignKey(Team, on_delete=models.CASCADE)
class Team (models.Model):
group = models.ForeignKey(Group, on_delete=models.CASCADE)
#your other fields

Django - How Updating Author Model in the mid-way?

I have Author model which looks like this:
class Author(models.Model):
name = models.CharField(max_length=100)
email = models.EmailField(unique=True)
created = models.DateTimeField(auto_now_add=True)
last_login = models.DateTimeField(auto_now=True)
Now I want to connect Author Model to User model and in the process add some additional fields in the Author model. Here is the updated version of Author model.
class Author(models.Model):
user = models.OneToOneField(User)
## additional fields
phone = models.IntegerField(blank=True)
address = models.CharField(max_length=200)
bio = models.TextField()
Author model is also connected to the Story model via ForeignKey. My question is how do I update my Author model without deleting any Story related to it.
class Author(models.Model):
user = models.OneToOneField(User, null=True, blank=True)
And do makemigrations and migrate. Now you have the empty user field. Later you can add user in admin page or Can able to add user also in Shell.