@@ -28,13 +28,17 @@ class JsonExportSchema(models.Model):
2828 active = fields .Boolean (default = True )
2929 model_id = fields .Many2one (
3030 "ir.model" ,
31- string = "Model" ,
31+ string = "Model Reference " ,
3232 required = True ,
3333 ondelete = "cascade" ,
3434 domain = [("transient" , "=" , False )],
3535 )
3636 model_name = fields .Char (
37- related = "model_id.model" , store = True , readonly = True , index = True
37+ string = "Model Name" ,
38+ related = "model_id.model" ,
39+ store = True ,
40+ readonly = True ,
41+ index = True ,
3842 )
3943 exporter_id = fields .Many2one ("ir.exports" , string = "Field Selector" )
4044 domain = fields .Char (string = "Record Filter" , default = "[]" )
@@ -130,11 +134,9 @@ def _compute_json_schema(self):
130134 def _wrap_api_response_schema (self , record_schema , endpoint = None ):
131135 """Wrap a record-level schema in the full API response envelope."""
132136 nullable_string = {"anyOf" : [{"type" : "string" }, {"type" : "null" }]}
133- description = (
134- "%s Supports ?page=N to navigate pages "
135- "and ?page=last to jump to the last page."
136- % record_schema .get ("description" , "" )
137- )
137+ desc = record_schema .get ("description" , "" )
138+ description = f"{ desc } Supports ?page=N to navigate pages "
139+ description += "and ?page=last to jump to the last page."
138140 if endpoint :
139141 if endpoint .allow_filtering :
140142 description += (
@@ -152,7 +154,7 @@ def _wrap_api_response_schema(self, record_schema, endpoint=None):
152154 )
153155 return {
154156 "$schema" : "http://json-schema.org/draft-07/schema#" ,
155- "title" : "%s — API Response" % record_schema .get (" title" , " Export" ) ,
157+ "title" : f" { record_schema .get (' title' , ' Export' ) } — API Response" ,
156158 "description" : description ,
157159 "type" : "object" ,
158160 "required" : ["success" , "data" , "pagination" , "meta" ],
@@ -249,16 +251,15 @@ def _wrap_api_response_schema(self, record_schema, endpoint=None):
249251 }
250252
251253 def _generate_json_schema (self ):
252- """Generate a JSON Schema (draft-07) from the resolved parser and model fields."""
254+ """Generate a JSON Schema from the resolved parser and model fields."""
253255 self .ensure_one ()
254256 parser = self ._get_parser ()
255257 model = self .env [self .model_name ]
256258 properties , required = self ._parser_to_schema_properties (parser , model )
257259 return {
258260 "$schema" : "http://json-schema.org/draft-07/schema#" ,
259261 "title" : self .name ,
260- "description" : "Auto-generated schema for %s (%s)"
261- % (self .name , self .model_name ),
262+ "description" : f"Auto-generated schema for { self .name } ({ self .model_name } )" ,
262263 "type" : "object" ,
263264 "properties" : properties ,
264265 "required" : required ,
@@ -383,7 +384,9 @@ def _get_parser(self):
383384 raise UserError (_ ("Please select a field selector (exporter) first." ))
384385 # Remove broken export lines (e.g. name=False) before parsing,
385386 # otherwise jsonifier's get_json_parser() crashes on .split("/")
386- bad_lines = self .exporter_id .export_fields .filtered (lambda l : not l .name )
387+ bad_lines = self .exporter_id .export_fields .filtered (
388+ lambda field : not field .name
389+ )
387390 if bad_lines :
388391 bad_lines .unlink ()
389392 raw_parser = self .exporter_id .get_json_parser ()
@@ -471,9 +474,9 @@ def _build_filter_domain(self, params, allowed_fields):
471474 raw_value = params [key ]
472475
473476 if field_name not in allowed_fields :
474- raise ValueError ("Filtering on field '%s ' is not allowed." % field_name )
477+ raise ValueError (f "Filtering on field '{ field_name } ' is not allowed." )
475478 if operator not in self .FILTER_OPERATORS :
476- raise ValueError ("Unknown filter operator '%s '." % operator )
479+ raise ValueError (f "Unknown filter operator '{ operator } '." )
477480
478481 odoo_op = self .FILTER_OPERATORS [operator ]
479482 value = self ._coerce_filter_value (field_name , operator , raw_value )
@@ -507,18 +510,18 @@ def _coerce_single_value(field_type, raw):
507510 try :
508511 return int (raw )
509512 except (ValueError , TypeError ) as err :
510- raise ValueError ("Expected integer value, got '%s '." % raw ) from err
513+ raise ValueError (f "Expected integer value, got '{ raw } '." ) from err
511514 elif field_type in ("float" , "monetary" ):
512515 try :
513516 return float (raw )
514517 except (ValueError , TypeError ) as err :
515- raise ValueError ("Expected numeric value, got '%s '." % raw ) from err
518+ raise ValueError (f "Expected numeric value, got '{ raw } '." ) from err
516519 elif field_type == "boolean" :
517520 if raw .lower () in ("true" , "1" , "yes" ):
518521 return True
519522 elif raw .lower () in ("false" , "0" , "no" ):
520523 return False
521- raise ValueError ("Expected boolean value, got '%s '." % raw )
524+ raise ValueError (f "Expected boolean value, got '{ raw } '." )
522525 return raw
523526
524527 def _build_sort_order (self , sort_param , allowed_fields ):
@@ -541,8 +544,8 @@ def _build_sort_order(self, sort_param, allowed_fields):
541544 field_name = token
542545 direction = "asc"
543546 if field_name not in allowed_fields :
544- raise ValueError ("Sorting on field '%s ' is not allowed." % field_name )
545- parts .append ("%s %s" % ( field_name , direction ) )
547+ raise ValueError (f "Sorting on field '{ field_name } ' is not allowed." )
548+ parts .append (f" { field_name } { direction } " )
546549 return ", " .join (parts )
547550
548551 def _filter_parser (self , fields_param ):
@@ -558,7 +561,7 @@ def _filter_parser(self, fields_param):
558561 invalid = requested - allowed
559562 if invalid :
560563 raise ValueError (
561- "Field selection on '%s' is not allowed." % "' , '" .join (sorted (invalid ))
564+ f "Field selection on '{ ' , ' .join (sorted (invalid ))} ' is not allowed."
562565 )
563566 full_parser = self ._get_parser ()
564567 filtered = []
@@ -583,9 +586,9 @@ def action_export_json(self):
583586 records = self ._get_records ()
584587 data = self ._serialize_records (records )
585588 content = json .dumps (data , indent = 2 , ensure_ascii = False )
586- filename = "export_%s_%s.json" % (
587- self .model_name .replace ("." , "_" ),
588- fields .Datetime .now ().strftime (" %Y%m%d_%H%M%S" ),
589+ filename = (
590+ f"export_ { self .model_name .replace ('.' , '_' ) } _"
591+ f" { fields .Datetime .now ().strftime (' %Y%m%d_%H%M%S' ) } .json"
589592 )
590593 attachment = self .env ["ir.attachment" ].create (
591594 {
@@ -601,7 +604,7 @@ def action_export_json(self):
601604 self ._create_log ("manual" , "success" , len (records ), duration )
602605 return {
603606 "type" : "ir.actions.act_url" ,
604- "url" : "/web/content/%s ?download=true" % attachment . id ,
607+ "url" : f "/web/content/{ attachment . id } ?download=true" ,
605608 "target" : "new" ,
606609 }
607610 except Exception as e :
@@ -616,7 +619,7 @@ def action_view_logs(self):
616619 "type" : "ir.actions.act_window" ,
617620 "name" : _ ("Export Logs" ),
618621 "res_model" : "json.export.log" ,
619- "view_mode" : "tree ,form" ,
622+ "view_mode" : "list ,form" ,
620623 "domain" : [("schema_id" , "=" , self .id )],
621624 "context" : {"default_schema_id" : self .id },
622625 }
0 commit comments