serve and provide url for media files stored in ftp server in production using django-storages

I am trying to serve media files in production using django-storages and a ftp server I am using a shared cpannel for ftp and trying to test it before I upload the code to production, it uploads the files in the server fine but doesn’t provide the download url. I want to access the url to download the uploaded media files in cpannel.

Here’s My Code

Settings.py

import os
from pathlib import Path
from dotenv import load_dotenv

from django.contrib.messages import constants as messages
from django.urls import reverse, reverse_lazy
from django.conf import global_settings

load_dotenv()


# project base dir
BASE_DIR = Path(__file__).resolve().parent.parent

# base url for link checker
SITE_DOMAIN = "127.0.0.1:8000"

# secretkey
SECRET_KEY = os.getenv("SECRET_KEY")

# DEBUG = os.getenv("DEBUG")
DEBUG = False

# allowed hosts
ALLOWED_HOSTS = ["*"]

# Application definition
USER_APPS = [
    "apps.user",
    "apps.container",
]


THIRD_PARTY = [
    "widget_tweaks",
    "crispy_forms",
    "crispy_tailwind",
    "active_link",  # highlights active link
    "template_partials",  # django template partials
    "django_htmx",  # django htmx integration
    "django_filters",  # filteriing
    "mathfilters",  # doing maths in templates
    "import_export",  # import export
    "linkcheck",  # checks for broken link
    "storages",
]

THEME = [
    "theme",
]

INSTALLED_APPS = [
    "authtools",  # authtools
    "django.contrib.admin",
    "django.contrib.auth",
    "django.contrib.contenttypes",
    "django.contrib.sessions",
    "django.contrib.messages",
    "django.contrib.humanize",  # humanize
    "whitenoise.runserver_nostatic",  # whitenoise
    "django.contrib.staticfiles",
]

INSTALLED_APPS += THIRD_PARTY
INSTALLED_APPS += USER_APPS
INSTALLED_APPS += THEME
TAILWIND_APP_NAME = "theme"

X_FRAME_OPTIONS = "SAMEORIGIN"

MIDDLEWARE = [
    # "debug_toolbar.middleware.DebugToolbarMiddleware",  # debug toolbar
    # "django_browser_reload.middleware.BrowserReloadMiddleware",  # browser-reload middleware
    "django.middleware.security.SecurityMiddleware",
    "whitenoise.middleware.WhiteNoiseMiddleware",  # whitenoise
    "django_htmx.middleware.HtmxMiddleware",  # django htmx
    "django.contrib.sessions.middleware.SessionMiddleware",
    "django.middleware.common.CommonMiddleware",
    "django.middleware.csrf.CsrfViewMiddleware",
    "django.contrib.auth.middleware.AuthenticationMiddleware",
    "django.contrib.messages.middleware.MessageMiddleware",
    "django.middleware.clickjacking.XFrameOptionsMiddleware",
    # "global_login_required.GlobalLoginRequiredMiddleware",  ## global login required
]

ROOT_URLCONF = "core.urls"


TEMPLATES = [
    {
        "BACKEND": "django.template.backends.django.DjangoTemplates",
        "DIRS": [
            os.path.join(BASE_DIR, "core/templates"),
        ],
        "APP_DIRS": True,
        "OPTIONS": {
            "context_processors": [
                "django.template.context_processors.debug",
                "django.template.context_processors.request",
                "django.contrib.auth.context_processors.auth",
                "django.contrib.messages.context_processors.messages",
                "django.template.context_processors.request",  # django tables 2 context processors
                "apps.container.context_processors.current_container",  # <-- currently active container
                "apps.container.context_processors.user_groups_processor",  # <-- current users group
                "apps.container.context_processors.list_of_containers",  # <-- current users group
            ],
            "builtins": [
                "template_partials.templatetags.partials",
            ],
        },
    },
]

WSGI_APPLICATION = "core.wsgi.application"


# Database
DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.sqlite3",
        "NAME": BASE_DIR / "db.sqlite3",
    }
}


