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

如何将Angular GET请求响应数据拆分加载到不同列表及变量中?

解决Angular对接Django REST API的数据拆分与渲染问题

问题核心

你的问题出在模型定义错误和服务返回类型不匹配,导致组件无法正确解析API返回的分页数据结构。


1. 修正ProductList模型定义

Django REST Framework的分页接口返回单个对象,包含分页元数据和data产品数组。你当前的data类型定义不符合TS语法,需单独定义Product接口并修正结构:

// products.models.ts
export interface Product {
  id: number;
  name: string;
  picture: string;
  price: number;
  discount: number | null;
  saved_amount: number;
  discount_percent: number | null;
  slug: string;
  is_available: boolean;
  ratings_average: number;
  ratings_count: number;
  date: string;
  uuid: string;
  extra_data: any;
  category: Category;
}

export interface Category {
  // 根据API返回补充Category字段,示例:
  id: number;
  name: string;
}

export interface ProductList {
  total_pages: number;
  current_page: number;
  has_next: boolean;
  has_prev: boolean;
  page_items_count: number;
  items_per_page: number;
  data: Product[]; // 改为Product对象数组
}

export interface ProductDetail {} // 后续补充详情结构

2. 修正ProductsService的返回类型

API返回的是单个分页对象而非数组,服务中所有返回ProductList[]的方法需改为ProductList:

// products.service.ts
import { Injectable } from '@angular/core';
import { Observable, catchError, of } from 'rxjs';
import { ProductList, ProductDetail } from '../../models/products.models';
import { HttpClient, HttpParams, HttpHeaders } from '@angular/common/http';

@Injectable({
  providedIn: 'root'
})
export class ProductsService {
  baseUrl = "http://127.0.0.1:8000/api";
  headers = new HttpHeaders({
    'Content-Type': 'application/json',
  });

  constructor(private http: HttpClient) { }

  private handleError(error: Error, errorValue: any) {
    return of(errorValue);
  }

  getProductList(): Observable<ProductList> {
    const productUrl = `${this.baseUrl}/products/`
    return this.http.get<ProductList>(productUrl, { headers: this.headers }).pipe(
      catchError((error) => this.handleError(error, { data: [], total_pages: 0 }))
    );
  }

  getUnavailableProductList(): Observable<ProductList> {
    const productUrl = `${this.baseUrl}/products/unvailable/`
    return this.http.get<ProductList>(productUrl, { headers: this.headers }).pipe(
      catchError((error) => this.handleError(error, { data: [], total_pages: 0 }))
    );
  }

  searchProducts(query: string|null): Observable<ProductList> {
    const params = query ? new HttpParams().set('q', query): {}
    const searchUrl = `${this.baseUrl}/products/search/`
    return this.http.get<ProductList>(searchUrl, { params: params, headers: this.headers }).pipe(
      catchError((error) => this.handleError(error, { data: [], total_pages: 0 }))
    );
  }

  getProductDetail(product_id: number): Observable<ProductDetail|undefined> {
    const productDetailUrl = `${this.baseUrl}/products/${product_id}/`
    return this.http.get<ProductDetail>(productDetailUrl, { headers: this.headers }).pipe(
      catchError((error) => this.handleError(error, undefined))
    );
  }
}

3. 在HomeComponent中正确拆分数据

组件中改为接收单个ProductList对象,提取产品列表和分页参数:

// homepage.component.ts
import { Component, OnInit } from '@angular/core';
import { ProductList, Product } from '../../models/products.models';
import { ProductsService } from 'src/app/services/products/products.service';

@Component({
  selector: 'app-homepage',
  templateUrl: './homepage.component.html',
  styleUrls: ['./homepage.component.css']
})
export class HomepageComponent implements OnInit {
  public products: Product[] = [];
  public total_pages: number = 0;
  public current_page: number = 0;
  public has_next: boolean = false;
  public has_prev: boolean = false;
  public page_items_count: number = 0;
  public items_per_page: number = 0;

  constructor (private productService: ProductsService) {}

  ngOnInit() {
    this.productService.getProductList().subscribe((res) => {
      this.products = res.data;
      this.total_pages = res.total_pages;
      this.current_page = res.current_page;
      this.has_next = res.has_next;
      this.has_prev = res.has_prev;
      this.page_items_count = res.page_items_count;
      this.items_per_page = res.items_per_page;
    });
  }
}

4. HTML模板中渲染数据

直接使用products数组遍历产品,分页参数直接绑定变量:

<!-- homepage.component.html -->
<!-- 产品列表 -->
<div *ngFor="let product of products" class="product-card">
  <h3>{{ product.name }}</h3>
  <img [src]="product.picture" alt="{{ product.name }}">
  <p>原价: {{ product.price }} 元</p>
  <p *ngIf="product.discount">折扣价: {{ product.price - product.saved_amount }} 元</p>
  <!-- 其他产品字段 -->
</div>

<!-- 分页控件 -->
<div class="pagination-bar">
  <button [disabled]="!has_prev">上一页</button>
  <span>第 {{ current_page }} 页 / 共 {{ total_pages }} 页</span>
  <button [disabled]="!has_next">下一页</button>
  <span>当前显示 {{ page_items_count }} 条 / 每页 {{ items_per_page }} 条</span>
</div>

内容的提问来源于stack exchange,提问作者Stefan-ci

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 18:43:13