1

I am trying to build freelancing type app. I am using flutter and for my backend data i created an api using django rest framework. Here is the models.py:

class Package(models.Model):
    
    management_duration_choices = (
        ("1", "1"),
        ("2", "2"),
        ("3", "3"),
        ("4", "4"),
        ("5", "5"),
        ("6", "6"),
        ("7", "7"),
        ("8", "8"),
        ("9", "9"),
        ("10", "10"),
        ("11", "11"),
        ("12", "12"),
        ("13", "13"),
        ("14", "14"),
        ("15", "15")
    )
    
    title = models.CharField(max_length=120)
    delivery_time = models.ForeignKey(
        DeliveryTime, on_delete=models.CASCADE, null=True)
    package_desc = models.TextField(null=True)
    revision_basic = models.ForeignKey(Revision, on_delete=models.SET_NULL, null=True, blank=True, related_name="revision_basic")
    revision_standard = models.ForeignKey(Revision, on_delete=models.SET_NULL, null=True, blank=True, related_name="revision_standard")
    revision_premium = models.ForeignKey(Revision, on_delete=models.SET_NULL, null=True, blank=True, related_name="revision_premium")
    num_of_pages_for_basic = models.ForeignKey(NumberOfPage, on_delete=models.SET_NULL, null=True, related_name="num_of_pages_for_basic", blank=True)
    num_of_pages_for_standard = models.ForeignKey(NumberOfPage, on_delete=models.SET_NULL, null=True, related_name="num_of_pages_for_standard", blank=True)
    num_of_pages_for_premium = models.ForeignKey(NumberOfPage, on_delete=models.SET_NULL, null=True, related_name="num_of_pages_for_premium", blank=True)
    is_responsive_basic = models.BooleanField(default=False, null=True, blank=True)
    is_responsive_standard = models.BooleanField(default=False, null=True, blank=True)
    is_responsive_premium = models.BooleanField(default=False, null=True, blank=True)
    setup_payment = models.BooleanField(default=False, null=True, blank=True)
    will_deploy = models.BooleanField(default=False, null=True, blank=True)
    is_compitable = models.BooleanField(default=False, null=True, blank=True)
    supported_formats = models.ManyToManyField(FileFormats, blank=True)
    # For Logo Design
    provide_vector = models.BooleanField(default=False, null=True, blank=True)
    is_3dmockup = models.BooleanField(default=False, null=True, blank=True)
    is_high_res_for_basic = models.BooleanField(default=False, null=True, blank=True)
    is_high_res_for_standard = models.BooleanField(default=False, null=True, blank=True)
    is_high_res_for_premium = models.BooleanField(default=False, null=True, blank=True)
    will_sourcefile_for_basic = models.BooleanField(default=False, null=True, blank=True)
    will_sourcefile_for_standard = models.BooleanField(default=False, null=True, blank=True)
    will_sourcefile_for_premium = models.BooleanField(default=False, null=True, blank=True)
    # For Digital Marketing
    is_campaign_optimization = models.BooleanField(default=False, null=True, blank=True)
    management_duration = models.CharField(max_length=120, choices=management_duration_choices, null=True, blank=True)
    
    # For Video editor
    
    video_length = models.PositiveBigIntegerField(default=0, null=True, blank=True)
    will_embedded_sub = models.BooleanField(default=False, null=True, blank=True)
    is_transactioable = models.BooleanField(default=False, null=True, blank=True)
    is_translated = models.BooleanField(default=False, null=True, blank=True)
    will_srt_logo = models.BooleanField(default=False, null=True, blank=True)
    will_add_logo = models.BooleanField(default=False, null=True, blank=True)
    
    # For Data Entry
    
    provide_pdf = models.BooleanField(null=True, default=False, blank=True)
    max_data = models.CharField(max_length=450, null=True, blank=True)
    provide_excel = models.BooleanField(default=False, null=True, blank=True)
    
    def __str__(self):
        return str(self.id)

