Search code examples
pythondjangopython-3.xdjango-modelsdjango-2.1

Django 2 lost the change on models even after saving the update


I'm working on a project using Python(3.7) and Django(2.1) in which I'm updating a model and save it, after that if I check the list view first it shows the update correctly but once I opened the detailed view it lost the update and return back to previous state.

Here's What I had tried:

From models.py:

class Order(models.Model):
    status_choices = (
        ('Active', 'Active'),
        ('Completed', 'Completed'),
        ('Late', 'Late'),
        ('Short', 'Short'),
        ('Canceled', 'Canceled'),
        ('Submitted', 'Submitted')
    )
    delivery_status_choices = (
        ('Accepted', 'Accepted'),
        ('Rejected', 'Rejected')
    )
    gig = models.ForeignKey('Gig', on_delete=models.CASCADE)
    seller = models.ForeignKey(User, on_delete=models.CASCADE, related_name='selling')
    buyer = models.ForeignKey(User, on_delete=models.CASCADE, related_name='buying')
    created_at = models.DateTimeField(auto_now=timezone.now())
    charge_id = models.CharField(max_length=234)
    days = models.IntegerField(blank=False)
    status = models.CharField(max_length=255, choices=status_choices)
    delivery = models.FileField(upload_to=content_file_name, blank=True)

    def __str__(self):
        return f'{self.buyer} order from {self.seller}'

From template.html:

{%  if not order.status == 'Completed' and not order.status == 'Submitted' and not order.status == 'Canceled' %}
     {% if order.buyer.username == user.username %}
           <form method="post" action="{% url 'order-cancel' %}">
                 {% csrf_token %}
                 <input type="text" name="id" value="{{ order.id }}" hidden />
                 <button type="submit" class="btn btn-primary align-content-center">Cancel the Order</button>
             </form>
      {% elif order.status == 'Canceled' %}
             <p> Your order has been canceled already!</p>
      {% endif %}
    {% else %}
        <p> You can't cancel this order now.</p>
 {% endif %}

and From views.py:

@login_required()
def order_cancel(request):
    if request.method == 'POST':
        try:
            order_id = request.POST.get('id')
            print(order_id)
            order = Order.objects.get(id=order_id)
            charge_id = order.charge_id
            refund = stripe.Refund.create(
                charge=charge_id,
            )
            order.status = 'Canceled'
            order.save()
            print(order.status)
            print('success')
            return HttpResponseRedirect(reverse_lazy('buying'))
        except Order.DoesNotExist:
            return redirect('home')

I'm trying to update the status of order, when I submit the request to order-cancel view, first it save the status as canceled and when I loads the detailed (Single object Page) it revert the updated status back o previous once.

What can be wrong here?

Thanks in advance!


Solution

  • you will merge() function and then finally commit the session.

    db.session.merge(order)
    db.session.commit()
    

    Two ways of getting around it. Solution 2 is always my best choice

    1.) using objects query get method

    @login_required()
    def order_cancel(request):
        if request.method == 'POST':
            try:
                order_id = request.POST.get('id')
                print(order_id)
                order = Order.objects.get(id=order_id)
                charge_id = order.charge_id
                refund = stripe.Refund.create(
                    charge=charge_id,
                )
                order.status = 'Canceled'
                db.session.merge(order)
                db.session.commit()
                print(order.status)
                print('success')
                return HttpResponseRedirect(reverse_lazy('buying'))
            except Order.DoesNotExist:
                return redirect('home')
    

    2.) using object query filter_by method

    @login_required()
    def order_cancel(request):
        if request.method == 'POST':
            try:
                order_id = request.POST.get('id')
                print(order_id)          
                order = Order.query.filter_by(id=order_id).first()
                charge_id = order.charge_id
                refund = stripe.Refund.create(
                    charge=charge_id,
                )
                order.status = 'Canceled'
                db.session.merge(order)
                db.session.commit()
                print(order.status)
                print('success')
                return HttpResponseRedirect(reverse_lazy('buying'))
            except Order.DoesNotExist:
                return redirect('home')