SoFunction
Updated on 2024-12-19

Example of nested try-except in django

I'm going to cut to the chase, so let's just go straight to the code!

# Since this is a yaml template and only grabs the node port, it's faster to process it this way
content_dict = parse_yaml(("{{", "").replace("}}", ""))
if 'service' in content_dict.keys():
  # Record all node_ports in this yaml and update to the database
  now_app_list = []
  for service_item in content_dict['service']:
    for port_item in service_item['port']:
      if 'nodePort' in port_item.keys():
        node_port = int(port_item['nodePort'])
        if 30000 <= node_port <= 32000:
          # The judgment here is a bit more complicated, if the port is there and the app is the same, no update. If the port is available and the app is not the same, report a conflict. If the port is not available, it can be inserted.
          now_app_list.append(node_port)
          try:
            (node_port=node_port, app=app)
            pass
          except :
            try:
              (node_port=node_port)
              (, 'nodeport{}port conflict!'.format(node_port))
              return HttpResponseRedirect(reverse_lazy("app:yaml_edit", kwargs=))
            except :
              name = '{}-{}'.format(, node_port)
              (
                name=name,
                app=app,
                node_port=node_port
              )
        else:
          (, 'nodeport{}The port is not in the specified range(30000-~32000)!'.format(node_port))
          return HttpResponseRedirect(reverse_lazy("app:yaml_edit", kwargs=))
  # Fetch all the node_ports of this app in AppPort, and clear the redundant ones.
  all_app_list = (app=app).values_list('node_port', flat=True)
  if all_app_list:
    # Take the intersection, which is the list of redundant ports in the database
    diff_list = [x for x in all_app_list if x not in now_app_list]
    if diff_list:
      (node_port__in=diff_list).delete()

I feel that the above code, the application of technical points quite a lot, for the record.

Includes management ideas for its node ports, extraction tips.

List flattening for orm, list intersection, batch deletion

Additional knowledge:Django saves the database in the exception catch, and then throws the exception again after saving it.

Demand:

When I check the quota, if the quota is not enough, I need to change the order status to 5 and then throw the original exception again

I: Initial approach

try:
  self.check_quota_enough(create_form) # Check quotas
except Exception as e:
   = 5
  ()
  raise e

Problem: django has transactions turned on by default, so I save the order status and then throw an exception without any problems

But when I query the database for order status, I find that the status of the order change before the exception was thrown has been lost

II: Optimize, use decorators, manually close transactions

# Add decorator to dispatch method to turn off transactions
class xxxxxxxx():
 @method_decorator(transaction.non_atomic_requests)
 def dispatch(self, request, *args, **kwargs):
   return super().dispatch(request, *args, **kwargs)
 
 def form_valid(self, form):
 ...
 ...
 try:
   self.check_quota_enough(create_form) # Check quotas
 except Exception as e:
    = 5
   ()
   raise e

This method solves the above problem

However, this method is valid for the entire view, and clearly does not make sense if the consistency of the transaction needs to be used elsewhere in the view

II: Optimization, defining transaction savepoints, controlling transaction consistency locally

class xxxxxxxx():
 
 def form_valid(self, form):
 ...
 ...
 sid = () # Define transaction save points
    try:
      self.check_quota_enough(create_form)
    except QuotaNotEnough as e:
       = 5
      ()
      transaction.savepoint_commit(sid)
      return self.render_to_json_response(result=False, messages=str(e))

(): data is stored here

sid = (): set save point

(): here the data is saved again

The next step is logical processing: if the xxxxxxxxxx condition is met, submit it manually, at which point the data saved by () and () will take effect.

If the xxxxxxxxxx condition is not met, then transaction rollback is executed, at this time the data in () before the save point we defined will not be affected, but the data in () after the save point will be rolled back.

So we can realize our needs by adjusting the position of the save point.

The above example of nested try-except in django is all I have to share with you.