[SOLVED] Django – Calling function in ListView or model to change model bolean status

Issue

I want to call a function – from a model or from a Listview that will change Order.isDone status – TRUE or FALSE after clicking the button in template.

Model.py:

class Order(models.Model):
    isDone = models.BooleanField(default=False, verbose_name='Zrealizowane')
 

views.py:

class OrderListView (ListView):
  model = Order
  template_name = 'orders/orders_list.html'
  ordering = ['-orderDate']

urls.py:

urlpatterns = [
    path('', views.home, name='page-home'),
    path('orders_list/', OrderListView.as_view(), name='page-orders-list'),
    path('completed_orders_list/', OrderCompletedListView.as_view(), name='page-completed-orders-list'),
    path('orders/order_create/', OrderCreateView.as_view(), name='page-order-create'),
    path('orders/<int:pk>/delete/', OrderDeleteView.as_view(), name='page-order-delete'),
]

template:

      <tbody>
        {% for order in object_list %}
          {% if order.isDone == False %}
          <tr>
            <td>
              <button type="button" class="btn btn-secondary" data-toggle="modal" data-target="#exampleModalCenter">Szczegóły</button>
              <form action="{% url 'page-orders-list' order.id %}" method="post">
                {% csrf_token %}
                <button class="btn btn-info btn-sm">Finish order</button>
              <form>
              <a class="btn btn-danger adminButton" href="{% url 'page-order-delete' order.id %}">Usuń</a>
            </td>
          </tr>
          {% endif %}
        {% endfor %}
      </tbody>
    </table>
  </div>

{% endblock %}

What is the easiest way to do this ?

Solution

I suggest using another view for this. You can use the get method in the view to change the status of the order. The in your HTML you would only need to use a link instead of a form.

So something like this:

views.py

class OrderFinishView(RedirectView):
  success_url = None  # After finishing the order, where do you want to redirect the user?
  
  def get(self, request, *args, **kwargs):
     order_id = self.kwargs['pk_order']  # pk_order must be in your URL
     order = get_object_or_404(Order, pk=order_id)

     order.is_done = True
     order.save()

     return super().get(request, *args, **kwargs)

urls.py

urlpatterns = [
    path('', views.home, name='page-home'),
    path('orders_list/', OrderListView.as_view(), name='page-orders-list'),
    path('completed_orders_list/', OrderCompletedListView.as_view(), name='page-completed-orders-list'),
    path('orders/order_create/', OrderCreateView.as_view(), name='page-order-create'),
    path('orders/<int:pk>/delete/', OrderDeleteView.as_view(), name='page-order-delete'),
    path('orders/<int:pk_order>/finish', OrderFinishView.as_view(), name='page-order-finish'),
]

template

      <tbody>
        {% for order in object_list %}
          {% if order.isDone == False %}
          <tr>
            <td>
                <a href={% url 'page-order-finish' order.id %}>Finish</a>
            </td>
          </tr>
          {% endif %}
        {% endfor %}
      </tbody>
    </table>
  </div>

{% endblock %}

Another idea is to use an UpdateView to update your order with a PartialOrderForm which would only contain the is_done field.

Answered By – vinkomlacic

Answer Checked By – Gilberto Lyons (BugsFixing Admin)

Leave a Reply

Your email address will not be published. Required fields are marked *