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?