Правильный способ деактивации пользователя и его профиля в Django
Я создал представление, в котором вошедший пользователь должен иметь возможность деактивировать свой профиль.
Я ожидаю, что изменение будет отражено в разделе администратора, но этого не происходит.
Похоже, что пользователь деактивируется, а профиль пользователя - нет.
Я в недоумении, поскольку после того, как я сделал целый проект, следуя документации Django, способ правильного управления деактивацией пользователя кажется отсутствующим.
Я бы хотел оставаться строгим к Class-Based-Views.
Мой фактический код:
# 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')
и соответствующий путь url:
path('profile_delete/<str:username>/', login_required(views.ProfileInactive.as_view()), name='profile_delete'),
Вопрос в том, что:
- После того, как пользователь, по-видимому, успешно, деактивируется, флаг на его профиле в разделе django admin все еще там, так что он как будто активен, но пользователь больше не может войти (как будто он больше не активен).
Пример:
{{ profile.user.is_active }} показывает False
{{ profile.is_active }} показывает True
Я пробовал много комбинаций, но не смог разобраться.
Кроме того, я хотел бы знать, есть ли питонический способ управления тем, что, как я ожидаю, будет очень распространенной \ необходимой функцией в любом приложении django.
Спасибо за любые подсказки, которые вы можете мне дать!
владельцем и профилем является request.user.
Решение №1
в вашей модели добавьте related_name:
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE,related_name="profile")
в вашем методе ProfileInactive.post:
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')
Решение №2
Использование сигналов.
создайте файл signals.py. добавьте этот фрагмент:
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()
В вашей функции "post" вы используете один и тот же ресурс пользователя. Т.е. "self.request.user" и "request.user" - это одно и то же.
Вместо этого вам следует выполнить Profile.objects.get(user = request.user) и изменить там флаг is_active.