I have two models Company and User:
class Company(models.Model):
name = CharField("Name", max_length=60)
owner = OneToOneField(
"Employee", related_name='owner', on_delete=SET_NULL, null=True)
class BaseUser(AbstractBaseUser, PermissionsMixin):
objects = CustomUserManager()
join_date = DateTimeField(default=timezone.now)
name = CharField("Name", max_length=60)
email = EmailField(('Email'), unique=True)
company = ForeignKey(Company, on_delete=models.CASCADE)
I need to have only one User as owner. I made it so two models point to each other which doesn't seem right. Is there a way to fix it and still have only one possible owner? I know standard way would be to add is_owner = Boolean to User but it allows other Users to be owners.
A ForeignKey from the Company to the BaseUser is sufficient:
class Company(models.Model):
name = CharField("Name", max_length=60)
owner = ForeignKey(
'Employee',
related_name='companies'
)
class BaseUser(AbstractBaseUser, PermissionsMixin):
objects = CustomUserManager()
join_date = DateTimeField(default=timezone.now)
name = CharField("Name", max_length=60)
email = EmailField(('Email'), unique=True)
# no company
Here we thus link a Company to one user. Two Companys can have the same owner, and it is possible that the BaseUser has no, one, or more Companys where he is the owner.
You can obtain all the companies for which a BaseUser is the owner with:
myuser.companies.all()
If two companies should always point to two different users, you can make use of the OneToOneField [Django-doc].
Related
I have custom user model:
class User(AbstractUser):
"""
Our own User model. Made by overriding Django's own AbstractUser model.
We need to define this as the main user model in settings.py with
variable AUTH_USER_MODEL *IMPORTANT*
"""
is_admin = models.BooleanField(default=False)
is_staff = models.BooleanField(default=False)
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
email = models.EmailField(
max_length=255,
unique=True,
verbose_name="email address"
)
institute = models.ForeignKey(
Institute, on_delete=models.SET_NULL, null=True)
objects = MyUserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
def __str__(self):
return self.email
I have two users in my projects. One is the super admin and the other is the admin. I've specified the model for admin as such:
class AdminUser(User):
is_admin = False
is_staff = True
def __str__(self):
return self.first_name+" "+self.last_name
# Control model features
class Meta:
verbose_name = 'Admin User'
verbose_name_plural = 'Admin Users'
Now I want to revoke access of the entire user model from this Admin User. How could this be achieved? We are going to have many more user types in future. They will be specified through models.
You can achieve this by just using groups in Django.
Your superuser will be you, that will have all permissions for default using the field is_admin=True. The second user can be a simple Staff user that is member of the group "Admins", just create the group and assign all the permissions to that group except the permissions to Add, Change and Delete users.
That will do the trick.
Update: If you need more complex cases, you can use the app django-groups-manager or django-guardian So you can create groups in trees, there you can use more domain driven permission rules.**
I want to extend the user model in Django (2.2) and combine it with a Host and a Guest entities that have also specific fields.
In the official documentation, it is recommended to create a "Profile" class with a OneToOne field that reference the User primary key.
I can see 3 ways of doing it:
Solution 1: Profile, Host and Guest model:
class Profile(models.Model):
k_user = models.OneToOneField(User, on_delete=models.CASCADE)
language = models.CharField(max_length=2)
class Host(models.Model):
k_user = models.OneToOneField(User, on_delete=models.CASCADE)
host_field= models.CharField(max_length=500)
class Guest(models.Model):
k_user = models.OneToOneField(User, on_delete=models.CASCADE)
guest_field = models.BooleanField(null=False)
Solution 2: Host and Guest model (with Profile fields duplicated)
class Host(models.Model):
k_user = models.OneToOneField(User, on_delete=models.CASCADE)
language = models.CharField(max_length=2)
host_field = models.CharField(max_length=500)
class Guest(models.Model):
k_user = models.OneToOneField(User, on_delete=models.CASCADE)
language = models.CharField(max_length=2)
guest_field = models.BooleanField(null=False)
Solution 3: Profile model (containing Guest and Host fields)
class Profile(models.Model):
k_user = models.OneToOneField(User, on_delete=models.CASCADE)
language = models.CharField(max_length=2)
is_host = models.BooleanField(null=False)
guest_field = models.BooleanField(null=False)
host_field = models.CharField(max_length=500)
All those solutions are working.
My question is: "Which one is the smartest, all things considered" (less database access, less code to write, easier to maintain, less limitations, etc..)
After digging further into Django's doc and reading the article mentioned by #sam that explain how to implement multi user types in Django, I found my answer.
It is written in the Django doc that "it’s highly recommended to set up a custom user model, even if the default User model is sufficient for you".
Here is what it gives in my case:
class User(AbstractUser):
is_guest = models.BooleanField(default=False)
is_host = models.BooleanField(default=False)
language = models.CharField(max_length=2)
class Host(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
host_field = models.CharField(max_length=500)
class Guest(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
guest_field = models.BooleanField(null=False)
in settings.py:
AUTH_USER_MODEL = 'path.to.User'
Guest or Host record are inserted when you create a new user:
user = User.objects.create_user(...)
if is_host:
Host.objects.create(user=user)
else:
Guest.objects.create(user=user)
I appreciate the fact that I can detect the user "type" in the request object (with request.user.is_host).
By extending the user class, you can also use the email field for login, and make it unique:
class User(AbstractUser):
[...]
email = models.EmailField(unique=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
If once in production you chose to add fields in the User model, it is possible if you have set up a custom user model.
Otherwise you will be stuck with profiles, so I advise you to follow Django's guidelines and always extending the user class, even if you don't need it (yet).
I would propose a 4:th way, using a mixin with an abstract model. This will derive the fields of the abstract model to the ones that you apply it to. This way you don't need to rewrite code and still apply it to different models:
class ProfileMixin(models.Model):
k_user = models.OneToOneField(User, on_delete=models.CASCADE)
language = models.CharField(max_length=2)
class Meta:
abstract = True
class Host(ProfileMixin):
host_field = models.CharField(max_length=500)
class Guest(ProfileMixin):
guest_field = models.BooleanField(null=False)
I am trying to build relations with my database tables. Im having a tutorial lesson at the moment with 3 tables. for example (auth_user table, partyEvent table, friends table).
Now a user should be able to create just one partyEvent. Friends can join any number of partyEvent created by the users.
The owner id in the Friends model tells the partyEvent and User 'the friend' belongs to.
I am able to restrict the users to create only one partyEvent. But when i try to register friends to a partyEvent, the owner's id is not sent. Instead the default value in:
owner = models.OneToOneField('auth.User', related_name = 'party', on_delete=models.CASCADE, default='1')
is rather sent. Why is that happening?
models
class PartyEvent(models.Model):
name = models.CharField(max_length=100, blank=False)
location = models.CharField(max_length=100, blank=False)
owner = models.OneToOneField('auth.User', related_name = 'party', on_delete=models.CASCADE, default='1')
class Friends(models.Model):
name = models.CharField(max_length=100, blank=False)
owner = models.ForeignKey('auth.User',related_name = 'friends', on_delete=models.CASCADE, default='1')
serializers
class FriendsSerializer(serializers.HyperlinkedModelSerializer):
owner = serializers.ReadOnlyField(source='owner.id')
class Meta:
model = Friends
fields = ('id','name','owner')
You can set current user by assigning serializers.CurrentUserDefault() as your serializer field default. Here is an example from the doc:
owner = serializers.HiddenField(
default=serializers.CurrentUserDefault()
)
I have the following two models in Django. One is basically an extension of the base Django user class and the other is a company model. I want to say that a user can belong to one or more companies and that a company can also have one or more contacts = "Users". Would this be a correct setup? How should I represent the tie between user and company?
User Profile model:
class Profile(models.Model):
user = models.OneToOneField(User)
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
Company model:
class Company(models.Model):
name = models.CharField(max_length=120)
account_name = models.CharField(max_length=10, default="")
sales_rep = models.ForeignKey(User, related_name="%(app_label)s_%(class)s_sales", default="")
csr = models.ForeignKey(User, related_name="%(app_label)s_%(class)s_csr", default="")
class CompanyContact(models.Model):
name = models.CharField(max_length=40, default="")
email = models.CharField(max_length=50, default="")
user = models.ForeignKey(User)
company = models.ForeignKey(Company)
First, is there a reason to extend the User model? The default model already includes a first_name and last_name field, so you don't need an additional model just for that data. Similarly, you don't really need CompanyContact because the User model also contains email and name (again, through first_name and last_name) fields.
You can add in your contacts as a ManyToManyField. If you want to use the custom Profile model instead of User, just replace User (in the ManyToManyField) with Profile.
class Company(models.Model):
name = models.CharField(max_length=120)
account_name = models.CharField(max_length=10, default="")
sales_rep = models.ForeignKey(User, related_name="%(app_label)s_%(class)s_sales", default="")
csr = models.ForeignKey(User, related_name="%(app_label)s_%(class)s_csr", default="")
contacts = models.ManyToManyField(User) # or Profile
This allows each company to have many contacts and each user to be a contact of many companies – thus many-to-many.
Now, if you wanted extra data to describe the many-to-many relationship, you can have another model for that. For example, you may want to keep a record if the contact is still active or what their role is. So, you may have a CompanyContact model that is similar to:
class CompanyContact(models.Model):
active = models.BooleanField(default=False)
role = models.CharField(max_length=50, default="")
user = models.ForeignKey(User) # or Profile
company = models.ForeignKey(Company)
Then, declare the ManyToManyField relationship to use this new model:
class Company(models.Model):
...
contacts = models.ManyToManyField(User, through="CompanyContact")
# or contacts = models.ManyToManyField(Profile, through="CompanyContact")
I want to create multiple types of user in django app e.g one for Company and one for Employee.
What I had in mind was company will signup for itself and then employees will be created by company admin through his/her dashboard.
After creation employees will sign in directly.
So (if possible) only one sign in form can be used for company and employees.
class Company(models.Model):
name = models.CharField(max_length=150)
logo = models.CharField(max_length=1000, blank=True)
admin_name = models.CharField(max_length=200)
admin_email = models.CharField(max_length=200) # can be used as 'username'
website = models.CharField(max_length=200, blank=True)
class CustomUserManager(auth_models.BaseUserManager):
def create_user(self, email, first_name, emp_id, password):
#
def create_superuser(self, email, first_name, emp_id, password):
#
class Users(auth_models.AbstractBaseUser, auth_models.PermissionsMixin):
company = models.ForeignKey(Company, on_delete=models.CASCADE, null=True)
first_name = models.CharField(max_length=200)
last_name = models.CharField(max_length=200)
profile_pic = models.CharField(max_length=2000, blank=True)
email = models.EmailField(unique=True, null=True)
emp_id = models.CharField(max_length=50)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['first_name', 'emp_id', ]
objects = CustomUserManager()
I searched almost everywhere but couldn't find anything. If there is any way to solve this issue please let me know otherwise if you know any trick to get this thing done then it is also welcome.
Thanks in advance.
You can just create groups for the different types of users:
Group.objects.create(name='Company')
And then assign the user to the appropriate group:
user.groups.add(group)
The last thing it sounds like you could do is to associate employees with the company user, so you can add a self reference to your Users model like this:
company_user = models.ForeignKey("self", null=True, blank=True)
So, for those employees, you can then associate the user with that company user and leave it blank for the company user itself.
Although, you don't need to do that if you want to use the company foreign key you already have to track the related users that way. But if a company may have several "company users", you could then group up the employees to each.
I hope that helps.