Hello I am pretty new to Django and don't get yet fundamental ideas of Users.
I was able to create a registration page to create users which are shown on the admin page in the "Authentication and AUthorization -> Users".
Now I want the users to logg in and create their profiles. They should add some additional information like name, bio, picture etc.
Every user should be able to add and see its own profile.
To do that I created a model:
class Profile(models.Model):
firstname = models.CharField(max_length=50)
lastname = models.CharField(max_length=50)
bio = models.TextField()
profile_pic = models.ImageField(upload_to="images/")
def __str__(self):
return self.firstname + ' | ' + self.lastname
In my view and the html I am able to add these informations to the model.
But HOW exactly can I relate this "Profile"-Model to the individual user? What do I miss here?
You can do this via adding a OneToOneField relationship between Profile and the default User:
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
firstname = models.CharField(max_length=50)
lastname = models.CharField(max_length=50)
bio = models.TextField()
profile_pic = models.ImageField(upload_to="images/")
def __str__(self):
return self.firstname + ' | ' + self.lastname
You can make a OneToOneField to the AUTH_USER_MODEL setting [Django-doc]. This settings contains a string with the qualified name of the user model. This is better than linking to the User model of django.contrib.auth.models.User, because if you later create a custom user model, the references to that user model will be updated:
from django.conf import settings
class Profile(models.Model):
user = models.OneToOneField(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE
)
# …
For more information, see the referencing the user model section of the Django documentation.
Related
I've inherited from the AbstractBaseUser as follows:
class User(AbstractBaseUser):
"""
Main User model, inherits from AbstractBaseUser
"""
# Meta
email = models.EmailField(verbose_name='email', max_length=60, unique=True)
username = models.CharField(max_length=40, unique=True) # equals to email
date_joined = models.DateTimeField(verbose_name='date joined', auto_now_add=True)
last_login = models.DateTimeField(verbose_name='last login', auto_now=True)
employee_of = models.OneToOneField(Customer, on_delete=models.SET_NULL, null=True)
So each User is linked to one and only one Customer.
Now within a view I want to access the instance of the current logged in user within the request object and get the employee_of value to get a queryset that contains all users of that customer.
def render_employees(request):
"""
Renders the employees page of the dashboard
:param request:
:return:
"""
# Return the value for the current site for css specific classes
dashboard_site = 'employees'
# Query the employees
qs_employees = User.objects.filter(employee_of=request.user.employee_of) # doesn't find field
...
However the filter doesn't work because request.user.employ_of doesn't seem to return anything. My IDE even suggests e.g. username, date_joined etc. but not employee_of.
Why's that?
class Customer(models.Model):
"""
A table that stores static data about a customer, usually a legal company
"""
legal_name = models.CharField(max_length=50)
street = models.CharField(max_length=30)
street_number = models.CharField(max_length=3)
def __str__(self):
return self.legal_name
Update:
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
from applications.customer.models import Customer
from django.conf import settings
BaseUser = settings.AUTH_USER_MODEL
class User(AbstractBaseUser):
"""
Main User model, inherits from AbstractBaseUser
"""
# Relations
user = models.OneToOneField(BaseUser, related_name='user_profile', on_delete=models.CASCADE, null=True) # link to default user model
employee_of = models.OneToOneField(Customer, on_delete=models.SET_NULL, null=True, blank=True)
I linked the user to the default user model via Django admin. However in the view im still not able to access employee_of within request.user
It seems that request.user is a different model. It's User model from django.contrib.auth. https://docs.djangoproject.com/en/4.0/ref/contrib/auth/#django.contrib.auth.models.User.
What you can do about it?
In our app we have UserProfile model that have OnetoOne relation to django User.
You can then store employee_of value there.
class UserProfile(AbstractBaseUser):
user = models.OnetoOneField("auth.User", related_name="user_profile", on_delete=models.CASCADE)
employee_of = models.OneToOneField(Customer, on_delete=models.SET_NULL, null=True)
and then access request.user employees using something like
request.user.user_profile.employee_of
I have two models. One is for UserProfile and the other is for Company.
class UserProfile(models.Model):
company_name = models.ForeignKey(Company, on_delete = models.CASCADE, related_name = 'company')
class Company(models.Model):
name = models.CharField(max_length = 100)
I am using Django Rest Framework for user creation. What I want to achieve is when I create a new user, I want to assign a company_name to that user. And if that company_name is not present in the db, then I want to create it on the go. But it is throwing an error. "Invalid hyperlink - No URL match."
You can use python's #property to tackle this problem in a clean and simple way. It works well for creating and for updating the object aswell. Note that the UserPorifle's field is renamed to company. Here is how you do it:
class Company(models.Model):
name = models.CharField(max_length=100)
class UserProfile(models.Model):
company = models.ForeignKey(Company, on_delete=models.CASCADE, related_name='company')
#property
def company_name(self):
return self.company.name
#company_name.setter
def company_name(self, value):
self.company, _ = Company.objects.get_or_create(name=value)
Now you can create objects using:
UserProfile.objects.create(company_name='Some name')
First you need to link your UserProfile Model with the user. It should be a OnetoOne Relationship because a User should only have one company I guess.
In your serializer you should add in the Company model and save the company name from the input in the API and then connect it to the new user that is being created.
I'm working on a project on how to create Two users : buyers/Sellers for Web using Django as Backend.
I've started the app "users"
I've read the Django Documentation about CustomUserModel
But Honestly don't know where to start from.
Any Suggestions?
In my opinion, a Buyer might be a seller and a seller might be a Buyer.
There are some suggestions:
Create your own application named users (This will help you full control User object in future).
Set your AUTH_USER_MODEL settings to users.User: AUTH_USER_MODEL = 'users.User' As you defined.
Define model Seller - OneToOne -> User: This contains seller's properties, Just create when access via user.seller
Define model Buyer - OneToOne -> User: This contains buyer's properties, just create when access via user.buyer
class User(AbstractUser):
# Your user's properties
# Your user's method
#property
def buyer(self):
try:
return Buyer.objects.get(user=self)
except Buyer.DoesNotExist:
default_value_of_buyer = {}
# Or define default value at model fields
return Buyer.objects.create(user=self, **default_value_of_buyer)
#property
def seller(self):
try:
return Seller.objects.get(user=self)
except Seller.DoesNotExist:
default_value_of_seller = {}
# Or define default value at model fields
return Seller.objects.create(user=self, **default_value_of_seller)
class Buyer(models.Model):
"""
You can add this to admin page to make some actions with Buyer
"""
user = models.OneToOneField(settings.AUTH_USER_MODEL, primary_key=True, on_delete=models.CASCADE, related_name='buyer_profile')
# Other properties of Buyer
def __str__(self):
return "%s's Buyer profile" % self.user
class Seller(models.Model):
"""
You can add this to admin page to make some actions with Seller
"""
user = models.OneToOneField(settings.AUTH_USER_MODEL, primary_key=True, on_delete=models.CASCADE, related_name='seller_profile')
# Other properties of Seller
def __str__(self):
return "%s's Seller profile" % self.user
It is not that hard buddy look:
you create a model User
class User(models.Model):
.........
types = (('b','buyer'),('s','seller'))
user_type = models.CharField(max_length=7, choices=types)
so every field has this argument called choices, it is a tuple that has tuples in it, every sub tuple is a choice and every choice has two elements the first one is what appears in the back end and the second element is what appears in the user interface, so 'b' is what appears in the back end and 'buyer' is what the user see in the form in the web site. Tell if that didn't work for you
class Account(models.Model):
types = (
('B', 'BUYER' ),('S', 'SELLER')
)
name = models.Charfield(max_length=15)
username = models.CharField(max_length=15)
email = models.EmailField()
password = models.CharField(max_length=16)
user_type = models.CharField(max_length=12, choices=types)
TRY THIS AND THEN GO TO YOUR ADMIN PAGE AND YOU WILL UNDERSTAND EVERYTHING
I've created a custom user model using abstractuser titled employee.
class Employee(AbstractUser):
username = models.CharField(max_length = 30)
first_name = models.CharField(max_length = 30)
last_name = models.CharField(max_length=30)
email = models.CharField(max_length=255)
password = models.CharField(max_length=30)
user_type = models.ForeignKey('UserProfile', null = True)
status = models.CharField(max_length = 30, default='Not Verified',)
def __str__(self):
return self.first_name + ' ' + self.last_name
That is my models.py pertaining to Employee
On the Admin page I see this - Admin Page
Learningsys is my app name.
How do I make it so that I see ''Employee or preferably 'Employees' under my app name instead of 'Users' and why does it show Users in the first place? I suspect it is because I am technically creating a 'Custom User' but would like clarification regardless.
Thanks,
Rohan.
You need to use verbose_name_plural meta option to change model's plural name on admin page:
class Employee(AbstractUser):
...
class Meta:
verbose_name_plural = 'Employees'
The default value of verbose_name_plural for AbstractUser is users so you inherited it with other AbstractUser's properties.
I'm trying to build a user profile which builds on the default Django user. I'm trying to extend the default user with an extra fields like this:
class MyMember(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL) #not sure about this
birthday = models.DateField()
USERNAME_FIELD = 'user' #how to use username field from default user?
REQUIRED_FIELDS = ['birthday',]
def __unicode__(self):
return self.username
But I'm getting this error: 'Manager' object has no attribute 'get_by_natural_key'? Why?
I would also like the USERNAME_FIELD to be the username from the default user. How?
Here's the UserProfile model class I use to extend the User model in my demo website:
#Private function required by image field.
def _get_upload_file_name_w_sub_dir(instance, filename):
return "uploaded_files/{0}{1}_{2}".format("profile_pic/", (str(time()).replace(".", "_"), filename))
class UserProfile(models.Model):
# This line is required. Links UserProfile to a User model instance.
# related_name is so you can reference *this* model as "user.profile"
# instead of "user.userprofile"
user = models.OneToOneField(User, related_name="profile")
# The additional attributes we wish to include.
year_discovered = models.IntegerField(blank=True,
verbose_name="Year you discovered Billy Joel's music/became a fan")
profile_picture = models.ImageField(upload_to=get_upload_profile_pic_file_name,
blank=True, null=True)
# Override the __unicode__() method to return out something meaningful!
def __unicode__(self):
return self.user.username
Here is the official documentation on extending the user model.
This is how you would extend the default Django User model. You would want to use a ForeignKey, and then you can use dot notation to access the fields of the User model.
Here:
from django.contrib.auth.models import User
class MyMember(models.Model):
user = models.ForeignKey(User)
birthday = models.DateField()
def __unicode__(self):
# the default "username" field in the django user model
return self.user.username