# Password validation
AUTH_PASSWORD_VALIDATORS = [
    {
        "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
    },
    {
        "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",
    },
    {
        "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",
    },
    {
        "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",
    },
]


# Internationalization
LANGUAGE_CODE = "en-us"
TIME_ZONE = "UTC"
USE_I18N = True
USE_TZ = True


# Static files (CSS, JavaScript, Images)
STATIC_URL = "static/"
STATIC_ROOT = os.path.join(BASE_DIR, "staticfiles")
STATICFILES_DIRS = [
    BASE_DIR / "static",
]

MEDIA_URL = "/media/"
MEDIA_ROOT = os.path.join(BASE_DIR, "media")

# for FTP storages
BASE_URL = "/files/"

STORAGES = {
    "staticfiles": {
        "BACKEND": "whitenoise.storage.CompressedManifestStaticFilesStorage",
    },
    "default": {
        "BACKEND": "storages.backends.ftp.FTPStorage",
    },
}


FTP_STORAGE_LOCATION = (
    "ftp://<user>:<password>@<server>:21"
)

# Default primary key field type
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
AUTH_USER_MODEL = "authtools.User"

# login and logout url
LOGIN_REDIRECT_URL = reverse_lazy("dashboard")
LOGIN_URL = reverse_lazy("login")
LOGOUT_REDIRECT_URL = reverse_lazy("login")

# crispy forms
CRISPY_ALLOWED_TEMPLATE_PACKS = "tailwind"
CRISPY_TEMPLATE_PACK = "tailwind"

# navigation active link
ACTIVE_LINK_CSS_CLASS = "block py-2 pl-3 pr-4 text-white bg-blue-700 rounded md:bg-transparent md:text-blue-700 md:p-0 md:dark:text-blue-500"

# message error css tags
MESSAGE_TAGS = {
    messages.SUCCESS: """   <div class="inline-flex items-center justify-center flex-shrink-0 w-8 h-8 text-green-500 bg-green-100 rounded-lg dark:bg-green-800 dark:text-green-200">
        <svg class="w-5 h-5" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 20 20">
            <path d="M10 .5a9.5 9.5 0 1 0 9.5 9.5A9.51 9.51 0 0 0 10 .5Zm3.707 8.207-4 4a1 1 0 0 1-1.414 0l-2-2a1 1 0 0 1 1.414-1.414L9 10.586l3.293-3.293a1 1 0 0 1 1.414 1.414Z"/>
        </svg>
        <span class="sr-only">Check icon</span>
    </div>
    
    """,
    messages.WARNING: """
        <div class="inline-flex items-center justify-center flex-shrink-0 w-8 h-8 text-orange-500 bg-orange-100 rounded-lg dark:bg-orange-700 dark:text-orange-200 ">
        <svg class="w-5 h-5" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 20 20">
            <path d="M10 .5a9.5 9.5 0 1 0 9.5 9.5A9.51 9.51 0 0 0 10 .5ZM10 15a1 1 0 1 1 0-2 1 1 0 0 1 0 2Zm1-4a1 1 0 0 1-2 0V6a1 1 0 0 1 2 0v5Z"/>
        </svg>
        <span class="sr-only">Warning icon</span>
    </div>""",
    messages.ERROR: """    <div class="inline-flex items-center justify-center flex-shrink-0 w-8 h-8 text-red-500 bg-red-100 rounded-lg dark:bg-red-800 dark:text-red-200">
        <svg class="w-5 h-5" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 20 20">
            <path d="M10 .5a9.5 9.5 0 1 0 9.5 9.5A9.51 9.51 0 0 0 10 .5Zm3.707 11.793a1 1 0 1 1-1.414 1.414L10 11.414l-2.293 2.293a1 1 0 0 1-1.414-1.414L8.586 10 6.293 7.707a1 1 0 0 1 1.414-1.414L10 8.586l2.293-2.293a1 1 0 0 1 1.414 1.414L11.414 10l2.293 2.293Z"/>
        </svg>
        <span class="sr-only">Error icon</span>
    </div>""",
}

Urls.py

"""
URL configuration for core project.

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/4.2/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  path('', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.urls import include, path
    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
"""

