Django Rest Framework 中的数据流?

问题描述 投票:0回答:1

我最近开始学习 Django Rest Framework,并在尝试理解 DRF 中的数据流时遇到了一些障碍。

据我了解,视图接收 Web 请求并返回 Web 响应,因此它们是 DRF 数据流中的第一个组件,对吗? (在网址之后)。

那么第二步是什么呢?视图通常引用序列化器,因此接下来执行我们的序列化器。如果是这样,为什么不是我们的模型,因为序列化器用于将模型实例等复杂数据类型转换为 JSON。

在阅读完 DRF docs 教程第 4 部分后,我遇到了这个问题以及几个相关问题。

上下文:在文档中,我们正在创建代码片段,现在我们希望将用户与他们创建的代码片段关联起来。

我们按照以下顺序执行以下步骤来实现此目的:

在本教程下面,我们将创建一个序列化器来代表用户。序列化器如何帮助代表用户,序列化器不是用于转换数据吗?

1 为我们的用户模型添加端点

现在我们已经有了一些用户可以使用,我们最好将这些用户的表示添加到我们的 API 中。

class UserSerializer(serializers.ModelSerializer):
    snippets = serializers.PrimaryKeyRelatedField(many=True, queryset=Snippet.objects.all())

    class Meta:
        model = User
        fields = ['id', 'username', 'snippets']

下面是我的主要问题,文档说用户不是作为序列化表示的一部分发送的,而是传入请求的属性。

用户如何已经成为传入请求的一部分?难道我们不是想要添加用户以将片段与其创建者相关联的人吗?

2 将片段与用户关联

现在,如果我们创建了一个代码片段,则无法将创建该代码片段的用户与该代码片段实例关联起来。用户不是作为序列化表示的一部分发送的,而是传入请求的属性。

我们处理这个问题的方法是重写代码片段视图上的 .perform_create() 方法,该方法允许我们修改实例保存的管理方式,并处理传入请求或请求的 URL 中隐含的任何信息。

在 SnippetList 视图类上,添加以下方法:

def perform_create(self, serializer):
    serializer.save(owner=self.request.user)

这里我们如何检查传入请求的属性。

3 更新我们的序列化器

现在片段与创建它们的用户相关联,让我们更新 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)

我试图通过谷歌搜索来理解,但找不到满意的答案。

python django django-rest-framework
1个回答
0
投票

序列化器如何帮助代表用户,序列化器不是用于转换数据吗?

确实如此。

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

 的力量,请完成教程并进行每一点练习。

© www.soinside.com 2019 - 2024. All rights reserved.