【问题标题】:Consuming a Rest API in Django在 Django 中使用 Rest API
【发布时间】:2018-06-16 07:39:12
【问题描述】:

是否可以制作一个使用 REST API 作为外键的模型字段?

我有两个项目。第一个项目在models.py中有这个模型:

from django.db import models
from django_countries.fields import CountryField
from django.urls import reverse

class Currency(models.Model):
    name = models.CharField(max_length = 50)
    country = CountryField()
    code = models.CharField(max_length = 3)
    base = models.BooleanField()

    class Meta:
        ordering = ['code']

    def __str__(self):
        return (self.code)

    def get_absolute_url(self):
        return reverse('currency_detail', args = [str(self.id)])

我在 serializers.py 中使用以下代码对模型进行了序列化:

from rest_framework import serializers
from currencies . models import Currency

class CurrencySerializer(serializers.ModelSerializer):
    class Meta:
        model = Currency
        fields = ('name', 'code')

我创建了以下views.py:

from django.http import HttpResponse, JsonResponse
from django.views.decorators.csrf import csrf_exempt
from rest_framework.renderers import JSONRenderer
from rest_framework.parsers import JSONParser

from currencies . models import Currency
from . serializers import CurrencySerializer


def currency_list(request):
    currency = Currency.objects.all()
    serializer = CurrencySerializer(currency, many = True)
    return JsonResponse(serializer.data, safe = False)

并在 urls.py 中提供以下内容:

from django.conf.urls import url
from . import views

urlpatterns = [
    url(r'^currencies/$', views.currency_list),
]

URL 以 JSON 格式传递信息正常。没有身份验证(我还不够好)。当我使用 requests 库并发出 get 请求时,它返回以下内容:

[{"name": "Krone", "code": "DKK"}, {"name": "Pound Sterling", "code": "GBP"}, {"name": "Cedi", "code": "GHS"}]

我想在一个新项目中使用这些信息,该项目将有一个不同的数据库并使用以下模型发布记录:

class JournalEntry(models.Model):
    date = DateField()
    currency = ForeignKey(consuming the json data so it renders as a dropdown menu in html)
    value = IntegerField()

有没有一个好方法来做这样的事情?我还没有找到任何可以帮助我正确概念化这一点的回应。也是为了帮助我学习。我打算用这种基于 API 的方法来实现更复杂的项目。谢谢。

【问题讨论】:

  • 在您的第二个项目中(定义了JournalEntry),您不能访问第一个项目的Currency 模型吗?我的意思是...你不能按照currency = ForeignKey('other_project.Currency...)`的方式做点什么吗?
  • 我认为当一切都在我的计算机上时,您的方法效果很好。当我将项目 1 部署到 Elastic Beanstalk 时,我担心如何访问它的数据。我将在生产中试用它并回复您。感谢您的评论。我非常感激。

标签: python json django rest django-rest-framework


【解决方案1】:

您必须通过 API 稍微改变一下自己的心态。 API 是一个数据源,你必须问自己,你将如何使用这个数据源以及你接收到什么样的数据。

您将如何实现 API 取决于答案。在许多情况下,API 充当数据库。您查询 API 而不是查询数据库,从这个角度来看,将这些数据存储在另一个数据库中然后从那里查询相同的数据没有多大意义。还有一些情况,API 只提供当前数据而不提供历史数据,而您也希望历史数据可供您使用。在这种情况下,将 API 数据存储在数据库中是完全有意义的。还有其他情况,但这两种可能是最常见的。

如果您将其转化为您的情况,使用不存储的数据可能是首选,因为您可能希望用户只能选择当前可用的货币。这种情况下的代码是:

models.py

class JournalEntry(models.Model):
    date = DateField()
    currency = CharField(max_length=4)
    value = IntegerField()

forms.py

class JournalEntryForm(forms.ModelForm):
    class Meta:
        model = JournalEntry
        fields = '__all__'

views.py

def currency(request):
    form = JournalEntryForm()
    r = requests.get('currencies_url')
    currencies = r.json()
    if form.is_valid():
        form.save()

    return render(request, 'currency.html', {'currencies': currencies, 'form': form})

currency.html

<html>
  <body>
    <form method="POST">{% csrf_token %}
      {% for field in form %}
      <p>{{ field.date }}</p>
      <p>
        <select name="currency" id="id_currency" required="">
          {% for currency in currencies %}
          <option value="{{ currency.code }}">{{ currency.name }}</option>
          {% endfor %}
        </select>
      </p>
      <p>{{ field.value }}</p>
      <input type="submit" value="Save">
    </form>
  </body>
</html>

如果您出于某种原因希望将货币日期保存在数据库中,那么您首先需要使用从 API 接收的数据创建条目。代码会是这样的:

models.py

class Currency(models.Model):
    name = models.CharField(max_length=50)
    code = models.CharField(max_lenght=4)

class JournalEntry(models.Model):
    date = DateField()
    currency = ForeignKey(Currency)
    value = IntegerField()

forms.py

... same as before ...

views.py

def get_currencies(request):
    r = requests.get('currencies_url')
    currencies = r.json()
    currency_data = []
    for currency in currencies:
        c = Currency()
        c.name = currency['name']
        c.code = currency['code']
        currency_data.append(c)

   if len(currency_data) > 0:
       bulk_create  = Currency.objects.bulk_create(currency_data)

   return HttpResponse('Done!')

def currency(request):
    form = JournalEntryForm()
    if form.is_valid():
        form.save()

    return render(request, 'currency.html', {'form': form})

currency.html

<html>
  <body>
    <form method="POST">{% csrf_token %}
      {{ form.as_p }}
      <input type="submit" value="Save">
    </form>
  </body>
</html>

代码有点简化,但显示了一个基本原理。我使用bulk_create 来保存从 API 接收到的货币数据,因为它以有效的方式插入对象列表,只需 1 个查询。其余的应该是不言自明的。

【讨论】:

  • 非常感谢。这很有帮助。
猜你喜欢
  • 1970-01-01
  • 2020-09-05
  • 1970-01-01
  • 1970-01-01
  • 2020-05-15
  • 1970-01-01
  • 2018-07-13
  • 2021-12-27
  • 2013-07-07
相关资源
最近更新 更多