from django.conf import settings
from django.conf.urls.static import static
from django.urls import path, include
from django.contrib import admin

from apps.container.views import dashboard, redirect_to_dashboard

urlpatterns = [
    path("admin/", admin.site.urls),
    path("accounts/", include("django.contrib.auth.urls")),
    path("container/", include("apps.container.urls")),
    path("dashboard", dashboard, name="dashboard"),
    path("", redirect_to_dashboard, name="redirect-to-dashboard"),
    # path("admin/linkcheck/", include("linkcheck.urls")),
]

if settings.DEBUG:
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)


DEBUG = [
    path("__debug__/", include("debug_toolbar.urls")),
]

urlpatterns += DEBUG

Models.py

import json
from storages.backends.ftp import FTPStorage


from django.core.exceptions import ValidationError
from django.db import models


from .constants import PAYMENT_METHODS


fs = FTPStorage()


class Shipper(models.Model):
    shipper_name = models.CharField(
        verbose_name="Shipper Name",
        max_length=255,
    )
    shipper_address = models.TextField(verbose_name="Shipper Address")
    shipper_contact = models.CharField(
        verbose_name="Shipper Contact Number",
        max_length=255,
    )
    shipper_email = models.EmailField(
        verbose_name="Shipper Email", null=True, blank=True
    )

    class Meta:
        db_table = ""
        managed = True
        verbose_name = "Shipper"
        verbose_name_plural = "Shippers"

    def __str__(self):
        return self.shipper_name

    @property
    def get_all_road_containers(self):
        road_containers = RoadContainer.objects.filter(
            shipper=self, container_number__current=True
        )
        return road_containers

    @property
    def get_all_sea_containers(self):
        sea_containers = SeaContainer.objects.filter(
            shipper=self, container_number__current=True
        )
        return sea_containers

    @property
    def get_containers(self):
        from itertools import chain

        containers = chain(
            RoadContainer.objects.filter(shipper=self, container_number__current=True),
            SeaContainer.objects.filter(shipper=self, container_number__current=True),
        )
        return containers


class Bank(models.Model):
    name = models.CharField(max_length=100)
    address = models.CharField(max_length=100)

    def __str__(self):
        return self.name


class Category(models.Model):
    category_name = models.CharField(
        verbose_name="Category Name",
        max_length=10,
        unique=True,
    )

    class Meta:
        db_table = ""
        managed = True
        verbose_name = "Category"
        verbose_name_plural = "Categorys"

    def __str__(self):
        return self.category_name


class Owner(models.Model):
    owner_name = models.CharField(
        verbose_name="Owner",
        max_length=255,
        unique=True,
    )
    owner_primary_number = models.CharField(
        verbose_name="Primary Phone Number",
        max_length=10,
        unique=True,
    )
    owner_secondary_number = models.CharField(
        verbose_name="Secondary Phone Number",
        max_length=10,
        unique=True,
        blank=True,
        null=True,
    )
    owner_email = models.EmailField(
        verbose_name="Email",
        unique=True,
    )

    def __str__(self):
        return self.owner_name


class Company(models.Model):
    name = models.CharField(
        max_length=200,
        verbose_name="Company Name",
    )
    owner = models.ForeignKey(
        to=Owner,
        on_delete=models.CASCADE,
    )

    def __str__(self):
        return self.name

    def get_company_name(self):
        return self.name


class ContainerNumber(models.Model):
    name = models.CharField(
        verbose_name="Container Number", max_length=255, unique=True
    )
    current = models.BooleanField(verbose_name="Current")

    def clean(self):
        if self.current:
            existing_active_instance = ContainerNumber.objects.filter(
                current=True
            ).exclude(pk=self.pk)
            if existing_active_instance.exists():
                raise ValidationError(
                    "There can be only one active Container Number at a time."
                )

    def save(self, *args, **kwargs):
        self.full_clean()  # This will trigger the clean method before saving
        super().save(*args, **kwargs)

    def __str__(self):
        return self.name


