I have created a view where the logged-in user should be able to deactivate its profile.
I expect then to see the change being reflected in my admin section, but it's not.
Looks like the user is being deactivated but the user.profile isn't.
I am puzzled since, after I did a whole project following Django docs, the way to properly manage user deactivation seems missing.
I'd like to stay strict to Class-Based-Views.
My actual code:
# models.py
# Model to handle user profiles
class Profile(models.Model):
"""Create user profiles and manage their attributes"""
user = models.OneToOneField(User, on_delete=models.CASCADE)
bio = models.TextField(max_length=180, blank=True)
location = models.CharField(max_length=30, blank=True)
birth_date = models.DateField(null=True, blank=True)
avatar = models.ImageField(upload_to='social/static/social/avatars/', null=True, blank=True)
follows = models.ManyToManyField('self', related_name='followed_by', symmetrical=False, blank=True)
is_active = models.BooleanField(default=True)
def __str__(self):
return self.user.username
# Signal function to create a profile when a user is created
@receiver(post_save, sender=User)
def create_profile(sender, instance, created, **kwargs):
if created:
user_profile = Profile(user=instance)
user_profile.save()
# views.py
class ProfileInactive(View):
"""User can made its profile unactive"""
model = models.Profile
template_name = 'social/profile_delete.html'
# Users can delete only their profile, or get a 404 error
def get_queryset(self):
owner = self.request.user
return self.model.objects.filter(user=owner)
def get(self, request, username):
profile = get_object_or_404(models.Profile, user__username=self.kwargs['username'])
return render(request, self.template_name, {'profile': profile})
def post(self, request, username):
owner = self.request.user
profile = request.user
print(owner, profile)
if owner == profile:
profile.is_active = False
owner.is_active = False
profile.save()
owner.save()
logout(request)
else:
raise Http404
return redirect('social:register')
and the related url path:
path('profile_delete/<str:username>/', login_required(views.ProfileInactive.as_view()), name='profile_delete'),
The issue is that:
- After, apparently successfully, the user is being deactivated, the flag on its profile in the django admin section is still there, so like it's active, but the user cannot login anymore (like it isn't active anymore).
Example:
{{ profile.user.is_active }}
shows False
{{ profile.is_active }}
Shows True
I tried many combinations but not able to sort it out.
Also, I'd like to know if there's a pythonic way of managing what I expect to be a very common \ needed feature in any django application.
Thanks for any hints you may give me!
CodePudding user response:
owner and profile is request.user
.
Solution #1
in your model add related_name
:
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE,related_name="profile")
in your ProfileInactive.post method:
def post(self, request, username):
owner = self.request.user
profile = request.user.profile #
print(owner, profile)
if owner == profile:
profile.is_active = False
owner.is_active = False
profile.save()
owner.save()
logout(request)
else:
raise Http404
return redirect('social:register')
Solution #2
Using signals.
create signals.py file. add this snippet:
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.contrib.auth.models import User
@receiver(post_save,sender=User)
def update_profile(sender, instance, *args, **kwargs):
user= instance
profile = user.profile
if user.is_active == False:
profile.is_active = False
profile.save()
else:
profile.is_active = True
profile.save()
CodePudding user response:
In your "post" function, you're using the same user resource. i.e "self.request.user" and "request.user" is the same thing.
You should instead be doing a Profile.objects.get(user = request.user) and changing the is_active flag there.