Reputation: 534
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:
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!
Upvotes: 2
Views: 908
Reputation: 1120
owner and profile is request.user
.
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')
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()
Upvotes: 1
Reputation: 48
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.
Upvotes: 0