thepoy 发表于 2019-11-27 17:49

django-rest,自定义viewsets.ModelViewSet中的create方法遇到的问题

本帖最后由 thepoy 于 2019-11-27 18:08 编辑

有两个model,一个是user,一个是address,二者是一对多的关系,address中有外键指向user:
#### models:
```python
class UserModel(models.Model):
    name = models.CharField(max_length=20, unique=True)
    password = models.CharField(max_length=256)


class Address(models.Model):
    addr = models.CharField(max_length=128)
    user = models.ForeignKey(UserModel, on_delete=models.CASCADE, null=True)
```

#### serializers:
```python
class UserSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
      model = UserModel
      fields = ['url', 'id', 'name', 'password']


class AddressSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
      model = Address
      fields = ['url', 'id', 'addr', 'user_id']
```


希望在创建地址时,不需要在form中添加user_id,直接把地址中的user增加为现在登录的用户,所以修改create方法如下:
```python
    def create(self, request, *args, **kwargs):
      data = request.data.copy()
      # 直接在把已登录的user_id添加到data中
      # 试过把user_id改为user,结果一样
      data.__setitem__('user_id', request.user.id)
      print(data)
      # 把已经添加过user_id的data作为序列化的参数
      serializer = self.get_serializer(data=data)
      serializer.is_valid(raise_exception=True)
      self.perform_create(serializer)
      headers = self.get_success_headers(serializer.data)
      print(serializer.data)
      return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
```

最后上面打印的结果:
```
data--><QueryDict: {'addr': ['重庆'], 'user_id': }>
serializer.data-->{'url': 'http://localhost:8000/app/address/16/', 'id': 16, 'addr': '重庆', 'user_id': None}
```

可以看见,data中user_id确实已经添加进去了,但是序列化后,serializer.data中的user_id却是None。

实在是搞不懂其中原理。

在为了减少IO、不修改Address的model的前提下,
如何才能在create中将address的user改为正在登录的user呢?

pangdong697 发表于 2019-11-27 18:28

class AddressSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
      model = Address
      fields = ['url', 'id', 'addr', 'user_id']
其中的user_id 只是关键生成的,并不是在数据库中真实存在的,如果要使用需要在序列化中定义一下
class AddressSerializer(serializers.HyperlinkedModelSerializer):
    user_id = serializers.IntegerField()
    class Meta:
      model = Address
      fields = ['url', 'id', 'addr', 'user_id']

thepoy 发表于 2019-11-28 09:12

pangdong697 发表于 2019-11-27 18:28
class AddressSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
      model = A ...
昨晚已经发现了,不过你说的跟我理解的不太一样,我个人觉得,user_id在数据库中是存在的,但在serializer.data中,user_id因为是外键引入的问题,默认是ReadOnlyField,解决这个ReadOnly需要重新在serializer中定义这个字段,解决办法正是与你的回答相同。
以上是我个人的理解,不知道对不对,但是是顺着这个思路解决的。
页: [1]
查看完整版本: django-rest,自定义viewsets.ModelViewSet中的create方法遇到的问题