You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否在Django中创建以REST API为数据源的外键模型字段?

Absolutely, there are a few solid, beginner-friendly approaches to solve this problem—perfect for learning how to integrate independent Django services. Let’s break down the most practical methods based on your needs:

Method 1: Load Dropdown Options via Frontend AJAX (Real-Time Data)

This approach pulls the latest currency data directly from the first project's API when the user loads the form, great if the currency list changes frequently.

Step 1: Update the JournalEntry Model

Since you can't use a ForeignKey across separate databases, store the currency code as a CharField:

# Second project's models.py
from django.db import models

class JournalEntry(models.Model):
    date = models.DateField()
    # Store the 3-letter currency code (e.g., "DKK", "GBP")
    currency = models.CharField(max_length=3)
    value = models.IntegerField()

Step 2: Render the Form and Populate with JavaScript

Create a template that renders an empty dropdown, then use fetch() to pull data from the API and populate it:

<!-- Second project's template: journalentry_form.html -->
<form method="post">
    {% csrf_token %}
    {{ form.as_p }}
    
    <!-- Custom currency dropdown -->
    <label for="id_currency">Currency:</label>
    <select id="id_currency" name="currency" required>
        <option value="">Select a currency</option>
    </select>
    
    <button type="submit">Save Entry</button>
</form>

<script>
// Fetch currency data from the first project's API
fetch('http://your-first-project-domain/currencies/')
    .then(response => response.json())
    .then(data => {
        const selectElement = document.getElementById('id_currency');
        data.forEach(currency => {
            const option = document.createElement('option');
            option.value = currency.code;
            option.textContent = `${currency.name} (${currency.code})`;
            selectElement.appendChild(option);
        });
    })
    .catch(error => console.error('Failed to load currencies:', error));
</script>

Step 3: Fix Cross-Origin Requests (CORS)

The first project needs to allow the second project to access its API. Install django-cors-headers in the first project:

pip install django-cors-headers

Then update its settings.py:

# First project's settings.py
INSTALLED_APPS = [
    # ... other apps
    'corsheaders',
]

MIDDLEWARE = [
    # ... other middleware
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.common.CommonMiddleware',
]

# Allow your second project's domain (use "*" for development only)
CORS_ALLOWED_ORIGINS = [
    "http://your-second-project-domain:8000",
]

Method 2: Populate Dropdown via Backend API Call (Server-Side Control)

If you need server-side validation or want to handle API errors gracefully, pull the currency data when initializing the form in the backend.

Step 1: Model Setup

Same as Method 1—use a CharField for currency.

Step 2: Create a Custom Form

Use requests to fetch data from the API and populate the dropdown choices when the form loads:

# Second project's forms.py
from django import forms
import requests
from .models import JournalEntry

class JournalEntryForm(forms.ModelForm):
    currency = forms.ChoiceField(choices=[], required=True)

    class Meta:
        model = JournalEntry
        fields = ['date', 'currency', 'value']

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # Fetch currency data from the external API
        try:
            response = requests.get('http://your-first-project-domain/currencies/')
            response.raise_for_status()  # Raise error for bad HTTP status codes
            currencies = response.json()
            
            # Convert API data to Django choice format: (value, display_text)
            self.fields['currency'].choices = [
                (curr['code'], f"{curr['name']} ({curr['code']})")
                for curr in currencies
            ]
            
            # Set initial value if editing an existing entry
            if self.instance.pk:
                self.fields['currency'].initial = self.instance.currency
        except requests.exceptions.RequestException as e:
            # Fallback if API is down
            self.fields['currency'].choices = [('', 'Could not load currencies')]

Step 3: Use the Form in Your View

# Second project's views.py
from django.shortcuts import render, redirect
from .forms import JournalEntryForm

def create_journal_entry(request):
    if request.method == 'POST':
        form = JournalEntryForm(request.POST)
        if form.is_valid():
            form.save()
            return redirect('journalentry_list')  # Redirect to your list view
    else:
        form = JournalEntryForm()
    return render(request, 'journalentry_form.html', {'form': form})

Your template can just use {{ form.as_p }}—the dropdown will be pre-populated with data from the API.


Method 3: Sync API Data to Local Database (Offline Access)

If you need to query currency data locally or work offline, sync the API data to a local model in the second project.

Step 1: Create Local Models

# Second project's models.py
from django.db import models

class LocalCurrency(models.Model):
    name = models.CharField(max_length=50)
    code = models.CharField(max_length=3, unique=True)

    def __str__(self):
        return f"{self.name} ({self.code})"

class JournalEntry(models.Model):
    date = models.DateField()
    # Now you can use a ForeignKey to the local currency model
    currency = models.ForeignKey(LocalCurrency, on_delete=models.PROTECT)
    value = models.IntegerField()

Step 2: Create a Sync Command

Make a Django management command to pull data from the API and update your local database:

# Second project: management/commands/sync_currencies.py
import requests
from django.core.management.base import BaseCommand
from your_app_name.models import LocalCurrency

class Command(BaseCommand):
    help = 'Sync currencies from the external Django API'

    def handle(self, *args, **options):
        try:
            response = requests.get('http://your-first-project-domain/currencies/')
            response.raise_for_status()
            currencies = response.json()
            
            # Update or create local currency records
            for curr in currencies:
                LocalCurrency.objects.update_or_create(
                    code=curr['code'],
                    defaults={'name': curr['name']}
                )
            
            self.stdout.write(self.style.SUCCESS('Successfully synced currencies!'))
        except requests.exceptions.RequestException as e:
            self.stdout.write(self.style.ERROR(f'Sync failed: {str(e)}'))

Step 3: Run the Sync

Execute the command to populate your local currency table:

python manage.py sync_currencies

For regular updates, set up a cron job or use a task manager like Celery to run this command automatically.

Now your JournalEntry form will automatically render a dropdown from the LocalCurrency model—no extra frontend or backend work needed!


Which Method Should You Choose?

  • Method 1: Best for real-time data updates, frontend-focused.
  • Method 2: Ideal if you need server-side validation or error handling.
  • Method 3: Great for offline access or when you need to query currency data locally.

内容的提问来源于stack exchange,提问作者Solomon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:44:49