class LCLimit(models.Model):
    bank = models.ForeignKey(Bank, on_delete=models.CASCADE)
    company = models.ForeignKey(Company, on_delete=models.CASCADE)
    limit_amount = models.DecimalField(max_digits=10, decimal_places=2)
    expiry_date = models.DateField()
    approval_percentage = models.IntegerField()

    def __str__(self):
        return self.bank.name

    def total_value_in_usd(self):
        sea_containers = SeaContainer.objects.filter(
            bank=self.bank,
            company=self.company,
            documents_cleared=False,
            container_number__current=True,
        )
        total_value = sum(
            container.calculate_value_in_usd() or 0 for container in sea_containers
        )
        return total_value


class MultiHisabFileField(models.Model):
    file = models.FileField(
        verbose_name="Multiple Hisab File",
        storage=fs,
    )

    def __str__(self):
        return str(self.file.name)


class PartyHisab(models.Model):
    party_name = models.CharField(verbose_name="Party Name", max_length=255, null=True)
    marka_name = models.CharField(
        verbose_name="Party Marka Detail", max_length=255, null=True
    )
    hisab_date = models.DateField(verbose_name="Hisab Date", max_length=255, null=True)
    hisab = models.ManyToManyField(to=MultiHisabFileField, verbose_name="Hisab Files")
    remarks = models.TextField(verbose_name="Remarks")

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

    def get_marka_name_words(self):
        if self.marka_name:
            try:
                marka_name_json = self.marka_name.replace("'", '"')
                marka_list = json.loads(marka_name_json)

                if not isinstance(marka_list, list):
                    marka_list = [marka_list]
                words = [word.strip() for word in marka_list]
                return words
            except json.JSONDecodeError:
                return []

        return []


class Payment(models.Model):
    payment_settled = models.BooleanField(default=False)
    expiry_date = models.DateField()

    def __str__(self):
        return f"Payment Settled:{self.payment_settled} - Expiry:{self.expiry_date}"


