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.