更新配置文件模型,该模型使用中间件last_activity字段DRF扩展了默认用户

问题描述

我正在尝试更新配置文件模型,以扩展认的用户模型。但是,由于Profile不显示任何条目,因此明显存在问题。您能否建议如何在扩展了另一个中间件的中间件中正确更新模型?

models.py

class Profile(models.Model):
    user = models.OnetoOneField(User,on_delete=models.CASCADE)
    last_activity = models.DateTimeField()  # filled in by middleware

    def __str__(self):
        return str(self.id)

serializers.py

class ProfileSerializer(serializers.ModelSerializer):
    class Meta:
        model = Profile
        fields = '__all__'

view.py

class ProfileList(ListAPIView):
    queryset = Profile.objects.all()
    serializer_class = ProfileSerializer

middleware.py

from django.utils import timezone

class UpdateLastActivityMiddleware(object):
def __init__(self,get_response):
    self.get_response = get_response

def __call__(self,request):
    return self.get_response(request)

def process_view(self,request,view_func,view_args,view_kwargs):
    if request.user.is_authenticated():
        # Update last visit time after request finished processing.
        # I'm trying to create record - in case user had no activity before
        Profile.objects.filter(user__id=request.user.pk).update_or_create(last_activity=timezone.Now())  # <-- looks like something is off here,since I'm not sure how to correctly update extended model

settings.py

MIDDLEWARE = [
    ...
    'core.middleware.UpdateLastActivityMiddleware',]

解决方法

numbers = [1,2,1,4,1]
count=0
for i in numbers :
    count=count+1
    if i == 1:
        a=[]
        a.append(count-1)
print(a)    #5

使用

Profile.objects.filter(user__id=request.user.pk).update_or_create(last_activity=timezone.now())

原因是由于这是一对一的关系,因此您不需要user.profile.last_activity=timezone.now() user.save() ,因为用户将始终拥有个人资料,反向关系应该可以立即使用,并且您可以进行更新属性update_or_create直接。

,

由于@Borko Kovacev和大量的Google搜索,这就是我最终得到的解决方案:

middleware.py

class UpdateLastActivityMiddleware:
    def __init__(self,get_response):
        self.get_response = get_response

    def __call__(self,request):
        return self.get_response(request)

    def process_view(self,request,view_func,view_args,view_kwargs):
        assert hasattr(request,'user')

        # need to separately detect user when used middleware with JWT (else Anonymous User)
        try:
            auth_res = authentication.JWTAuthentication().authenticate(request)
        except InvalidToken:
            return JsonResponse({'error': 'Invalid token'},status=status.HTTP_401_UNAUTHORIZED)

        if auth_res:
            request.user = auth_res[0]
        
        # save last_activity on each authenticated request
        if request.user.is_authenticated:
            request.user.profile.last_activity = timezone.now()  # assigning last_activity
            request.user.save()  # this triggers signal on User model saving
            print(f'MIDDLEWARE saved last_activity for {request.user}')

signals.py

from django.db.models.signals import post_save
from django.dispatch import receiver
from django.contrib.auth.models import User

from .models import Profile


@receiver(post_save,sender=User)  # to populate Profile on user creation (else fails because Profile record does not exist for user)
def create_profile(sender,instance,created,**kwargs):
    if created:
        print('signals create_profile ')
        Profile.objects.create(user=instance)

@receiver(post_save,sender=User)  # to update Profile on user update (triggered by middleware)
def save_profile(sender,**kwargs):
    print('signals save_profile ')
    instance.profile.save()