Правильный способ деактивации пользователя и его профиля в 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.

Вернуться на верх