class ExtraImage(models.Model):
    image = models.ImageField(upload_to="images/", null=True)

    def __str__(self):
        return str(self.image)
        
    def save(self, *args, **kwargs):
        super(ExtraImage, self).save(*args, **kwargs)

        if not self.image:
            return

        imag = Image.open(self.image.path)
        if imag.width > 800 or imag.height> 600:
            output_size = (800, 600)
            imag.thumbnail(output_size)
            imag.save(self.image.path)


class Offer(models.Model):
    Offer_STATUS = (
        ("ACTIVE", "ACTIVE"),
        ("PENDING APPROVAL", "PENDING APPROVAL"),
        ("REQUIRED MODIFICATION", "REQUIRED MODIFICATION"),
        ("DENIED", "DENIED"),
        ("PAUSED", "PAUSED"),
    )

    slug = models.SlugField(unique=True, null=True)
    user = models.ForeignKey(User, null=True, on_delete=models.CASCADE)
    offer_title = models.CharField(max_length=240)
    seo_title = models.CharField(max_length=60, null=True)
    image = models.ImageField(upload_to='images/')
    extra_images = models.ManyToManyField(ExtraImage, blank=True)
    offer_video = models.FileField(upload_to="images/", blank=True, null=True)
    document = models.FileField(upload_to="files/", null=True, blank=True)
    service = models.ForeignKey(Services, on_delete=models.CASCADE, null=True)
    category = models.ForeignKey(Category, on_delete=models.CASCADE, null=True, related_name="offers")
    sub_category = models.ForeignKey(Subcategory, on_delete=models.CASCADE, null=True, blank=True)
    child_subcategory = models.ForeignKey(ChildSubcategory, on_delete=models.CASCADE, null=True, blank=True)
    packages = models.ManyToManyField(Package, through='OfferManager')
    description = models.TextField()
    # offer_rating = models.FloatField(default=0)
    is_popular = models.BooleanField(default=False, null=True)
    pop_web = models.BooleanField(default=False, null=True, blank=True)
    is_pro = models.BooleanField(default=False, null=True)
    click = models.PositiveIntegerField(null=True, blank=True, default=0)
    impressions = models.PositiveIntegerField(default=0, null=True, blank=True)
    order_count = models.PositiveIntegerField(default=0, null=True, blank=True)
    cancellation = models.PositiveIntegerField(default=0, null=True, blank=True)
    offer_status = models.CharField(max_length=200, null=True, choices=Offer_STATUS, default="PENDING APPROVAL")
    is_premium = models.BooleanField(default=False)
    is_bronze = models.BooleanField(default=False, null=True)
    bronze_created = models.DateTimeField(null=True, blank=True)
    is_silver = models.BooleanField(default=False, null=True)
    silver_created = models.DateTimeField(null=True, blank=True)
    is_gold = models.BooleanField(default=False, null=True)
    gold_created = models.DateTimeField(null=True, blank=True)
    is_pending = models.BooleanField(null=True, blank=True, default=True)
    created_at = models.DateTimeField(auto_now_add=True, null=True)

    # From Admin Side
    has_checked = models.BooleanField(default=False)
    already_clicked = models.BooleanField(default=False)

    # Pointing Sytem DB
    points = models.PositiveIntegerField(null=True, default=0)

    def __str__(self):
        return str(self.id)
        
    def save(self, *args, **kwargs):
        super(Offer, self).save(*args, **kwargs)

        if not self.image:
            return

        imag = Image.open(self.image.path)
        if imag.width > 800 or imag.height> 600:
            output_size = (800, 600)
            imag.thumbnail(output_size)
            imag.save(self.image.path)
            



class OfferFavoriteModel(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    offer = models.ForeignKey(Offer, on_delete=models.CASCADE)
    is_Favorite = models.BooleanField(default=False)




class OfferManager(models.Model):
    offer = models.ForeignKey(Offer, on_delete=models.CASCADE, null=True)
    package = models.ForeignKey(Package, on_delete=models.CASCADE, null=True)
    price = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)

    def __str__(self):
        return str(self.id)

