1

I am using the Django rest framework to create an eCommerce API. I made API and tried to fetch data using the HTTP package for flutter and dart. I fetched the shops/restaurants but now I want to fetch shop-wise product. I mean when I tap a shop/restaurant the product will be shown by the shop. Here is my models.py:

class Shop(models.Model):
    created_at = models.DateField(default=date.today)
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    shop_name = models.CharField(max_length=255)
    shop_logo = models.ImageField(upload_to="images/")

class Product(models.Model):
    created_at = models.DateField(default=date.today)
    shop = models.ForeignKey(Shop, on_delete=models.CASCADE)
    product_name = models.CharField(max_length=255)
    product_img = models.ImageField(upload_to="images/")
    regular_price = models.DecimalField(decimal_places=2, max_digits=10, default=0.00)
    selling_price = models.DecimalField(decimal_places=2, max_digits=10, default=0.00)
    is_active = models.BooleanField(default=False)

    class Meta:
        ordering = ["-id"]

    def __str__(self):
        return self.product_name

Here is my serializer for restaurant/shop and product:

class ProductSerializer(serializers.ModelSerializer):
    class Meta:
        model = Product
        fields = ("shop", "product_name", "product_img", "regular_price", "selling_price")
        depth = 1


class GetRestaurantSerializer(serializers.ModelSerializer):
    class Meta:
        model = Shop
        fields = ("id", "shop_name", "shop_logo")
        depth = 1

Here is my views:

class ShopView(APIView):
    def get(self, request):
        shop = Shop.objects.all()
        shop_serializer = GetRestaurantSerializer(shop, many=True)
        return Response(shop_serializer.data, status=status.HTTP_200_OK)


class ShopWiseProducts(APIView):
    def get(self, request, shop_id):
        shopId = Shop.objects.get(id=shop_id)
        product = Product.objects.filter(shop=shopId.id)
        product_serializer = ProductSerializer(product, many=True)
        return Response(product_serializer.data, status=status.HTTP_200_OK)

Here is my urls

path("products/<int:shop_id>/", ShopWiseProducts.as_view()),
    path("shops/", ShopView.as_view()),

Flutter Part In my flutter part, I created 2 controllers for fetching restaurants and products. Here is it:

class RestaurantProductController with ChangeNotifier {
  List<RestaurantProduct> _products = [];

  Future<bool> getProducts(int id) async {
    var url = Uri.parse("http://10.0.2.2:8000/user-api/products/$id");
    try {
      http.Response response = await http.get(url);
      var data = json.decode(response.body) as List;
      List<RestaurantProduct> temp = [];
      data.forEach((element) {
        RestaurantProduct rest_product = RestaurantProduct.fromJson(element);
        temp.add(rest_product);
      });
      _products = temp;
      notifyListeners();
      return true;
    } catch (e) {
      print(e);
      return false;
    }
  }

  List<RestaurantProduct> get products {
    return [..._products];
  }

  RestaurantProduct productDetails(id) {
    return _products.firstWhere((element) => element == id);
  }
}

ShopController

class RestaurantController with ChangeNotifier {
  List<RestaurantModel> _rests = [];

  Future<bool> getRestaurants() async {
    var url = Uri.parse("http://10.0.2.2:8000/user-api/shops");
    try {
      http.Response response = await http.get(url);
      var data = json.decode(response.body) as List;
      List<RestaurantModel> temp = [];
      data.forEach((element) {
        RestaurantModel restaurantModel = RestaurantModel.fromJson(element);
        temp.add(restaurantModel);
      });
      _rests = temp;
      notifyListeners();
      return true;
    } catch (e) {
      print("e getRestaurants");
      return false;
    }
  }

  List<RestaurantModel> get restaurants {
    return [..._rests];
  }

  RestaurantModel restaurantDetails(id) {
    return _rests.firstWhere((element) => element.id == id);
  }
}

Here is my models RestaurantModel

class RestaurantModel {
  late int id;
  late String shopName;
  late String shopLogo;

  RestaurantModel({
    required this.id,
    required this.shopName,
    required this.shopLogo,
  });
  // late final int id;
  // late final String shopName;
  // late final String shopLogo;

  RestaurantModel.fromJson(Map<String, dynamic> json) {
    id = json['id'];
    shopName = json['shop_name'];
    shopLogo = json['shop_logo'];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> _data = new Map<String, dynamic>();
    _data['id'] = this.id;
    _data['shop_name'] = this.shopName;
    _data['shop_logo'] = this.shopLogo;
    return _data;
  }
}

ProductModel

class RestaurantProduct {
  RestaurantProduct({
    required this.shop,
    required this.productName,
    required this.productImg,
    required this.regularPrice,
    required this.sellingPrice,
  });
  late final Shop shop;
  late final String productName;
  late final String productImg;
  late final String regularPrice;
  late final String sellingPrice;

