user519178
user519178

Reputation: 9

How to submit an update form and create form at the same time in Django?

I am trying to update a model "Stock", then create a new "StockTransaction" at the same time. I want to accomplish this using two different forms submitted together. I am able to get the stock update transaction to work, but when I try to is_valid() on the transaction form, it always returns false. I can't figure out why it is returning false.

here are all of the relevant code sections that are used. Any help is appreciated. Thank you in advance!

def buyStock(request, pk):
    stock = Stock.objects.get(id=pk)
    form = StockForm(instance=stock)
    tform = StockTransForm()
    if request.method == 'POST':
        form = StockForm(request.POST, instance=stock)
        form.instance.buyPrice = stock.ticker.price
        form.instance.dateOfPurchase = date.today()
        form.instance.forSale = False

        tform.instance.stockID = stock.stockID
        tform.instance.buyPrice = stock.buyPrice
        tform.instance.sellPrice = stock.ticker.price
        tform.instance.broker = form.instance.broker
        tform.instance.buyer = form.instance.ownerID
        tform.instance.seller = stock.ownerID
        tform.instance.ticker = stock.ticker

    if form.is_valid() and tform.is_valid():
            form.save()
            tform.save()
class StockTransaction(models.Model):
    transactionID = models.AutoField(primary_key=True)
    ticker = models.ForeignKey(PublicCompany, on_delete=models.CASCADE, default=None,
                               related_name='stocktrans-ticker+')
    stockID = models.IntegerField()
    buyer = models.ForeignKey(FinancialAccount, on_delete=models.PROTECT, default=None,
                              related_name='stocktrans-buyer+')
    seller = models.ForeignKey(FinancialAccount, on_delete=models.PROTECT, default=None,
                               related_name='stocktrans-seller+')
    sellPrice = models.DecimalField(max_digits=7, decimal_places=2)
    buyPrice = models.DecimalField(max_digits=7, decimal_places=2)
    date = models.DateField(auto_now_add=True)
    broker = models.ForeignKey(Agent, on_delete=models.PROTECT, default=None, related_name='stocktrans-broker+')
class Stock(models.Model):

    ownerID = models.ForeignKey(FinancialAccount, on_delete=models.CASCADE, default=None,
                                related_name='stock-owner+')#on delete maybe change
    buyPrice = models.DecimalField(max_digits=7, decimal_places=2)
    broker = models.ForeignKey(Agent, on_delete=models.PROTECT, default=None, related_name='stock-broker+')
    dateOfPurchase = models.DateField(auto_now_add=True)
    ticker = models.ForeignKey(PublicCompany, on_delete=models.CASCADE, default=None)
    stockID = models.IntegerField()
    forSale = models.BooleanField(default=True)

    class Meta:
        unique_together = ['ticker', 'stockID']
class StockTransForm(ModelForm):
    class Meta:
        model = StockTransaction
        fields = []
{% extends 'finances/base.html' %}
{% block content %}
    <div class="content-section">
        <form action="" method="POST">
            {% csrf_token %}
            {{form}}
            <fieldset class="form-group">
                <legend class="border-bottom mb-4">Buy Asset</legend>
                <h2>Are you sure you want to buy this asset - {{stock.ticker}}:{{stock.stockID}}</h2>
            </fieldset>
            <div class ="form-group">
                <button class="btn btn-outline-danger" type ="submit">Buy</button>
                <a class="btn btn-outline-secondary" href="{% url 'finance-forsale'%}">No</a>
            </div>
        </form>
    </div>
{% endblock content %}

I have gone over every variable to make sure that they all match and are the same.

Upvotes: 0

Views: 37

Answers (1)

nigel222
nigel222

Reputation: 8202

Don't know what's wrong, but updating instance is not the official way. What you should do is use commit=False to apply all data which came in through the form to obtain an instance which is not yet saved.

if request.method == 'POST': 
    form = StockForm(request.POST, instance=stock) 
    if form.is_valid(): 

        f_instance = form.save( commit=False) 

        # now update instance with non-form data
        f_instance.buyPrice = stock.ticker.price
        f_instance.dateOfPurchase = date.today() 
        f_instance.forSale = False 

        # f_instance is not yet saved to the DB 

    #now similar code for tform to t_instance 
    ... 

    # finally, save these instances to the DB 
    if form.is_valid() and tform.is_valid(): 
        with transaction.atomic(): # unless the entire view is atomic 
             f_instance.save() 
             t_instance.save()

Upvotes: 1

Related Questions