We decided to add a business justification field to our Trac instance today, but needed to put it directly below the description field so that it was in a more logical position for the users. It is not possible to intermingle custom ticket fields with standard ones (from within Trac), so editing the ticket template file will be required.

Note: This has been developed and tested for Trac-1.0.1dev_r11400, and may not work on other versions without modifications

Another Note: This process is overkill in most scenarios, and is really only useful if you also need to change the ordering of default ticket fields. If you are just trying to order custom fields, please take a look at the order property in Trac’s documentation

  1. Copy ticket.html to your local Trac environment’s templates directory (/var/local/trac/templates in my case)
    # Ubuntu
    sudo cp /usr/local/lib/python2.7/dist-packages/Trac-1.0.1dev_r11400-py2.7.egg/trac/ticket/templates/ticket.html /var/local/trac/templates/
    # RedHat/CentOS
    sudo cp /usr/local/lib/python2.7/site-packages/Trac-1.0.1dev_r11400-py2.7.egg/trac/ticket/templates/ticket.html /var/local/trac/templates/
  2. Add the below code to the top of the copied template file (/var/local/trac/templates/ticket.html). Note – summary, reporter, and description are hard coded into Trac and cannot be modified using this method. You can manually alter them further down in this template if necessary (not covered here).
      # Define the field order. Note that `summary`, `reporter`, and `description` are hard coded into Trac
      ## Add custom fields anywhere in the below list, excluded elements will be added to the end
      field_types = [ 'type', 'priority', 'component', 'cc', 'keywords', ] 
      # Sorting function
      def sort_nicely(field1, field2):
            idx1 = field_types.index(field1['name'])
        except ValueError:
            idx1 = 1000 # no match, push to the end
            idx2 = field_types.index(field2['name'])
        except ValueError:
            idx2 = 1000 # no match, push to the end
        return cmp(idx1, idx2)
      # Sort the fields
      # Re-generate fields_map for use within the ticket template
      field_types = ['summary', 'reporter', 'description',] + field_types  #< Inject the hard coded fields
      fields_map = {}
      for i in xrange(0, len(fields)):
          fields_map[fields[i]['name']] = i
  3. Restart tracd (or restart the web server if WSGI, uWSGI, etc.)