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

如何在Django Admin数据表中展示API获取的数据

实现从远程API获取数据并在Django Admin展示的方案

核心思路

由于数据不再存储在本地数据库,我们需要重写Django Admin的列表视图,直接从指定GET API拉取数据,转换为模型实例后渲染到Admin表格中;同时可扩展编辑功能,调用远程API完成数据更新。


步骤1:调整Admin类,重写列表视图

修改profile_management/admin.py,重写changelist_view方法来获取远程API数据,并替换默认的查询集:

from django.contrib import admin
from django.urls import reverse
from django.utils.html import format_html
from django.contrib.admin.views.main import ChangeList
from django.contrib import messages
import requests
from datetime import date
from profile_management.models import ClientProfile
from package_management.models import Package


@admin.register(ClientProfile)
class ProfileAdmin(admin.ModelAdmin):
    list_display = (
        'profile_auto_increment_id', 'profile_name', 'profile_status', 
        'subscribed_package_name', 'expire_date', 'action_column'
    )
    search_fields = ('profile_name',)
    list_filter = ('active_status', )

    def profile_auto_increment_id(self, obj):
        if obj.pk:
            return f"#{obj.pk}"
        else:
            return "(Not saved)"
    profile_auto_increment_id.short_description = 'ID'

    def profile_status(self, obj):
        return '<span style="color:green">Active</span>' if obj.active_status else '<span style="color:red">Inactive</span>'
    profile_status.short_description = 'Status'
    profile_status.allow_tags = True

    def subscribed_package_name(self, obj):
        return obj.subscribed_package.package_name if obj.subscribed_package else "Unknown"
    subscribed_package_name.short_description = 'Subscribed Package'

    def action_column(self, obj):
        edit_url = reverse('admin:profile_management_clientprofile_change', args=[obj.pk])
        return format_html(
            '<a href="{}" class="button">Edit</a>', edit_url
        )
    action_column.short_description = 'Actions'

    def changelist_view(self, request, extra_context=None):
        # 从远程API拉取所有数据
        api_url = "http://x.xxx.xxx.xx/api2/get_all_profile"
        profiles_data = []
        try:
            response = requests.get(api_url)
            response.raise_for_status()
            profiles_data = response.json()
        except requests.exceptions.RequestException as e:
            messages.error(request, f"无法获取用户数据: {str(e)}")

        # 将API数据转换为ClientProfile实例
        profiles = []
        for data in profiles_data:
            profile = ClientProfile()
            profile.pk = data.get('id')
            profile.profile_name = data.get('profile_name')
            profile.active_status = data.get('active_status')
            
            # 关联Package模型(根据API返回的ID获取本地Package实例)
            try:
                profile.subscribed_package = Package.objects.get(id=data.get('subscribed_package'))
            except Package.DoesNotExist:
                profile.subscribed_package = None
                
            profile.plugin_platform = data.get('plugin_platform')
            # 转换日期字符串为date对象
            profile.expire_date = date.fromisoformat(data.get('expire_date')) if data.get('expire_date') else None
            profile.company_email = data.get('company_email')
            profile.company_phone = data.get('company_phone')
            profile.website = data.get('website')
            profile.company_address = data.get('company_address')
            profile.main_client = data.get('main_client')
            profiles.append(profile)

        # 处理搜索过滤
        if 'q' in request.GET:
            search_term = request.GET.get('q').lower()
            profiles = [p for p in profiles if search_term in p.profile_name.lower()]

        # 处理状态筛选
        if 'active_status' in request.GET:
            status_filter = request.GET.get('active_status')
            if status_filter == 'True':
                profiles = [p for p in profiles if p.active_status]
            elif status_filter == 'False':
                profiles = [p for p in profiles if not p.active_status]

        # 构建Admin所需的ChangeList对象
        cl = ChangeList(
            request, self.model, self.list_display, self.list_display_links, 
            self.list_filter, self.date_hierarchy, self.search_fields, 
            self.list_select_related, self.list_per_page, self.list_max_show_all, 
            self.list_editable, self
        )
        cl.result_list = profiles
        cl.result_count = len(profiles)
        cl.full_result_count = len(profiles)
        cl.show_all = False
        cl.can_show_all = False

        extra_context = extra_context or {}
        extra_context['cl'] = cl
        return super().changelist_view(request, extra_context=extra_context)

步骤2:扩展编辑功能(可选)

如果需要在Admin中编辑远程数据,重写change_view方法,实现从API拉取单条数据、提交表单到API更新:

2.1 创建自定义表单

在profile_management/forms.py中创建表单:

from django import forms
from profile_management.models import ClientProfile

class ClientProfileForm(forms.ModelForm):
    class Meta:
        model = ClientProfile
        fields = [
            'profile_name', 'active_status', 'subscribed_package', 
            'plugin_platform', 'expire_date', 'company_email', 
            'company_phone', 'website', 'company_address', 'main_client'
        ]

2.2 在Admin类中添加编辑视图

在ProfileAdmin类中添加以下方法:

from django.shortcuts import render, redirect
from profile_management.forms import ClientProfileForm

def change_view(self, request, object_id, form_url='', extra_context=None):
    # 从API拉取单条数据
    detail_api_url = f"http://x.xxx.xxx.xx/api2/get_profile/{object_id}"
    profile_data = {}
    try:
        response = requests.get(detail_api_url)
        response.raise_for_status()
        profile_data = response.json()
    except requests.exceptions.RequestException as e:
        messages.error(request, f"无法获取用户详情: {str(e)}")
        return redirect('admin:profile_management_clientprofile_changelist')

    # 处理表单提交
    if request.method == 'POST':
        form = ClientProfileForm(request.POST)
        if form.is_valid():
            # 调用API更新数据
            update_api_url = f"http://x.xxx.xxx.xx/api2/update_profile/{object_id}"
            try:
                response = requests.put(update_api_url, json=form.cleaned_data)
                response.raise_for_status()
                messages.success(request, "用户信息更新成功")
                return redirect('admin:profile_management_clientprofile_changelist')
            except requests.exceptions.RequestException as e:
                messages.error(request, f"更新用户信息失败: {str(e)}")
    else:
        # 用API数据填充表单初始值
        form = ClientProfileForm(initial=profile_data)

    extra_context = extra_context or {}
    extra_context['form'] = form
    extra_context['original'] = ClientProfile(**profile_data)  # 模拟原始对象供模板使用
    return render(request, 'admin/change_form.html', extra_context)

注意事项

  1. API数据格式适配:确保API返回的字段名与模型字段名一致,若不一致需在转换时做映射。
  2. 异常处理:添加了基础的API请求异常处理,可根据需求扩展日志记录或更友好的错误提示。
  3. 性能优化:若API数据量较大,可实现分页逻辑,在changelist_view中处理page参数并传递给API。
  4. 权限控制:保留Django Admin原有的权限体系,确保只有授权用户能访问和编辑数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 09:27:04