Here is my serializers.py:

class OfferSeriaLizer(serializers.ModelSerializer):
    class Meta:
        model = Offer
        fields = ('id', 'offer_title', 'image', 'user', 'click', 'category', 'packages',)
        depth = 1

Here is my views.py for fetching offers:

class OfferApiView(APIView):
    def get(self, request):

        offers = Offer.objects.filter(offer_status="ACTIVE").order_by("-click")

        serializer = OfferSeriaLizer(offers, many=True)


        return Response(serializer.data)

You can see in the models.py there is a model named offermanager. I successfully showing the offers but in the offer details page i only succeed to fetch the title and package description but i want to fetch the offermanager data also. Like If i open an offer it will also show the offermanager according the offer id.

Here is my Flutter app part. Offer Controller :

import 'dart:convert';
import 'package:flutter/cupertino.dart';

import 'package:http/http.dart' as http;
import 'package:marketage_v2/models/offer_model.dart';

class OfferController with ChangeNotifier {
  List<OfferModel> _offers = [];

  Future<bool> getOffers() async {
    var url = Uri.parse("https://marketage.io/api/offers/");

    try {
      http.Response response = await http.get(url);
      var data = json.decode(response.body) as List;
      List<OfferModel> temp = [];
      for (var element in data) {
        OfferModel offermodel = OfferModel.fromJson(element);
        temp.add(offermodel);
      }
      _offers = temp;
      notifyListeners();
      return true;
    } catch (e) {
      return false;
    }
  }

  List<OfferModel> get offers {
    return [..._offers];
  }

  OfferModel offerDetails(id) {
    return _offers.firstWhere((element) => element.id == id);
  }
}

Offer Model:

class OfferModel {
  OfferModel({
    required this.id,
    required this.offerTitle,
    required this.image,
    required this.user,
    required this.click,
    required this.category,
    required this.packages,
  });
  late final int id;
  late final String offerTitle;
  late final String image;
  late final User user;
  late final int click;
  late final Category category;
  late final List<Packages> packages;

  OfferModel.fromJson(Map<String, dynamic> json) {
    id = json['id'];
    offerTitle = json['offer_title'];
    image = json['image'];
    user = User.fromJson(json['user']);
    click = json['click'];
    category = Category.fromJson(json['category']);
    packages =
        List.from(json['packages']).map((e) => Packages.fromJson(e)).toList();
  }

  Map<String, dynamic> toJson() {
    final _data = <String, dynamic>{};
    _data['id'] = id;
    _data['offer_title'] = offerTitle;
    _data['image'] = image;
    _data['user'] = user.toJson();
    _data['click'] = click;
    _data['category'] = category.toJson();
    _data['packages'] = packages.map((e) => e.toJson()).toList();

    return _data;
  }
}

class User {
  User({
    required this.id,
    required this.password,
    required this.lastLogin,
    required this.isSuperuser,
    required this.username,
    required this.firstName,
    required this.lastName,
    required this.email,
    required this.isStaff,
    required this.isActive,
    required this.dateJoined,
    required this.groups,
    required this.userPermissions,
  });
  late final int id;
  late final String password;
  late final String lastLogin;
  late final bool isSuperuser;
  late final String username;
  late final String firstName;
  late final String lastName;
  late final String email;
  late final bool isStaff;
  late final bool isActive;
  late final String dateJoined;
  late final List<dynamic> groups;
  late final List<dynamic> userPermissions;

  User.fromJson(Map<String, dynamic> json) {
    id = json['id'];
    password = json['password'];
    lastLogin = json['last_login'];
    isSuperuser = json['is_superuser'];
    username = json['username'];
    firstName = json['first_name'];
    lastName = json['last_name'];
    email = json['email'];
    isStaff = json['is_staff'];
    isActive = json['is_active'];
    dateJoined = json['date_joined'];
    groups = List.castFrom<dynamic, dynamic>(json['groups']);
    userPermissions = List.castFrom<dynamic, dynamic>(json['user_permissions']);
  }