class RoadContainer(models.Model):
    container_number = models.ForeignKey(
        to=ContainerNumber,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
    )

    company = models.ForeignKey(
        to="Company",
        on_delete=models.SET_NULL,
        null=True,
    )

    number = models.CharField(
        verbose_name="Sea Container Number",
        max_length=10,
    )
    payment_method = models.CharField(
        max_length=6,
        choices=PAYMENT_METHODS,
        default="LC",
    )
    bill_of_lading = models.CharField(
        verbose_name="Bill of Lading", max_length=50, null=True, blank=True
    )
    bill_of_lading_date = models.DateField(
        verbose_name="Bill of Lading Date",
        null=True,
        blank=True,
    )

    cartoon_number = models.PositiveIntegerField(
        verbose_name="Loaded Cartoon Number",
    )
    refrence_number = models.CharField(
        verbose_name="LC / TT / DAP number",
        max_length=30,
        unique=True,
        null=True,
        blank=True,
    )
    refrence_date = models.DateField(
        verbose_name="LC / TT / DAP date",
        null=True,
        blank=True,
    )

    proforma_invoice_number = models.CharField(
        verbose_name="Proforma Invoice Number",
        max_length=30,
        unique=True,
    )
    proforma_invoice_date = models.DateField(
        verbose_name="Proforma Invoice Date",
    )
    commercial_invoice_number = models.CharField(
        verbose_name="Commercial Invoice Number",
        max_length=30,
        unique=True,
        null=True,
        blank=True,
    )
    commercial_invoice_date = models.DateField(
        verbose_name="Commercial Invoice Date",
        null=True,
        blank=True,
    )
    customs_cleared = models.BooleanField(
        verbose_name="Customs Clearance Status",
        default=False,
        # null=True,
        blank=True,
    )
    customs_cleared_date = models.DateField(
        verbose_name="Customs Cleared Date",
        null=True,
        blank=True,
    )

    margin_percentage = models.PositiveSmallIntegerField(
        verbose_name="Margin Percentage",
        default="10",
    )

    margin_amount = models.DecimalField(
        verbose_name="Margin Amount",
        # default="10",
        max_digits=13,
        null=True,
        decimal_places=2,
    )

    category = models.ForeignKey(
        to=Category,
        on_delete=models.SET_NULL,
        blank=True,
        null=True,
    )
    proforma_invoice_value = models.DecimalField(
        verbose_name="Proforma Invoice Amount",
        max_digits=13,
        decimal_places=2,
        blank=True,
        null=True,
    )

    commercial_invoice_value = models.DecimalField(
        verbose_name="Commercial Invoice Amount",
        max_digits=13,
        decimal_places=2,
        blank=True,
        null=True,
    )

    bank = models.ForeignKey(
        to=Bank,
        verbose_name="Bank",
        on_delete=models.SET_NULL,
        null=True,
    )

    shipper = models.ForeignKey(
        to=Shipper,
        verbose_name="Shipper",
        on_delete=models.SET_NULL,
        null=True,
        related_name="shipper_container",
    )

    hisab_files = models.FileField(
        verbose_name="Select Hisab Files",
        null=True,
        blank=True,
        storage=fs,
    )

    excel_file = models.FileField(
        verbose_name="Excel File",
        null=True,
        blank=True,
        storage=fs,
    )
    customs_excel_file = models.FileField(
        verbose_name="Customs Excel File",
        null=True,
        blank=True,
        storage=fs,
    )
    insurance_file = models.FileField(
        storage=fs,
        verbose_name="Insurance File",
        null=True,
        blank=True,
    )
    contianer_file = models.FileField(
        verbose_name="Container Documents",
        null=True,
        blank=True,
        storage=fs,
    )
    pragyapan_patra = models.FileField(
        verbose_name="Pragyapan Patra",
        null=True,
        blank=True,
        storage=fs,
    )
    dollar_rate = models.DecimalField(
        verbose_name="Dollar Rate",
        decimal_places=2,
        max_digits=5,
        blank=True,
        null=True,
    )

    documents_cleared = models.BooleanField(
        verbose_name="Documents Cleared",
        default=False,
        # null=True,
        # blank=True,
    )

    class Meta:
        db_table = ""
        managed = True
        verbose_name = "Road Container"
        verbose_name_plural = "Road Containers"
        unique_together = ("container_number", "number", "category")

    def calculate_value_in_usd(self):
        if self.dollar_rate is not None and self.proforma_invoice_value is not None:
            value_in_nrp = self.dollar_rate * self.proforma_invoice_value
            return value_in_nrp
        return None

    def __str__(self):
        return f"{self.category} - {self.number}"

    def get_container_name(self):
        return f"{self.category} - {self.number}"

    def get_type(self):
        return "road"


class RoadLoadingMarka(models.Model):
    road_container = models.ForeignKey(
        to=RoadContainer,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
    )
    party_name = models.CharField(
        verbose_name="Party Name",
        max_length=255,
        null=True,
    )
    bilty = models.ImageField(
        null=True,
        storage=fs,
    )
    bilty_number = models.CharField(
        verbose_name="Bilty Number",
        max_length=255,
        null=True,
    )
    bilty_date = models.DateField(
        null=True,
    )
    marka_name = models.CharField(
        verbose_name="Marka Name",
        max_length=255,
        null=True,
    )
    bilty_cartoon_number = models.PositiveSmallIntegerField(
        verbose_name="Cartoon",
        null=True,
    )
    loaded_cartoon_number = models.PositiveSmallIntegerField(
        verbose_name="Loaded Cartoon",
        null=True,
    )
    bilty_rmb = models.DecimalField(
        verbose_name="RMB",
        decimal_places=2,
        max_digits=5,
        null=True,
    )
    place = models.CharField(
        verbose_name="Bilty Place",
        max_length=255,
        null=True,
    )
    transport = models.CharField(
        verbose_name="Transport",
        max_length=155,
        null=True,
    )
    remarks = models.TextField(
        verbose_name="Remarks",
        blank=True,
        null=True,
    )
    packing_list = models.ImageField(
        null=True,
        blank=True,
        storage=fs,
    )


