I am beginning my first django project and would like to know which method is best for creating a relationship between User & Company models.
Option 1 - User existing django user model and create a user profile model
Class UserProfile(models.Model):
user = models.OneToOneField(User)
company = models.ForeignKey(Company)
Option 2 - Create custom user model
Class MyUser(AbstractBaseUser):
"all of the required user data -- left off for brevity"
company = models.ForeignKey(Company)
I have no issue with the base user model, my concern is more related to performance IF the application grows to a larger scale. I realize option 1 requires an additional database hit; however, I like the flexibility of having a UserProfile which can be modified to include additional criteria.
Which option would you prefer, or is there a better way?
I have decided to create the UserProfile to give additional flexibility. While we don't know how the application will grow, we feel it is important to keep our domain as flexible as possible. Thank you for all of the feedback.
So it basically depends on the use case and scope of the application, if you know that you just care about user nmae, email add, pass mainly then i will go with in built User Profile that comes with django. Otherwise, I would prefer making another UserProfile, as you will have the flexibility to add more parameters and methods with respect to your project.
Related
I am working on an enterprise LMS powered by Django REST framework.
Authentication is done via Google OAuth 2.0 using the package drf-social-oauth2, and the target organizations for my software are schools and universities.
Some models have foreign keys to the user model; however, due to the nature of my application, oftentimes a user may want to reference a user that isn’t present in the database yet. This happens because users are created in the database upon their first login in the application via OAuth, yet the person who wants to create a specific model instance referencing another user may want to do so before they’ve logged in for the first time: for example, a teacher may want to pre-enroll a list of students into their new course, but those users might not have logged in for the first time yet, and therefore might not exist in the database.
I’ll give a concrete example with a model in my application:
class UserCoursePrivilege(models.Model):
"""
Represents the administrative permissions a user has over a course.
See logic.privileges.py for the available permissions.
"""
user = models.ForeignKey(
User,
on_delete=models.CASCADE,
related_name="privileged_courses",
)
course = models.ForeignKey(
Course,
on_delete=models.CASCADE,
related_name="privileged_users",
)
allow_privileges = models.JSONField(default=list, blank=True)
deny_privileges = models.JSONField(default=list, blank=True)
This object is created in the frontend by accessing a table which shows all registered users and allows turning on switches that correspond the specific permissions for that user.
More than once have I found myself in the situation in which a teacher would email me telling me they couldn’t find their colleague to add their permissions for a course, and I would tell them to have them log in first and then come back to find the in the user table.
However, this isn’t very user-friendly and somehow counterintuitive considering that my application doesn’t provide an explicit user creation process, so the mental model for users is that their account somehow “already exists” and they just need to sign in.
I’m looking for a way to handle this in as transparent way as possible.
The target user experience is something like this: if the user cannot find the person they want to create the object for, the interface shows them a banner like “Can’t find the person you’re looking for?” and allows them to type in the email address of that person and proceed like normal (in the example above, that would entail showing them all the toggles to select permissions to grant).
Then, an instance of the correct model would be created, but with a null foreign key to user.
Then I would have a model that looks like this:
class PendingModelInstance(models.Model):
"""
Represents a model instance which references a user that doesn't exist yet
"""
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
object_id = models.TextField()
content_object = GenericForeignKey("content_type", "object_id")
email_address = models.TextField()
an instance of this would be created referencing the “partial” instance with the missing FK and with the email address of the user.
Then, upon user creation, a query is made to retrieve all instances of PendingModelInstance which have the email of the newly created user, their referenced models are then retrieved and updated with a FK to the new user instance.
This approach seems like it could work fine, but it introduces an issue I don’t really like: it makes foreign keys nullable, which they don’t need to be and shouldn’t be.
Is there a better alternative?
I'm using Django to build a B2B SaaS hobby project, where each company (tenant) can have many users and, eventually, remove them.
It's important to keep the reason why a user was removed.
The straightfoward way for this to be solved would be to turn is_active to False and add a reason_for_removal field on the User model. Then make sure is_active is indexed (is it by default in Django?) and all querysets are appropriately filtered.
However, in a GDPR world, is this the right way to do it? Does it make sense to create a separate model called RemovedUser just with the user and reason_for_removal fields (and no other Personal Identifiable Information) and delete the original user instance?
I am currently learning Django, specifically DRF to make an API that will be consumed by a web app client. The app is for a teacher who gives extracurricular classes in Mathematics and Science. My basic idea is that there will be two types of User, a Student and a Teacher. Teachers will obviously have more access rights than Students. The problem is, a django User class has the is_admin attribute and, since only Teachers could possibly be admin of the site, I cannot create a single User class that has is_admin and user_type attribute. For instance, the User with is_admin=True and user_type=Student will be an invalid combination. My idea is to make my User class as an Abstract Base Class and then make two seperate classes, Student and Teacher, that inherit from it. This is also ideal in the sense that only Teachers can publish articles, which means the Student class just won't have that permission, but then I face another problem. All Users have a single Profile. The Profile will store a bio, an avatar image of the user, etc. But when setting up the OneToOneField relationship in Profile, the profile must have that relationship with Students and Teachers, thus all User types. How can I set up that relationship? Can I say OneToOneField(User) and due to the inheritance that user could be a Student or a Teacher? If not, what should I do?
If you have experience and you are thinking, why on earth is he (that is me) doing that?, feel free to comment on my design plan and please show me how a better design would look. Thanks in advance.
EDIT: Is there any advantage in having a single profile for each user, storing a bio and image etc? Is there any gain in this over storing that info in the User model?
Don't create separate classes. Just that they have different permissions doesn't mean they need to be different classes! They can all be User (or your own subclass of that, but the same).
Then you configure two different groups (docs). You assign each new user to one of the two groups.
Your code can then use some custom permission (say a 'publish' permission on Article) and give that permission to the Teacher group, and check in your code that the current user has that permission.
Typically only one or a few users have "is_admin", is_admin means that you automatically have all existing permissions. It's for user management, configuring the groups, and such.
Keep it as one class unless you need each class to have different attributes. But in your case, you can just make is_staff=True synonymous with being a teacher, and then you could get rid of the user_type attribute. It's usually better practice to use boolean fields instead of char fields with a finite set of choices that do unknown things in the code. So staff would be teachers, and non-staff would be students.
Aside: By "is_admin", you meant "is_staff", right? I am not aware that the django User model has an "is_admin" attribute, only is_staff and is_superuser.
I currently have a website that has three kinds of permissions:
Active
Staff
SuperUser
What I want to do is limit what a user can view depending on his subaccess level on Driver i.e. Driver has three sub access levels - 100, 200, 300. I was thinking of doing this by
def email_check(user):
return user.accesslevel
#user_passes_test(accesslevel=100)
def my_view(request):
...
How do I add the additional property of the subaccess level to the user model? Is there any other way to implement this? ALso, since this is a an already live project, there are a lot of user on-board already. I'll also need to provide them a default access value.
Your idea to go with user_passes_test looks good to me.
So your main issue is basically how to extend the user model. This topic is covered thoroughly under Django documentation: Customizing authentication.
To sum up, there are mainly two ways to go with. One is to extend your user model with a custom model with an one-to-one relationship with User and any custom fields such as access level.
Alternatively, you can provide with a custom user model and substitute the Django User model, but this seems not appropriate for your case.
If I am trying to create a login app for my project is it advisable to use auth_user as the model to store newly created user's in and just extend in in my signup app through:
from auth.models import User
class UserForm(ModelForm):
class Meta:
model=User
Or is it better to create a custom model to store users in. Will what I have above even work? I'm sure the answer is either "of course, that's what it's there for" or "dear god why would you want to do that" but I don't know which.
User is meant to store the credentials of users that will be able to log into and use the system via normal Django auth mechanisms. If your project will use Django's auth then yes, User is the correct model to use.
The short answer is yes. and if you want to store additional information of the user, you could create another model and a foreign key to the user model.