Min*_*nnR 41 django django-rest-framework
我有以下代码完美地工作.我可以Post通过选择图像和用户从DRF面板创建对象.但是,我希望DRF由当前登录的用户填充用户字段.
models.py
class Post(TimeStamped):
user = models.ForeignKey(User)
photo = models.ImageField(upload_to='upload/')
hidden = models.BooleanField(default=False)
upvotes = models.PositiveIntegerField(default=0)
downvotes = models.PositiveIntegerField(default=0)
comments = models.PositiveIntegerField(default=0)
Run Code Online (Sandbox Code Playgroud)
serializers.py
class PostSerializer(serializers.ModelSerializer):
class Meta:
model = Post
fields = ['id', 'user', 'photo']
Run Code Online (Sandbox Code Playgroud)
views.py
class PhotoListAPIView(generics.ListCreateAPIView):
queryset = Post.objects.filter(hidden=False)
serializer_class = PostSerializer
authentication_classes = (SessionAuthentication, BasicAuthentication)
permission_classes = (IsAuthenticated,)
Run Code Online (Sandbox Code Playgroud)
我怎样才能做到这一点?
Mar*_*ons 55
您可以使用CurrentUserDefault:
user = serializers.PrimaryKeyRelatedField(
read_only=True,
default=serializers.CurrentUserDefault()
)
Run Code Online (Sandbox Code Playgroud)
见http://www.django-rest-framework.org/api-guide/validators/#currentuserdefault
Dav*_*ips 49
在我的头顶,您可以覆盖该perform_create()方法:
class PhotoListAPIView(generics.ListCreateAPIView):
...
def perform_create(self, serializer):
serializer.save(user=self.request.user)
Run Code Online (Sandbox Code Playgroud)
给它一个镜头,让我知道它是否有效
oli*_*del 15
这取决于您的使用案例.如果您希望它是"只写",意味着DRF会在写入时自动填充该字段而不返回读取,则根据文档的最直接实现将使用HiddenField:
class PhotoListAPIView(generics.ListCreateAPIView):
user = serializers.HiddenField(
default=serializers.CurrentUserDefault(),
)
Run Code Online (Sandbox Code Playgroud)
如果你想要它是可读的,你可以使用PrimaryKeyRelatedField,同时小心你的序列化程序在写入时预先填充字段 - 否则用户可以设置user指向其他随机用户的字段.
class PhotoListAPIView(generics.ListCreateAPIView):
user = serializers.PrimaryKeyRelatedField(
# set it to read_only as we're handling the writing part ourselves
read_only=True,
)
def perform_create(self, serializer):
serializer.save(user=self.request.user)
Run Code Online (Sandbox Code Playgroud)
最后,请注意,如果您使用的是更详细APIView而不是generics.ListCreateAPIView,则必须覆盖create而不是perform_create如此:
class PhotoListAPIView(generics.ListCreateAPIView):
user = serializers.PrimaryKeyRelatedField(
read_only=True,
)
def create(self, validated_data):
# add the current User to the validated_data dict and call
# the super method which basically only creates a model
# instance with that data
validated_data['user'] = self.request.user
return super(PhotoListAPIView, self).create(validated_data)
Run Code Online (Sandbox Code Playgroud)
小智 8
从DRF 版本 3.8.0(拉取请求讨论)开始,您可以save()在序列化程序中覆盖。
from rest_framework import serializers
...
class PostSerializer(serializers.ModelSerializer):
user = serializers.PrimaryKeyRelatedField(read_only=True, default=serializers.CurrentUserDefault())
class Meta:
model = Post
fields = ['id', 'user', 'photo']
def save(self, **kwargs):
"""Include default for read_only `user` field"""
kwargs["user"] = self.fields["user"].get_default()
return super().save(**kwargs)
Run Code Online (Sandbox Code Playgroud)
@DaveBensonPhillips 的答案可能会在您的特定情况下工作一段时间,但它不是很通用,因为它破坏了 OOP 继承链。
ListCreateAPIView继承自CreateModelMixin它已经保存了序列化器。您应该始终努力执行覆盖方法的完整链,除非您有充分的理由不这样做。这样你的代码就可以保持干爽并且能够抵抗变化:
class PhotoListAPIView(generics.ListCreateAPIView):
...
def perform_create(self, serializer):
serializer.validated_data['user'] = self.request.user
return super(PhotoListAPIView, self).perform_create(serializer)
Run Code Online (Sandbox Code Playgroud)
您可以避免user在请求中传递,并且您不会在输出中看到它,但是DRF会自动填充它:
from rest_framework import serializers
class MyModelSerializer(serializers.ModelSerializer):
user = serializers.HiddenField(default=serializers.CurrentUserDefault())
class Meta:
model = models.MyModel
fields = (
'user',
'other',
'fields',
)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
19819 次 |
| 最近记录: |