首页 > 解决方案 > 围绕外部数据构建对象模型

问题描述

我想将外部数据集成到 Django 应用程序中。例如,假设我想处理 GitHub 问题,就好像它们在 Django 中被制定为普通模型一样。所以在这些对象下,我使用 GitHub API 来检索和存储数据。

特别是,我还希望能够从模型中引用 GitHub 问题,而不是反过来。即,我不打算直接修改或扩展外部数据。

视图将使用这种抽象来获取数据,但也会遵循从“普通对象”到外部数据属性的引用。简单的连接也很好,但显然会有限制。

是否有任何示例说明如何以惯用的方式实现这一目标?

理想情况下,这也将被拆分为一般描述 API 的一般部分,以及类似于描述普通 ORM 类的类的描述部分。

标签: pythondjango

解决方案


如果你想为你的 Github 问题使用类似 Django 模型的界面,为什么不使用真正的Django 模型呢?例如,您可以fetch在模型中创建一个方法,该方法将从远程 api 加载数据并将其保存到您的模型中。这样,您就不需要在代码中的任何地方发出外部请求,而只是在您需要的时候。一个最小的示例如下所示:

import requests
from django.db import models

from .exceptions import GithubAPIError


class GithubRepo(models.Model):
    api_url = models.URLField()  # e.g. https://api.github.com/repos/octocat/Hello-World


class GithubIssue(models.Model):
    issue_id = models.IntegerField()
    repo = models.ForeignKey(GithubRepo, on_delete=models.CASCADE)

    node_id = models.CharField(max_length=100)
    title = models.CharField(max_length=255, null=True, blank=True)
    body = models.TextField(null=True, blank=True)

    """
    Other fields
    """

    class Meta:
        unique_together = [["issue_id", "repo"]]

    @property
    def url(self):
        return f"{self.repo.api_url}/issues/{self.issue_id}"

    def fetch_data(self):
        response = requests.get(self.url)
        if response.status != 200:
            raise GithubAPIError("Something went wrong")

        data = response.json()

        # populate fields from repsonse
        self.title = data['title']
        self.body = data['body']

    def save(
        self, force_insert=False, force_update=False, using=None, update_fields=None
    ):
        if self.pk is None:  # fetch on first created
            self.fetch_data()
            super(GithubIssue, self).save(
                force_insert, force_update, using, update_fields
            )


您还可以为您的模型编写一个自定义管理器,该管理器将在您每次调用create方法时获取数据 -GithubIssue.objects.create()


推荐阅读