I have a user model that extended from AbstractBaseUser I've shown that below
class User(AbstractBaseUser,PermissionsMixin):
email = models.EmailField(verbose_name='email', max_length=80, unique=True)
username = models.CharField(max_length=30, unique=True)
first_name = models.CharField(max_length=100,null=True)
last_name = models.CharField(max_length=100,null=True)
phone_no = models.CharField(max_length=12, null=True)
date_joined = models.DateField(
verbose_name='date joined', auto_now_add=True)
last_login = models.DateField(verbose_name='last login', auto_now=True)
is_admin = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
is_teacher = models.BooleanField(default=False)
address = models.CharField(max_length=500, null=True, blank=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username']
objects = MyAccountManager()
def __str__(self):
return self.email
# def has_perm(self, perm, obj=None):
# return self.is_admin
def has_module_perms(self, app_label):
return True
Also, I need to update the User's details by using the view mentioned below
class UpdateUser(RetrieveUpdateAPIView):
permission_classes = (IsAuthenticated,)
serializer_class = UserSerializerAPI
queryset = User.objects.all()
After Changing user model details I can not log in. I'm using rest-auth login URL to log user in. When I try to log in it gives me an error saying
{
"non_field_errors": [
"Unable to log in with provided credentials."
]
}
What is the reason for that
class UpdateUser(RetrieveUpdateAPIView):
permission_classes = (IsAuthenticated,)
serializer_class = UserSerializerAPI
queryset = User.objects.all()
def perform_update(self, serializer):
instance = serializer.save()
instance.set_password(instance.password)
instance.save()
That's how I solved the problem
Related
I'm trying to display user specific content in my django website and I am one step away from completing this task. In models.py I need the contact_email field to have its default value to be the email of the logged in user. I've tried many methods of doing this but nothing has worked yet.
models.py
class Account(AbstractUser):
email = models.EmailField(verbose_name='email', max_length=60, unique=True)
name = models.CharField(max_length=45, unique=False)
username = models.CharField(max_length=100, default='')
date_joined = models.DateTimeField(verbose_name='date joined', auto_now_add=True)
last_login = models.DateTimeField(verbose_name='last login', auto_now=True)
is_admin = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
is_employee = models.BooleanField(default=True, verbose_name='Are you using FilmLink as an employee?')
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['name', 'is_employee']
objects = MyAccountManager()
class Meta:
permissions = [
("post_jobs", "Can post jobs"),
]
def __str__(self):
return self.name
def has_perm(self, perm, obj=None):
return True
def has_perms(self, perm):
return True
def has_module_perms(self, app_label):
return True
#property
def is_staff(self):
return self.is_admin
class Job(models.Model):
company = models.CharField(max_length=40, null=True, verbose_name="Company/Employer")
description = models.TextField(null=True)
role = models.CharField(max_length=25)
area_of_filming = models.CharField(max_length=50, verbose_name="Area Of Filming", default="")
contact_email = models.EmailField(verbose_name='Contact Email', max_length=60, default='')#stuck on setting this default
created = models.DateTimeField(auto_now_add=True)
user = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, on_delete=models.CASCADE)
def __str__(self):
return self.company
views.py
#login_required(login_url='login')
def manage_jobs(request):
if request.user.is_employee:
return redirect('home')
else:
form = JobForm(request.POST)
if form.is_valid():
form.save()
jobs = Job.objects.filter(contact_email = request.user.email)
context = {"form":form, "jobs":jobs}
return render(request, 'employer/manage-jobs.html', context)
forms.py
class JobForm(ModelForm):
class Meta:
model = Job
fields = ('company', 'description', 'role', 'area_of_filming', 'contact_email')
I don't believe you can set a default that way.
What you should do instead is, when creating a Job object and saving it to database, provide the value of contact_email yourself.
You would then be able to later filter the Job entries based on contact_email field.
# Creating a Job object
job = Job()
job.column1 = value
job.contact_email = request.user.email
# In other view, where you need to filter
jobs = Job.objects.filter(contact_email=request.user.email)
A random thought:
if the only reason you want that contact_email field there is to be able to apply the filter to get all Job objects for that particular user, then you can just filter with user field too.
jobs = Job.objects.filter(user=request.user)
context = {"form":form, "jobs":jobs, 'contact_email': request.user.email}
return render(request, 'employer/manage-jobs.html', context)
When I run api request I get a following error:
AttributeError: Got AttributeError when attempting to get a value for field email on serializer UserSerializer.
The serializer field might be named incorrectly and not match any attribute or key on the tuple instance.
Original exception text was: 'tuple' object has no attribute 'email'.
New user gets inserted in database anyway, email field is filleld properly.
View:
class Register(APIView):
def post(self, request):
serializer = UserSerializer(data=request.data)
if serializer.is_valid():
user = serializer.save()
if user:
return Response(serializer.data, status=status.HTTP_201_CREATED)
Serializer:
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['email', 'username', 'name', 'password']
def create(self, validated_data):
user = User.objects.create_user(**validated_data),
return user
Model:
class User(AbstractBaseUser):
email = models.EmailField(max_length=254, unique=True)
username = models.CharField(max_length=30, unique=True)
name = models.CharField(max_length=60)
date_of_birth = models.DateField(blank=True, null=True)
bio = models.CharField(default='', max_length=10000)
photo = models.ImageField(max_length=255, null=True, blank=True)
email_verified_at = models.DateTimeField(null=True, blank=True)
email_token_time = models.DateTimeField(null=True, blank=True)
email_token = models.CharField(default='', max_length=64)
password_token_time = models.DateTimeField(null=True, blank=True)
password_token = models.CharField(default='', max_length=64)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
last_seen = models.DateTimeField(null=True, blank=True)
USERNAME_FIELD = 'email'
EMAIL_FIELD = 'email'
REQUIRED_FIELDS = ['username', 'name']
objects = UserManager()
class Meta:
db_table = "User"
def __str__(self):
return self.username
I also have custom user manager, but that is probably irrelevant, and works as user does get inserted to database.
You have typo in this line:
user = User.objects.create_user(**validated_data),
It contains comma , in the last of line. So user become a tuple of user instance, not just user instance. It become (user,).
Should return user instance.
My User Model
SELLER = "SELLER"
CUSTOMER = "CUSTOMER"
USER_TYPE_CHOICES = (
('SELLER' , 'Seller'),
('CUSTOMER' , 'Customer'),
)
class User(AbstractBaseUser,PermissionsMixin):
email = models.EmailField( max_length=255, unique=True)
user_type = models.CharField(max_length=200,choices=USER_TYPE_CHOICES,null=True)
last_login = models.DateTimeField( blank=True, null=True)
is_staff = models.BooleanField( default=False)
is_superuser = models.BooleanField( default=False)
is_active = models.BooleanField( default=True)
date_joined = models.DateTimeField(default=timezone.now)
objects = UserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
class Meta:
ordering = ['email']
def clean(self):
super().clean()
self.email = self.__class__.objects.normalize_email(self.email)
def get_full_name(self):
return self.email
def get_short_name(self):
return self.email
I have two user_types one seller and one customer how i can use user_passes_test decorator to see if the user.user_type is seller so he can see the seller view only seller can see the seller view
def seller_home(request,pk):
try:
seller = Seller.objects.get(id=pk)
except User.DoesNotExist:
raise Http404("Seller Does Not Exisit")
sellerproducts = Product.objects.filter(seller=seller)
totalsellerproducts = sellerproducts.count()
context = {'seller':seller,'sellerproducts':sellerproducts,"totalsellerproducts":totalsellerproducts }
return render(request,"seller_home.html",context)
I think that you can't, because user_passes_test is for authenticated users only, so the seller or customer cannot be sent by URL to the view, because it will be insecure, anyone will be able to test any pk, You must use the authenticated user in request.user to do this, then the decorator will be easy. Something like this:
def seller_check(user):
return user.user_type == User.SELLER
#user_passes_test(seller_check)
def seller_home(request):
pass
Hi fellow programmers,
I am getting the following error when I try to visit my url can you please point out the mistake in my code. Is there any error in my serializer or view. I will be gateful if you find that.
Got AttributeError when attempting to get a value for field username on serializer PerformerSerializer.
The serializer field might be named incorrectly and not match any attribute or key on the User instance.
Original exception text was: 'User' object has no attribute 'user'.
models.py
class User(AbstractBaseUser):
username = models.CharField(_('Username'), unique=True,max_length=20)
email = models.EmailField(_('Email address'), unique=True)
is_staff = models.BooleanField(default=False)
is_admin = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
is_superuser = models.BooleanField(default=False)
last_login = models.DateTimeField(auto_now=True)
date_joined = models.DateTimeField(auto_now_add=True)
full_name = models.CharField(_("Full Name"), max_length=50,null=True)
date_of_birth = models.DateField(_("Date of birth"), auto_now=False, auto_now_add=False,null=True)
is_verified = models.BooleanField(_("Verified"), default=False)
profileImage = models.ImageField(_('Profile Image'),null=True, upload_to=None, height_field=None, width_field=None, max_length=100)
gender = models.CharField(_("Gender"), max_length=6, choices=GENDER_CHOICES,null=True)
profileTitle = models.CharField(_('Title'), max_length=20,null=True)
profileBio = models.TextField(_('Bio'),null=True)
profileWebsite = models.URLField(_('Website'), max_length=25,null=True)
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['email',]
objects = UserManager()
def has_perm(self,perm,obj=None):
return self.is_admin
def has_module_perms(self,app_label):
return True
def __str__(self):
return self.username
def natural_key(self):
return (self.username)
class Song(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
name = models.CharField(_("Name"), max_length=50)
song = models.FileField(_("Song"), upload_to=None, max_length=100)
song_image = models.ImageField(upload_to=None, height_field=None, width_field=None, max_length=100)
likes = models.IntegerField(_("Likes"),default=0)
views = models.IntegerField(_("Views"),default=0)
performer = models.ManyToManyField('self',verbose_name=_("Performed By"),related_name='artist_in_song')
def performer_user(self, username):
performer = Song.objects.get(user__username=username)
if not self.is_performer(performer):
self.performer.add(performer)
self.save()
return True
return False
def is_performer(self, username):
return self.performer.all().filter(user__username=username).exists()
serializers.py
class PerformerSerializer(serializers.ModelSerializer):
username = serializers.CharField(source='user.username')
class Meta:
model = Song
fields = ('username',)
class UserSerializer(serializers.ModelSerializer):
#id = serializers.ReadOnlyField(source='user.id')
class Meta:
model = User
fields = ('id',)
class SongSerializer(serializers.ModelSerializer):
performer = PerformerSerializer(many=True, read_only= True)
user= UserSerializer(many=False, read_only= True)
class Meta:
model = Song
fields = ('user','performer','id','name','song','song_image','likes','views')
read_only_fields = ('likes','views')
views.py
class SongCreateView(generics.ListCreateAPIView):
queryset = Song.objects.all()
serializer_class = SongSerializer
permission_classes = [IsAuthenticated]
Thank You.
I ran python manage.py migrate accounts zero then i faced an error,
I checked my models multiple times it seems everything is ok but...!?
This is the error:
django.db.utils.IntegrityError: (1062, "Duplicate entry '1' for key 'accounts_post_user_id_ecf3e197_uniq'")
User model:
class User(AbstractBaseUser):
id = models.BigAutoField(primary_key=True)
username = models.CharField(max_length=30, unique=True)
email = models.EmailField(max_length=191, unique=True)
email_verified = models.BooleanField(default=False)
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30, blank=True)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
is_admin = models.BooleanField(default=False)
is_verified = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
objects = UserManager()
USERNAME_FIELD = 'username'
EMAIL_FIELD = 'email'
REQUIRED_FIELDS = ['email', 'first_name', 'last_name']
def __str__(self):
return self.username
def has_perm(self, perm, obj=None):
return self.is_admin
def has_module_perms(self, app_label):
return self.is_admin
Post model:
class Post(models.Model):
id = models.BigAutoField(primary_key=True)
user = models.ForeignKey(User, on_delete=models.CASCADE)
channel = models.ForeignKey(Channel, on_delete=models.CASCADE, null=True, blank=True)
hashed_id = models.CharField(max_length=191)
text = models.TextField(max_length=270)
visits = models.IntegerField(default=0)
comment_status = models.BooleanField(default=True)
edited = models.BooleanField(default=False)
signature = models.CharField(max_length=191)
deleted_at = models.DateTimeField(null=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
There was 1 user with 2 posts.
I added unique=False to ForeignKey fields and it solved the problem.
I hope if this error occurs in your app this answer gives you a hand.