  Map<String, dynamic> toJson() {
    final _data = <String, dynamic>{};
    _data['id'] = id;
    _data['password'] = password;
    _data['last_login'] = lastLogin;
    _data['is_superuser'] = isSuperuser;
    _data['username'] = username;
    _data['first_name'] = firstName;
    _data['last_name'] = lastName;
    _data['email'] = email;
    _data['is_staff'] = isStaff;
    _data['is_active'] = isActive;
    _data['date_joined'] = dateJoined;
    _data['groups'] = groups;
    _data['user_permissions'] = userPermissions;
    return _data;
  }
}

class Category {
  Category({
    required this.id,
    required this.slug,
    required this.title,
    required this.icon,
    required this.subcategory,
  });
  late final int id;
  late final String slug;
  late final String title;
  late final String icon;
  late final List<int> subcategory;

  Category.fromJson(Map<String, dynamic> json) {
    id = json['id'];
    slug = json['slug'];
    title = json['title'];
    icon = json['icon'];
    subcategory = List.castFrom<dynamic, int>(json['subcategory']);
  }

  Map<String, dynamic> toJson() {
    final _data = <String, dynamic>{};
    _data['id'] = id;
    _data['slug'] = slug;
    _data['title'] = title;
    _data['icon'] = icon;
    _data['subcategory'] = subcategory;
    return _data;
  }
}

class Packages {
  Packages({
    required this.id,
    required this.title,
    required this.packageDesc,
    required this.isResponsiveBasic,
    required this.isResponsiveStandard,
    required this.isResponsivePremium,
    required this.setupPayment,
    required this.willDeploy,
    required this.isCompitable,
    required this.provideVector,
    required this.is_3dmockup,
    required this.isHighResForBasic,
    required this.isHighResForStandard,
    required this.isHighResForPremium,
    required this.willSourcefileForBasic,
    required this.willSourcefileForStandard,
    required this.willSourcefileForPremium,
    required this.isCampaignOptimization,
    this.managementDuration,
    required this.videoLength,
    required this.willEmbeddedSub,
    required this.isTransactioable,
    required this.isTranslated,
    required this.willSrtLogo,
    required this.willAddLogo,
    required this.providePdf,
    this.maxData,
    required this.provideExcel,
    required this.deliveryTime,
    this.revisionBasic,
    this.revisionStandard,
    this.revisionPremium,
    this.numOfPagesForBasic,
    this.numOfPagesForStandard,
    this.numOfPagesForPremium,
    required this.supportedFormats,
  });
  late final int id;
  late final String title;
  late final String packageDesc;
  late final bool isResponsiveBasic;
  late final bool isResponsiveStandard;
  late final bool isResponsivePremium;
  late final bool setupPayment;
  late final bool willDeploy;
  late final bool isCompitable;
  late final bool provideVector;
  late final bool is_3dmockup;
  late final bool isHighResForBasic;
  late final bool isHighResForStandard;
  late final bool isHighResForPremium;
  late final bool willSourcefileForBasic;
  late final bool willSourcefileForStandard;
  late final bool willSourcefileForPremium;
  late final bool isCampaignOptimization;
  late final Null managementDuration;
  late final int videoLength;
  late final bool willEmbeddedSub;
  late final bool isTransactioable;
  late final bool isTranslated;
  late final bool willSrtLogo;
  late final bool willAddLogo;
  late final bool providePdf;
  late final Null maxData;
  late final bool provideExcel;
  late final int deliveryTime;
  late final int? revisionBasic;
  late final int? revisionStandard;
  late final int? revisionPremium;
  late final Null numOfPagesForBasic;
  late final Null numOfPagesForStandard;
  late final Null numOfPagesForPremium;
  late final List<dynamic> supportedFormats;

