How can I export "{pmin} to {pmax}" from my model which I am using in admin?

MY MODEL:-

class BomItem(models.Model):   
    def get_absolute_url(self):
        return reverse('bom-item-detail', kwargs={'pk': self.id})

    # A link to the parent part
    # Each part will get a reverse lookup field 'bom_items'
    part = models.ForeignKey(Part, on_delete=models.CASCADE, related_name='bom_items',
                             help_text=_('Select parent part'),
                             limit_choices_to={
                                 'assembly': True,
                                 'is_template': False,
                             })

    # A link to the child item (sub-part)
    # Each part will get a reverse lookup field 'used_in'
    sub_part = models.ForeignKey(Part, on_delete=models.CASCADE, related_name='used_in',
                                 help_text=_('Select part to be used in BOM'),
                                 limit_choices_to={
                                     'component': True,
                                     'is_template': False,
                                 })

    # Quantity required
    quantity = models.DecimalField(default=1.0, max_digits=15, decimal_places=5, validators=[MinValueValidator(0)],
                                   help_text=_('BOM quantity for this BOM item'))

    overage = models.CharField(max_length=24, blank=True, validators=[validators.validate_overage],
                               help_text=_('Estimated build wastage quantity (absolute or percentage)')
                               )

    reference = models.CharField(max_length=500, blank=True, help_text=_('BOM item reference'))

    # Note attached to this BOM line item
    note = models.CharField(max_length=500, blank=True, help_text=_('BOM item notes'))

    checksum = models.CharField(max_length=128, blank=True, help_text=_('BOM line checksum'))

    def get_item_hash(self):
        """ Calculate the checksum hash of this BOM line item:
        The hash is calculated from the following fields:
        - Part.full_name (if the part name changes, the BOM checksum is invalidated)
        - Quantity
        - Reference field
        - Note field
        """

        # Seed the hash with the ID of this BOM item
        hash = hashlib.md5(str(self.id).encode())

        # Update the hash based on line information
        hash.update(str(self.sub_part.id).encode())
        hash.update(str(self.sub_part.full_name).encode())
        hash.update(str(self.quantity).encode())
        hash.update(str(self.note).encode())
        hash.update(str(self.reference).encode())

        return str(hash.digest())

    def validate_hash(self, valid=True):
        """ Mark this item as 'valid' (store the checksum hash).

        Args:
            valid: If true, validate the hash, otherwise invalidate it (default = True)
        """

        if valid:
            self.checksum = str(self.get_item_hash())
        else:
            self.checksum = ''

        self.save()

    @property
    def is_line_valid(self):
        """ Check if this line item has been validated by the user """

        # Ensure an empty checksum returns False
        if len(self.checksum) == 0:
            return False

        return self.get_item_hash() == self.checksum

    def clean(self):
        """ Check validity of the BomItem model.
        Performs model checks beyond simple field validation.
        - A part cannot refer to itself in its BOM
        - A part cannot refer to a part which refers to it
        """

        # A part cannot refer to itself in its BOM
        try:
            if self.sub_part is not None and self.part is not None:
                if self.part == self.sub_part:
                    raise ValidationError({'sub_part': _('Part cannot be added to its own Bill of Materials')})

            # TODO - Make sure that there is no recusion

            # Test for simple recursion
            for item in self.sub_part.bom_items.all():
                if self.part == item.sub_part:
                    raise ValidationError({'sub_part': _(
                        "Part '{p1}' is  used in BOM for '{p2}' (recursive)".format(p1=str(self.part),
                                                                                    p2=str(self.sub_part)))})

        except Part.DoesNotExist:
            # A blank Part will be caught elsewhere
            pass

    class Meta:
        verbose_name = "BOM Item"

        # Prevent duplication of parent/child rows
        unique_together = ('part', 'sub_part')

    def __str__(self):
        return "{n} x {child} to make {parent}".format(
            parent=self.part.full_name,
            child=self.sub_part.full_name,
            n=helpers.decimal2string(self.quantity))

    def get_overage_quantity(self, quantity):
        """ Calculate overage quantity
        """

        # Most of the time overage string will be empty
        if len(self.overage) == 0:
            return 0

        overage = str(self.overage).strip()

        # Is the overage a numerical value?
        try:
            ovg = float(overage)

            if ovg < 0:
                ovg = 0

            return ovg
        except ValueError:
            pass

        # Is the overage a percentage?
        if overage.endswith('%'):
            overage = overage[:-1].strip()

            try:
                percent = float(overage) / 100.0
                if percent > 1:
                    percent = 1
                if percent < 0:
                    percent = 0

                # Must be represented as a decimal
                percent = Decimal(percent)

                return float(percent * quantity)

            except ValueError:
                pass

        # Default = No overage
        return 0

    def get_required_quantity(self, build_quantity):
        """ Calculate the required part quantity, based on the supplier build_quantity.
        Includes overage estimate in the returned value.

        Args:
            build_quantity: Number of parts to build
        Returns:
            Quantity required for this build (including overage)
        """

        # Base quantity requirement
        base_quantity = self.quantity * build_quantity

        # Overage requiremet
        ovrg_quantity = self.get_overage_quantity(base_quantity)

        required = float(base_quantity) + float(ovrg_quantity)

        return required

    @property
    def price_range(self):
        """ Return the price-range for this BOM item. """

        prange = self.sub_part.get_price_range(self.quantity)

        if prange is None:
            return prange

        pmin, pmax = prange

        if pmin == pmax:
            return decimal2string(pmin)

        # Convert to better string representation
        pmin = decimal2string(pmin)
        pmax = decimal2string(pmax)

        return "{pmin} to {pmax}".format(pmin=pmin, pmax=pmax)

My admin.py from where I am exporting my data:-

class BomItemResource(ModelResource):
    """ Class for managing BomItem data import/export """

    sub_part_name = Field(attribute='sub_part__full_name', readonly=True)
    sub_part_description = Field(attribute='sub_part__description', readonly=True)
    available = Field(attribute='sub_part__total_stock', readonly=True)
    price_range = Field(attribute='sub_part', readonly=True)  #I want here my price how can I do this.

    class Meta:
        model = BomItem
        skip_unchanged = True
        report_skipped = False
        clean_model_instances = True

        exclude = [
            'checksum',
            'id',
            'part',
            'sub_part',
            'overage',
        ]

Just taking a quick stab at this, but it looks like you might need to create a dehydrate_ method to retrieve the values you want in the format you want them exported.

1 Like

Please reply on this thread if you know:- how can I also show stock message with there location like "Added %s items to stock with %s location"?

Just a friendly request - please don’t “cross-post” requests for assistance across threads to me. I do a pretty good job of seeing all the new posts coming in, and these types of messages just clutter up the “new messages list”.

Thanks,
Ken