Access Django custom user profile field - python

I added a custom user profile field role with the following models.py.
from django.contrib.auth.models import User
from django.db import models
from django.db.models.signals import post_save
from django.dispatch import receiver
class Profile(models.Model):
ROLE_CHOICES = (
(792, 'Student'),
(172, 'Teacher'),
(864, 'Supervisor'),
)
user = models.OneToOneField(User, on_delete=models.CASCADE)
role = models.IntegerField(choices=ROLE_CHOICES, null=True, blank=True)
def __str__(self):
return self.user.username
#receiver(post_save, sender=User)
def create_or_update_user_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
instance.profile.save()
What is the best way to return the int value assigned to the role? For example if the current logged in user is assigned the role of "Teacher", I want to be able to use the 172 value elsewhere like in views.py.

Currently logged in user is request.user, so
request.user.profile.role
will return 172, and
request.user.profile.get_role_display()
will return "Teacher". Note that you should omit parentheses if you are using the latter in a template.

Related

Having problem in automatically creating a customer field in database when some user signs up on website

this is my models.py
class MyUser(AbstractBaseUser):
email = models.EmailField(
verbose_name='email address',
max_length=255,
unique=True,
)
mobile = models.CharField(max_length=12)
first_name=models.CharField(max_length=20)
last_name=models.CharField(max_length=20)
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
objects = MyUserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['mobile','first_name','last_name']
class Customer(models.Model):
user=models.OneToOneField(MyUser,null=True,blank=True,on_delete=models.CASCADE)
name=models.CharField(max_length=100,null=True)
email=models.CharField(max_length=100)
mobile=models.CharField(max_length=12)
def __str__(self):
return self.name
class Order(models.Model):
customer=models.ForeignKey(Customer,on_delete=models.SET_NULL,null=True,blank=True)
date_ordered=models.DateTimeField(auto_now_add=True)
complete=models.BooleanField(default=False,null=True,blank=False)
transaction_id=models.CharField(max_length=100,null=True)
and this is my views.py
def signup(request):
if request.method == "POST":
first_name=request.POST['first_name']
last_name=request.POST['last_name']
email=request.POST['email']
mobile=request.POST['mobile']
password=request.POST['password']
cpassword=request.POST['cpassword']
if password==cpassword:
if User.objects.filter(email=email).exists():
messages.info(request,'Email already in use')
return redirect('signup')
elif User.objects.filter(mobile=mobile).exists():
messages.info(request,'Mobile Number already in use')
return redirect('signup')
else:
user=User.objects.create_user(first_name=first_name,last_name=last_name,email=email,password=password,mobile=mobile)
customer=Customer(user=user.email,mobile=mobile,name=first_name)
customer.save();
user.save();
return redirect('/login/')
else:
messages.info(request,'Passwords not matching')
return redirect('signup')
else:
return render(request,'signup.html')
I am working on a basic e-commerce website and to access the shopping cart the user must be registered.
The other model i am using is Order and which has a foreign key as customer.So basically to access the cart one has to be the customer.
The signup page that i have registers the users but also at the same time I want to make him/her a customer as well but i am not able to do it.
I tried using this
customer=Customer(user=user.email,mobile=mobile,name=first_name)
customer.save();
but i am getting error.
Please suggest some way so that whenever someone registers there is a customer object automatically created for him so that he can access the cart.
(i can manually set a customer in localhost/admin but thats extremely inefficient)
Following is a basic example.
Create signals.py file inside your app where models.py is located.
from django.contrib.auth import get_user_model
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.conf import settings
# User = get_user_model()
User = settings.AUTH_USER_MODEL
#receiver(post_save, sender=User)
def create_customer(sender, instance, created, **kwargs):
if created:
Customer.objects.create(user=instance)
#receiver(post_save, sender=User)
def save_customer(sender, instance, **kwargs):
instance.customer.save()

Duplicate key error when saving a new user