class SeaContainer(models.Model):
    container_number = models.ForeignKey(
        to=ContainerNumber,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
    )

    company = models.ForeignKey(
        to="Company",
        on_delete=models.SET_NULL,
        null=True,
    )

    number = models.CharField(
        verbose_name="Sea Container Number",
        max_length=10,
    )
    payment_method = models.CharField(
        max_length=6,
        choices=PAYMENT_METHODS,
        default="LC",
    )
    bill_of_lading = models.CharField(
        verbose_name="Bill of Lading", max_length=50, null=True, blank=True
    )
    bill_of_lading_date = models.DateField(
        verbose_name="Bill of Lading Date",
        null=True,
        blank=True,
    )

    cartoon_number = models.PositiveIntegerField(
        verbose_name="Loaded Cartoon Number",
    )
    refrence_number = models.CharField(
        verbose_name="LC / TT / DAP number",
        max_length=30,
        unique=True,
        null=True,
        blank=True,
    )
    refrence_date = models.DateField(
        verbose_name="LC / TT / DAP date",
        null=True,
        blank=True,
    )

    proforma_invoice_number = models.CharField(
        verbose_name="Proforma Invoice Number",
        max_length=30,
        unique=True,
    )
    proforma_invoice_date = models.DateField(
        verbose_name="Proforma Invoice Date",
    )
    commercial_invoice_number = models.CharField(
        verbose_name="Commercial Invoice Number",
        max_length=30,
        unique=True,
        null=True,
        blank=True,
    )
    commercial_invoice_date = models.DateField(
        verbose_name="Commercial Invoice Date",
        null=True,
        blank=True,
    )
    customs_cleared = models.BooleanField(
        verbose_name="Customs Clearance Status",
        default=False,
        # null=True,
        blank=True,
    )
    customs_cleared_date = models.DateField(
        verbose_name="Customs Cleared Date",
        null=True,
        blank=True,
    )

    margin_percentage = models.PositiveSmallIntegerField(
        verbose_name="Margin Percentage",
        default="10",
    )

    margin_amount = models.DecimalField(
        verbose_name="Margin Amount",
        # default="10",
        max_digits=13,
        null=True,
        decimal_places=2,
    )

    category = models.ForeignKey(
        to=Category,
        on_delete=models.SET_NULL,
        blank=True,
        null=True,
    )
    proforma_invoice_value = models.DecimalField(
        verbose_name="Proforma Invoice Amount",
        max_digits=13,
        decimal_places=2,
        blank=True,
        null=True,
    )

    commercial_invoice_value = models.DecimalField(
        verbose_name="Commercial Invoice Amount",
        max_digits=13,
        decimal_places=2,
        blank=True,
        null=True,
    )

    bank = models.ForeignKey(
        to=Bank,
        verbose_name="Bank",
        on_delete=models.SET_NULL,
        null=True,
    )

    shipper = models.ForeignKey(
        to=Shipper,
        verbose_name="Shipper",
        on_delete=models.SET_NULL,
        null=True,
    )

    hisab_files = models.FileField(
        verbose_name="Select Hisab Files",
        null=True,
        blank=True,
        storage=fs,
    )

    excel_file = models.FileField(
        verbose_name="Excel File",
        null=True,
        blank=True,
        storage=fs,
    )
    customs_excel_file = models.FileField(
        verbose_name="Customs Excel File",
        null=True,
        blank=True,
        storage=fs,
    )
    insurance_file = models.FileField(
        verbose_name="Insurance File",
        null=True,
        blank=True,
        storage=fs,
    )
    contianer_file = models.FileField(
        verbose_name="Container Documents",
        null=True,
        blank=True,
        storage=fs,
    )
    pragyapan_patra = models.FileField(
        verbose_name="Pragyapan Patra",
        null=True,
        blank=True,
        storage=fs,
    )
    dollar_rate = models.DecimalField(
        verbose_name="Dollar Rate",
        decimal_places=2,
        max_digits=5,
        blank=True,
        null=True,
    )

    documents_cleared = models.BooleanField(
        verbose_name="Documents Cleared",
        default=False,
    )

    class Meta:
        db_table = ""
        managed = True
        verbose_name = "SeaContainer"
        verbose_name_plural = "SeaContainers"
        unique_together = ("container_number", "number", "category")

    def calculate_value_in_usd(self):
        if self.dollar_rate is not None and self.proforma_invoice_value is not None:
            value_in_nrp = self.dollar_rate * self.proforma_invoice_value
            return value_in_nrp
        return None

    def __str__(self):
        return f"{self.category} - {self.number}"

    def get_container_name(self):
        return f"{self.category} - {self.number}"

    def get_type(self):
        return "sea"


