我最近开始学习 Django Rest Framework,并在尝试理解 DRF 中的数据流时遇到了一些障碍。
据我了解,视图接收 Web 请求并返回 Web 响应,因此它们是 DRF 数据流中的第一个组件,对吗? (在网址之后)。
那么第二步是什么呢?视图通常引用序列化器,因此接下来执行我们的序列化器。如果是这样,为什么不是我们的模型,因为序列化器用于将模型实例等复杂数据类型转换为 JSON。
在阅读完 DRF docs 教程第 4 部分后,我遇到了这个问题以及几个相关问题。
上下文:在文档中,我们正在创建代码片段,现在我们希望将用户与他们创建的代码片段关联起来。
我们按照以下顺序执行以下步骤来实现此目的:
在本教程下面,我们将创建一个序列化器来代表用户。序列化器如何帮助代表用户,序列化器不是用于转换数据吗?
现在我们已经有了一些用户可以使用,我们最好将这些用户的表示添加到我们的 API 中。
class UserSerializer(serializers.ModelSerializer):
snippets = serializers.PrimaryKeyRelatedField(many=True, queryset=Snippet.objects.all())
class Meta:
model = User
fields = ['id', 'username', 'snippets']
下面是我的主要问题,文档说用户不是作为序列化表示的一部分发送的,而是传入请求的属性。
用户如何已经成为传入请求的一部分?难道我们不是想要添加用户以将片段与其创建者相关联的人吗?
现在,如果我们创建了一个代码片段,则无法将创建该代码片段的用户与该代码片段实例关联起来。用户不是作为序列化表示的一部分发送的,而是传入请求的属性。
我们处理这个问题的方法是重写代码片段视图上的 .perform_create() 方法,该方法允许我们修改实例保存的管理方式,并处理传入请求或请求的 URL 中隐含的任何信息。
在 SnippetList 视图类上,添加以下方法:
def perform_create(self, serializer):
serializer.save(owner=self.request.user)
这里我们如何检查传入请求的属性。
现在片段与创建它们的用户相关联,让我们更新 SnippetSerializer 以反映这一点。 将以下字段添加到serializers.py中的序列化器定义中:
owner = serializers.ReadOnlyField(source='owner.username')
这三个步骤如何帮助将用户添加到我们的片段中。这里的数据到底是如何流动的?
谢谢你。
P.S:看了别人写的代码后我有一个问题,serializer.save(data=data) 或serializer.create(data=data) 是什么意思?
代码如下:
views.py
class SnippetList(generics.ListCreateAPIView):
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
permission_classes = [permissions.IsAuthenticatedOrReadOnly]
def perform_create(self, serializer):
serializer.save(owner= self.request.user)
序列化器.py
class SnippetSerializer(serializers.ModelSerializer):
owner = serializers.ReadOnlyField(source="owner.username")
class Meta:
model = Snippet
fields = ["id", "title" , "code", "linenos", "language", "style", "owner"]
class UserSerializer(serializers.ModelSerializer):
snippets = serializers.PrimaryKeyRelatedField(many=True, queryset=Snippet.objects.all())
class Meta:
model = User
fields = ["id", "username", "snippets"]
模型.py
class Snippet(models.Model):
created = models.DateTimeField(auto_now_add=True)
title = models.CharField(max_length=100, blank=True, default='')
code = models.TextField()
linenos = models.BooleanField(default=False)
language = models.CharField(choices=LANGUAGE_CHOICES, default="python", max_length=100)
style = models.CharField(choices=STYLE_CHOICES, default="friendly", max_length=100)
owner = models.ForeignKey("auth.User", related_name="snippets", on_delete=models.CASCADE)
highlighted = models.TextField()
class Meta:
ordering = ['created']
def save(self,*args, **kwargs):
"""
Use the "pygments" library to create a highlighted HTML representation of the code snippet.
"""
lexer = get_lexer_by_name(self.language)
linenos = "table" if self.linenos else False
options = {"title": self.title} if self.title else{}
formatter = HtmlFormatter(style=self.style, linenos=linenos, full=True ,**options)
self.highlighted = highlight(self.code, lexer, formatter)
super().save(*args, **kwargs)
我试图通过谷歌搜索来理解,但找不到满意的答案。
序列化器如何帮助代表用户,序列化器不是用于转换数据吗?
确实如此。
Serializer
允许复杂的数据(例如QuerySet
和Model
实例)转换为原生Python数据类型,然后可以轻松呈现为JSON、XML或其他内容类型。 Serializer
还提供反序列化,允许在首先验证传入数据后将解析的数据转换回复杂类型。
...文档说用户不是作为序列化表示的一部分发送的,而是传入请求的属性。当用户在 Django 中进行身份验证时,
user
的属性
HttpRequest
成为
AUTH_USER_MODEL
的实例,代表当前登录的用户。如果用户当前未登录,
user
将被设置为
AnonymousUser
的实例。在这种情况下,DRF 不会更改任何内容,因此您始终可以通过
HttpRequest.user
获取当前登录用户的实例。由此可见,没有必要将其作为request.body
的一部分发送。
这里我们如何检查传入请求的属性[?]您可以通过运行检查来判断用户是否已登录:
if request.user.is_authenticated:
print("Yes user is logged in.")
这三个步骤如何帮助将用户添加到我们的片段中[?]有很多方法可以解决这个问题,但我将给出最基本的方法以避免混淆:
像这样
model
Snippet
:
class Snippet(models.Model):
#•••Rest of code•••
owner = models.ForeignKey("auth.User", related_name="snippets", on_delete=models.CASCADE)
#•••Rest of code•••
您可以像这样创建一个新的Snippet
:
snippet = Snippet.objects.create(
#•••Other fields•••
owner = request.user
#•••Rest of code•••
)
关于 Serializer
的整个 DRF 文档旨在向您展示它们有多么强大。上面的示例可以用
Serializer
来完成。使用
Serializer
,您可以反序列化已解析的
body
的
HttpRequest
,对其进行验证并将
save()
反序列化值存入数据库。
Serializer
的力量,请完成教程并进行每一点练习。