3

I have duplication problem now I don't know the way forward need help I have this model branch with a reverse relation to stock

class Branch(models.Model):
    name = models.CharField(
        'Branch',
        unique=True,
        max_length=10,
        validators=[MinLengthValidator(5)])
    location = models.TextField(max_length=650,
        blank=True,
        help_text='location of the linsan branch')


    class Meta:
        verbose_name_plural = 'Branch'

    def __str__(self):
        return self.name 

class Stock(models.Model):
    branch          = models.ForeignKey(
        Branch,
        related_name = 'branch',
        help_text='Enter the name of the branch',
        on_delete=models.CASCADE,
        blank=False,
        null=False
        )

    manufacturers_name = models.CharField(
        max_length=50, 
        blank=True)

    description        = models.CharField(
        max_length=50,
        help_text='Enter the name of the product here',
        unique=True
        )

    model_number    = models.CharField(
        max_length=25,
        blank=True,
        null=True,
        help_text='Enter the model number of the item if any')

    color           = models.CharField(
        max_length=20,
        default='black',
        blank=True,
        null=True,)
    quantity        = models.PositiveIntegerField(
        validators=[validate],
        verbose_name='Quantity In stock')

    retail_price    = MoneyField(
        max_digits=14,
        decimal_places=2,
        default_currency='NGN',
        blank=False,
        verbose_name="Retail Price")

    customer_price  = MoneyField(
        max_digits=14,
        decimal_places=2,
        default_currency='NGN',
        blank=False)

    added = models.DateTimeField(
        auto_now_add=True, 
        help_text='The date the product was added')
    image           = models.ImageField(
        blank=True,
        null=True,
        upload_to='uploads/%Y/%m/%d/',
        help_text='Upload the image of the product if any')
    history = HistoricalRecords()
    class Meta:
        ordering = ['description']


    def __str__(self):
        return self.description

And another model with a foreignKey to stock

class WaybillItem(models.Model):
    waybill = models.ForeignKey(Waybill,
        on_delete=models.CASCADE,
        related_name='waybill_item')
    product = models.ForeignKey(
        'stock.Stock',
        on_delete=models.CASCADE,
        blank=False,
        null=False)
    quantity = models.PositiveIntegerField(validators=[validate, MinValueValidator(1)])

In my stock app I have a signal that I want to create new stock object to another branch if it doesn't exist.

def update_stock_on_waybill(sender, instance, **kwargs):
    transferred_to = instance.waybill.transferred_to.branch.all()
    product = instance.product

    if product in transferred_to:
        print("it is!")
        pass
    else:
        print("it isn't")
        Stock.objects.create(
            branch=instance.product.branch,
            description=instance.product.description,
            model_number=instance.product.model_number,
            color=instance.product.color,
            quantity=instance.quantity,
            retail_price=instance.product.retail_price,
            customer_price=instance.product.customer_price
            )
    product.save()

    pre_save.connect(update_stock_on_waybill, sender=WaybillItem)

But Every time I save a new Waybill(**I excluded the model) which doesn't exist it creates the new object and which is fine but same apply if the object does exist, I am relatively new to python, django, programming in general I just started so a nudge, a push, pointers in the right direction will be mostly grateful I will continue to search this site for something similar I believe someone might have stumbled across something similar preciously. Thanks in adv

7
  • Am I understanding correctly that you only want to create this object once, and only once? Commented Oct 5, 2018 at 15:57
  • yes that is what I want to do for a particular branch Commented Oct 5, 2018 at 15:58
  • 1
    You can use get_or_create instead of create, but why all this redundant data and not a foreign key from stock to product? Commented Oct 5, 2018 at 15:59
  • Why not add boolean like is_create = True on the first pass, then check against that boolean Commented Oct 5, 2018 at 15:59
  • that was a place holder for what I intend doing if the objects stop duplicating eg: if there is already object in the other branch instead of creating new object I want to add to the quantity instead Commented Oct 5, 2018 at 16:01

2 Answers 2

1

To accomplish what you want, you can add a boolean check to the first pass.

def update_stock_on_waybill(sender, instance,is_create, **kwargs):

    transferred_to = instance.waybill.transferred_to.branch.all()
    product = instance.product

    if is_create:
        print("it is!")
        pass
    else:
        print("it isn't")
        Stock.objects.create(
            branch=instance.product.branch,
            description=instance.product.description,
            model_number=instance.product.model_number,
            color=instance.product.color,
            quantity=instance.quantity,
            retail_price=instance.product.retail_price,
            customer_price=instance.product.customer_price
            )
        is_create = True
    product.save()

    pre_save.connect(update_stock_on_waybill, sender=WaybillItem)
    return is_create

I added is_create as a parameter to the function, as the check, and as the return. is_created can be set as a variable outside of the scope of this function, then passed to the function every time it is called.

so

out_scope_created = False
out_scope_created = update_stock_on_waybill(sender,instance,out_scope_created)
Sign up to request clarification or add additional context in comments.

2 Comments

Let me check and come back it
ooh my bad I have figured it out. I will stick with yours as the answer though.
0

I tacked similar situation a bit differently. I added a set of existing items (identifier to the object) to the object creation. I then fail the init in the class if the new object already exists.

class firstone:
    def __init__(self,name:str,chk:set):
        if name in chk:
            raise ValueError
        self.name = name
        chk.add(name)

    def get_name(self) -> str:
        return self.name

Create a set and instantiate first object.

nmset=set()
a=firstone("a",nmset)

a.get_name()

Returns 'a'

nmset

Returns set containing just 'a'

b=firstone("a",nmset)

Throws the ValueError which can be handled whichever way..

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-17-312c2fbf49eb> in <module>
----> 1 b=firstone("a",nmset)

<ipython-input-13-660b12b68b44> in __init__(self, name, chk)
      2     def __init__(self,name:str,chk:set):
      3         if name in chk:
----> 4             raise ValueError
      5         self.name = name
      6         chk.add(name)

ValueError: 

The downside is the to have to pass the set but I found this to be an easier approach when there are just a lot of places objects can be instantiated from...

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.