  Packages.fromJson(Map<String, dynamic> json) {
    id = json['id'];
    title = json['title'];
    packageDesc = json['package_desc'];
    isResponsiveBasic = json['is_responsive_basic'];
    isResponsiveStandard = json['is_responsive_standard'];
    isResponsivePremium = json['is_responsive_premium'];
    setupPayment = json['setup_payment'];
    willDeploy = json['will_deploy'];
    isCompitable = json['is_compitable'];
    provideVector = json['provide_vector'];
    is_3dmockup = json['is_3dmockup'];
    isHighResForBasic = json['is_high_res_for_basic'];
    isHighResForStandard = json['is_high_res_for_standard'];
    isHighResForPremium = json['is_high_res_for_premium'];
    willSourcefileForBasic = json['will_sourcefile_for_basic'];
    willSourcefileForStandard = json['will_sourcefile_for_standard'];
    willSourcefileForPremium = json['will_sourcefile_for_premium'];
    isCampaignOptimization = json['is_campaign_optimization'];
    managementDuration = null;
    videoLength = json['video_length'];
    willEmbeddedSub = json['will_embedded_sub'];
    isTransactioable = json['is_transactioable'];
    isTranslated = json['is_translated'];
    willSrtLogo = json['will_srt_logo'];
    willAddLogo = json['will_add_logo'];
    providePdf = json['provide_pdf'];
    maxData = null;
    provideExcel = json['provide_excel'];
    deliveryTime = json['delivery_time'];
    revisionBasic = null;
    revisionStandard = null;
    revisionPremium = null;
    numOfPagesForBasic = null;
    numOfPagesForStandard = null;
    numOfPagesForPremium = null;
    supportedFormats =
        List.castFrom<dynamic, dynamic>(json['supported_formats']);
  }

  Map<String, dynamic> toJson() {
    final _data = <String, dynamic>{};
    _data['id'] = id;
    _data['title'] = title;
    _data['package_desc'] = packageDesc;
    _data['is_responsive_basic'] = isResponsiveBasic;
    _data['is_responsive_standard'] = isResponsiveStandard;
    _data['is_responsive_premium'] = isResponsivePremium;
    _data['setup_payment'] = setupPayment;
    _data['will_deploy'] = willDeploy;
    _data['is_compitable'] = isCompitable;
    _data['provide_vector'] = provideVector;
    _data['is_3dmockup'] = is_3dmockup;
    _data['is_high_res_for_basic'] = isHighResForBasic;
    _data['is_high_res_for_standard'] = isHighResForStandard;
    _data['is_high_res_for_premium'] = isHighResForPremium;
    _data['will_sourcefile_for_basic'] = willSourcefileForBasic;
    _data['will_sourcefile_for_standard'] = willSourcefileForStandard;
    _data['will_sourcefile_for_premium'] = willSourcefileForPremium;
    _data['is_campaign_optimization'] = isCampaignOptimization;
    _data['management_duration'] = managementDuration;
    _data['video_length'] = videoLength;
    _data['will_embedded_sub'] = willEmbeddedSub;
    _data['is_transactioable'] = isTransactioable;
    _data['is_translated'] = isTranslated;
    _data['will_srt_logo'] = willSrtLogo;
    _data['will_add_logo'] = willAddLogo;
    _data['provide_pdf'] = providePdf;
    _data['max_data'] = maxData;
    _data['provide_excel'] = provideExcel;
    _data['delivery_time'] = deliveryTime;
    _data['revision_basic'] = revisionBasic;
    _data['revision_standard'] = revisionStandard;
    _data['revision_premium'] = revisionPremium;
    _data['num_of_pages_for_basic'] = numOfPagesForBasic;
    _data['num_of_pages_for_standard'] = numOfPagesForStandard;
    _data['num_of_pages_for_premium'] = numOfPagesForPremium;
    _data['supported_formats'] = supportedFormats;
    return _data;
  }
}

In django i was able to fetch offermanager models data just like this : for m in offers.offermanager_set.all I used this code in the templates and i was successfull. But how can i fetch the data just like django in flutter

Please help

Sakib ovi
  • 537
  • 3
  • 19

0 Answers0