【问题标题】:Django REST framework serialize last logDjango REST框架序列化最后一个日志
【发布时间】:2017-08-22 15:06:00
【问题描述】:

我在一个网站中使用了Django rest框架,效果很好。

但我只是遇到了一个特殊的问题,就像这样:

models.py

class User(models.Model):
    uid = models.IntegerField(
        primary_key=True,
    )
    name = models.CharField(
        max_length=15,
    )

class LoginLog(models.Model):
    sn = models.AutoField(
        primary_key=True,
    )
    user = models.ForeignKey(
        to=User,
    )
    time = models.IntegerField(
        null=False,
    )
    IP = models.CharField(
        max_length=20,
        verbose_name='Login IP',
    )

serializers.py

class UserSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = User
        fields = '__all__'

class UserListView(generics.ListAPIView, ):
    queryset = User.objects.all()
    serializer_class = UserSerializer

如何序列化UserSerializer 中的最后一个LoginLog

只需像这样返回 json 数据:

{
    "name": "admin",
    "uid": 1,
    "last_login": {
        "time": 1503414665,
        "IP": "127.0.0.1"
    }
}

【问题讨论】:

    标签: django django-rest-framework


    【解决方案1】:

    因为您只想要时间,而不是整个实体:

    class UserSerializer(serializers.HyperlinkedModelSerializer):
        last_login_time = serializers.SerializerMethodField()
    
        def get_last_login_time(self, obj):
            last_login = obj.loginlog_set.last()
            if last_login is not None:
                return last_login.time
            return None
    
        class Meta:
            model = User
            fields = ('uid', 'account', 'last_login_time')
    

    此外,默认情况下将模型上的所有字段列入白名单可能会给您带来麻烦,不建议这样做。明确(如上)。

    【讨论】:

      【解决方案2】:

      一个可能的解决方案是使用SerializerMethodField:

      class UserSerializer(serializers.HyperlinkedModelSerializer):
          login_log = serializers.SerializerMethodField()
      
          class Meta:
              model = User
              fields = '__all__'
      
          def get_login_log(self, obj):
              last_login_log = obj.__class__.objects.filter(user=obj.user).last()
              login_log_serializer = LoginLogSerializer(last_login_log)
      
              return login_log_serializer.data
      
      • obj.__class__ 将简单地复制 LoginLog
      • 然后您过滤那些与您的用户相关的条目
      • 您获得last() 并将其序列化返回。

      这是否简单明了是有争议的,但它会给出想要的结果。这有点hacky。

      你可以看看这个:Return only last entry of related model in serializer - Django

      【讨论】:

      • 我刚试过,它返回错误如下:LoginLog is not JSON serializable
      • @YYLeo 我意识到我的错误。我用一个可能可行的解决方案更新了我的答案。
      • @YYLeo 另外,你需要实现一个LoginLogSerializer,因为这是一个嵌套关系。
      • 谢谢!我昨天试过了,它引发了另一个错误:'HyperlinkedIdentityField' requires the request in the serializer context. 我试图重载UserListView.get() 方法来传递请求,它引发了:'QuerySet' object has no attribute 'pk'
      • 我解决了这个问题,只要在get_login_log方法中获取request并传入LoginLogSerializer,就可以了。谢谢!
      猜你喜欢
      • 2015-06-29
      • 2017-06-25
      • 2017-01-07
      • 1970-01-01
      • 2020-03-22
      • 2015-10-29
      • 2017-02-09
      • 2015-07-06
      • 2021-06-23
      相关资源
      最近更新 更多