如何在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)
注意事项
- API数据格式适配:确保API返回的字段名与模型字段名一致,若不一致需在转换时做映射。
- 异常处理:添加了基础的API请求异常处理,可根据需求扩展日志记录或更友好的错误提示。
- 性能优化:若API数据量较大,可实现分页逻辑,在
changelist_view中处理page参数并传递给API。 - 权限控制:保留Django Admin原有的权限体系,确保只有授权用户能访问和编辑数据。
内容的提问来源于stack exchange,提问作者Nihal Shantha
相关产品推荐
相关产品推荐