class SeaLoadingMarka(models.Model):
    sea_container = models.ForeignKey(
        to=SeaContainer,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
    )
    party_name = models.CharField(
        verbose_name="Party Name", max_length=255, default="Null"
    )
    marka_name = models.CharField(verbose_name="Marka Name", max_length=255)
    cartoon_number = models.PositiveIntegerField(verbose_name="Cartoon")
    cbm = models.DecimalField(
        verbose_name="CBM",
        decimal_places=2,
        max_digits=5,
        null=True,
        default=0.00,
    )

    # all_sent = models.BooleanField(verbose_name="Sent to Customer", default=False)
    # remarks = models.TextField(verbose_name="Sent Remarks")
    # chalan_image = models.ImageField(verbose_name="Document Chalan")

    def __str__(self):
        return f"{self.sea_container} - {self.marka_name}"

*Html File*


<h2 class="text-2xl font-semibold mb-4">Container File</h2>
{% if sea_container.contianer_file %}
    <iframe src="{{ sea_container.contianer_file.url }}"
            class="w-full h-64"
            frameborder="0"></iframe>
    <a href="{{ sea_container.contianer_file.url }}"
       target="_blank"
       class="focus:outline-none text-white bg-purple-700 hover:bg-purple-800 focus:ring-4 focus:ring-purple-300 font-medium rounded-lg text-sm px-5 py-2.5 mb-2 dark:bg-purple-600 dark:hover:bg-purple-700 dark:focus:ring-purple-900">View</a>
    {% if 'add_edit' in groups %}
        <a hx-delete="{% url "delete-container-file" sea_container.id %}"
           hx-confirm="Sure Want to delete?"
           class="focus:outline-none text-white bg-red-700 hover:bg-red-800 focus:ring-4 focus:ring-red-300 font-medium rounded-lg text-sm px-5 py-2.5 mb-2 dark:bg-red-600 dark:hover:bg-red-700 dark:focus:ring-red-900">Delete</a>
    {% endif %}
{% else %}
    <p class="font-semibold mb-4 text-red-500">No Container File Uploaded</p>
    {% if 'add_edit' in groups %}
        <form id="container-form"
              hx-encoding='multipart/form-data'
              hx-post="{% url "upload-container-file" sea_container.id %}">
            <label class="block mb-2 text-sm font-medium text-gray-900 dark:text-white"
                   for="hisab_file">Upload file</label>
            <div class="grid grid-cols-2 gap-4">
                <div>
                    <input class="block w-full text-sm text-gray-900 border border-gray-300 rounded-lg cursor-pointer bg-gray-50 dark:text-gray-400 focus:outline-none dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400"
                           id="container_file"
                           name="container_file"
                           type="file"
                           required
                           accept="image/*,.pdf">
                </div>
                <div>
                    <button type="submit"
                            class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center me-2 dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800 inline-flex items-center">
                        Submit
                    </button>
                </div>
            </div>
        </form>
    {% endif %}
{% endif %}

Screenshots

Couldn’t add more links to above so I’m adding it here
Models.py
Template

Please do not post links to code stored externally. Copy/paste the code itself into the body of your post.

If you are looking for assistance with a specific issue, it’s more helpful if you posted just the portions of the code where you are having a problem. You are less likely to find someone willing to help my making them review your entire project without you providing some type of guide as to which section you think they should be looking at.

Side note: When posting code here, enclose the code between lines of three backtick - ` characters. This means you’ll have a line of ```, then the code, then another line of ```. This forces the forum software to keep your code properly formatted.

1 Like

I’ve updated my post to include the code, thank you