Quiero integrar datos externos en una aplicación Django. Digamos, por ejemplo, que quiero trabajar con problemas de GitHub como si estuvieran formulados como modelos normales dentro de Django. Debajo de estos objetos, uso la API de GitHub para recuperar y almacenar datos.
En particular, también quiero poder hacer referencia a los problemas de GitHub de los modelos, pero no al revés. Es decir, no tengo la intención de modificar o ampliar los datos externos directamente.
Las vistas usarían esta abstracción para obtener datos, pero también para seguir las referencias de "objetos normales" a las propiedades de los datos externos. También sería bueno tener uniones simples, pero claramente habría limitaciones.
¿Hay algún ejemplo de cómo lograr esto de una manera idiomática?
Idealmente, esto también se dividiría en una parte general que describe la API en general, y una parte descriptiva de las clases similar a cómo se describen las clases ORM normales.
Sugeriría usar los principios normales de programación orientada a objetos, polimorfismo, asociación, etc. para obtener una sensación similar a los modelos reales.
Pero no estoy seguro de intentar simular el comportamiento lo más cerca posible, porque el ORM está diseñado específicamente para la interacción con la base de datos. Simplemente escribiría mis métodos personalizados.
La forma de django en este caso sería escribir un backend "db" personalizado.
Este repositorio parece abandonado, pero aún puede llevarlo a algunas ideas.
Si desea usar una interfaz similar a Django Model para sus problemas de Github, ¿por qué no usar modelos reales de Django ? Puede, por ejemplo, crear un método de fetch en su modelo, que cargará datos desde la API remota y los guardará en su modelo. De esa manera, no necesitará realizar solicitudes externas en todas partes de su código, sino solo cuando lo necesite. Un ejemplo mínimo se verá así:
import requests from django.db import models from .exceptions import GithubAPIError class GithubRepo(models.Model): api_url = models.URLField() # eg 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 ) También puede escribir un Administrador personalizado para su modelo que obtendrá datos cada vez que llame a un método de create : GithubIssue.objects.create()