I'm trying to save a User and a Profile in django which are linked together using a oneToOneField but I'm getting an error saying
duplicate key value violates unique constraint
"auth_user_username_key
eventhough I dont have any duplicates.
I also get this error:
duplicate key value violates unique constraint
"api_profile_user_id_key" DETAIL: Key (user_id)=(9) already exists.
Here is my code:
model.py
from django.db import models
from django.contrib.auth.models import User
from django.db.models import CharField, OneToOneField
from django.db.models.signals import post_save
from django.dispatch import receiver
class Profile(models.Model):
user = OneToOneField(User, on_delete=models.CASCADE)
phone_number = CharField(max_length=20)
account_type = CharField(max_length=10, default='basic')
facebook_id = CharField(max_length=20, blank=True)
google_id = CharField(max_length=20, blank=True)
notification_id = CharField(max_length=40, blank=True)
# TODO add account info and watchlist
def __str__(self):
return self.user.email
#receiver(post_save, sender=User)
def user_save(sender, instance, **kwargs):
Profile.objects.create(user=instance)
view.py:
#api_view(['POST'])
def sign_up(request):
data = request.data
user = User.objects.create_user(username=data['username'],
password=data['password'],
first_name=data['first_name'],
last_name=data['last_name'],
email=data['email']
)
user.profile.phone_number = data['phone_number']
user.save()
return Response('hey')
I think the problem is in the post_save receiver however I'm not sure.
create_user is also calling save(), then you also call user.save(), the post_save signal is being called twice for one user, you get the error because two Profile objects are being created for one user
You could do:
#receiver(post_save, sender=User)
def user_save(sender, instance, **kwargs):
Profile.objects.get_or_create(user=instance)

Create profile at the same time that the user is created

I'm trying to create a profile in the DRF create function in serializer, but when save User model the next exception is triggered
ValueError: "<Usuario: Some Name>" needs to have a value for field "id" before this many-to-many relationship can be used.
This is my configuration background over python 3
Django == 1.11
DRF == Django rest framework
class CustomUserManager(BaseUserManager):
def _create_user(self, firstname, lastname, password, **extra_fields):
now = timezone.now()
if not firstname:
raise ValueError(u'The firstname is required.')
user = self.model(
firstname=firstname,
lastname=lastname,
last_login=now,
**extra_fields
)
user.set_password(password)
user.save()
return user
class Usuario(
AbstractBaseUser, PermissionsMixin,
TimeStampedModel, SoftDeletableModel
):
objects = CustomUserManager()
class Profile(models.Model):
user = models.OneToOneField(Usuario, related_name='profile', on_delete=models.CASCADE)
class UserSerializer(serializers.ModelSerializer):
profile = PerfilSerializer(read_only=True)
def create(self, validate_data):
user_data = validate_data
profile_data = validate_data.pop('profile')
usr = Usuario(**user_data)
usr.save()
profl = Profile(**profile_data)
profl.save()
profl.user.set(usr)
return usr
I want to get the model with the user instance and the profile created
You are on the right track, just tweak your create on the profile serializer. Try this:
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = Profile
def create(self, validated_data):
user = User.objects.create(**validated_data)
Profile.objects.create(user=user)
return user
Simply use Django Signals on User save.
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver
#receiver(post_save, sender=User)
def save_profile(sender, instance, **kwargs):
instance.profile.save()
Check out this concrete tutorial, as it solves your problem.
https://simpleisbetterthancomplex.com/tutorial/2016/07/28/how-to-create-django-signals.html
Glad to help you!

primary key must be unique when extending table

I'm trying to add extend user model. I keep getting this error: Primary key is not unique.
class UserExtended(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE,parent_link=True,primary_key=True)
If I remove primary_key=True then I get the error instance.userextended.id does not exists well, of course it doesn't since now I dont have id.
How do I get around this?
In models.py
from django.contrib.auth.models import User
from django.db.models.signals import post_save
from django.dispatch import receiver
class UserExtended(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
# Then you can also add fields like these to extended model
profilepic = models.ImageField(upload_to='uploads/users/%Y/%m/%d/', null=True, blank=True)
designation = models.CharField(max_length=200,null=True, blank=True)
about = models.TextField(null=True, blank=True)
website = models.URLField(null=True,blank=True)
def __str__(self):
return self.user.username
#receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
if created:
UserExtended.objects.create(user=instance)
#receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
instance.userextended.save()
Now, whenever a new user is created, a extended record for that user will be created automatically.
Also, if a user record is saved, then it will automatically be updated in extended record.

Django | How to reference the User's username when using OneToOneField in UserProfile?

Here's my models.py:
from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
class Userprofile(models.Model):
user = models.OneToOneField(User, primary_key=True)
username = user.__unicode__()
path = './data/'+username+'/'
file = models.FileField(upload_to=path)
labelfile = models.FileField(upload_to=path, blank=True)
def __unicode__(self):
return u"%s" % self.user.username
def create_user_profile(sender, instance, created, **kwargs):
if created:
Userprofile.objects.create(user=instance)
post_save.connect(create_user_profile, sender=User)
the problem is:
AttributeError: 'OneToOneField' object has no attribute 'model'
I want a file upload function that it can save in a index related to the User's name, but I can't find a good way to do it. And I hope someone can help me. Thanks.

Categories