  RestaurantProduct.fromJson(Map<String, dynamic> json) {
    shop = Shop.fromJson(json['shop']);
    productName = json['product_name'];
    productImg = json['product_img'];
    regularPrice = json['regular_price'];
    sellingPrice = json['selling_price'];
  }

  Map<String, dynamic> toJson() {
    final _data = <String, dynamic>{};
    _data['shop'] = shop.toJson();
    _data['product_name'] = productName;
    _data['product_img'] = productImg;
    _data['regular_price'] = regularPrice;
    _data['selling_price'] = sellingPrice;
    return _data;
  }
}
class Shop {
  Shop({
    required this.id,
    required this.createdAt,
    required this.shopName,
    required this.shopLogo,
    required this.user,
  });
  late final int id;
  late final String createdAt;
  late final String shopName;
  late final String shopLogo;
  late final int user;

  Shop.fromJson(Map<String, dynamic> json) {
    id = json['id'];
    createdAt = json['created_at'];
    shopName = json['shop_name'];
    shopLogo = json['shop_logo'];
    user = json['user'];
  }

  Map<String, dynamic> toJson() {
    final _data = <String, dynamic>{};
    _data['id'] = id;
    _data['created_at'] = createdAt;
    _data['shop_name'] = shopName;
    _data['shop_logo'] = shopLogo;
    _data['user'] = user;
    return _data;
  }
}

I successfully Fetched all the shops but now I want to fetch all the products which are under shops. I mean shop wise product. I tried this

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:restaurant_delivery/controllers/restaurant_controller.dart';
import 'package:restaurant_delivery/controllers/restaurant_wise_product_controller.dart';
import 'package:restaurant_delivery/widgets/product_card.dart';

class RestaurantWiseProduct extends StatefulWidget {
  static const routeName = "/restaurant-wise-products";
  const RestaurantWiseProduct({Key? key}) : super(key: key);

  @override
  State<RestaurantWiseProduct> createState() => _RestaurantWiseProductState();
}

class _RestaurantWiseProductState extends State<RestaurantWiseProduct> {
  bool _init = true;
  bool _isLoading = false;

  @override
  void didChangeDependencies() async {
    if (_init) {
      // Provider.of<CartState>(context).getCartDatas();
      // Provider.of<CartState>(context).getoldOrders();
      _isLoading = await Provider.of<RestaurantProductController>(context)
          .getProducts(id);
      setState(() {});
    }
    _init = false;
    super.didChangeDependencies();
  }

  @override
  Widget build(BuildContext context) {
    final id = ModalRoute.of(context)!.settings.arguments;
    final shop_details =
        Provider.of<RestaurantController>(context).restaurantDetails(id);
    final product = Provider.of<RestaurantProductController>(context).products;

    return Scaffold(
      appBar: AppBar(
          //elevation: 10.0,
          ),
      body: ListView(
        children: [
          Container(
              padding: const EdgeInsets.all(8.0),
              child: Text(
                "${shop_details.shopName}",
                style: TextStyle(
                  fontSize: 15,
                  letterSpacing: 2.3,
                  fontWeight: FontWeight.bold,
                ),
              )),
          Container(
              height: 500,
              child: GridView.count(
                crossAxisCount: 2,
                scrollDirection: Axis.vertical,
                children: List.generate(product.length, (i) {
                  return ProductCard(
                      shop: product[i].shop,
                      productName: product[i].productName,
                      productImg: product[i].productImg,
                      regularPrice: product[i].regularPrice,
                      sellingPrice: product[i].sellingPrice);
                }),
              )),
        ],
      ),
    );
  }
}

But I am getting an error in this line:-

_isLoading = await Provider.of<RestaurantProductController>(context)
          .getProducts(id);

This is the log:

 Error: The getter 'id' isn't defined for the class '_RestaurantWiseProductState'.
    package:restaurant_delivery/screens/shop_wise_products.dart:25
    - '_RestaurantWiseProductState' is from 'package:restaurant_delivery/screens/shop_wise_products.dart' ('lib/screens/shop_wise_products.dart').
    package:restaurant_delivery/screens/shop_wise_products.dart:1
    Try correcting the name to the name of an existing getter, or defining a getter or field named 'id'.
              .getProducts(id);

So, How can I show shop wise product? Is there any way to show like this?

G H Prakash
  • 1,720
  • 10
  • 30
Sakib ovi
  • 537
  • 3
  • 19

1 Answers1

1

You can simply use order_by

shop_instance = Shop.objects.get(id=shop_id)
product = Product.objects.filter(shop=shop_instance).order_by('id', 'shop_instance')
Polymath
  • 328
  • 1
  • 9
  • I want to show the data in my flutter app. How can i show that. I can do that using django but in flutter i failed to do that – Sakib ovi Jan 26 '22 at 08:01