Please note that these Trac pages are no longer being updated. Wiki contents/documentation have moved to GitHub.

Version 40 (modified by gpress, 7 years ago)

Django Template example

Web Code Style Guidelines for the Seattle project

This guide explains how to format code for the Seattle project that implements functionality exposed to the web. This guide should be seen as complementary to the general code style guidelines, so please read that document thoroughly before you continue with the content below. Please let Ivan know if you have suggestions on ways to improve this page.



This guide contains general rules of thumbs, as well as instructions on how to format specific types of web files used by Seattle. This guide is expected to evolve, and should not be considered complete.


Django applications


Django code is written in Python, and falls under the purview of Seattle CodingStyle guidelines. However, Django is complex enough to warrant a few special cases.


Django views


Views are python functions which take a web request and return a web response. These responses can be anything from redirects to 404 errors. All of the Clearinghouse web pages are defined in views.py as well as all of the Django variables they use. All web pages must be defined in views.py and also mapped to a URL in the urls.py file.

Decorators must be explained. Always. A Decorator is the "@whatever" before a views.py function.

  • Django makes use of decorators to simplify complex functions. Each use of a decorator must be explained in the <Note> section of the function's docstring. Example:
@login_required()
def donations(request,share_form=None):
    """
    <Purpose>
    ...

    <Note>
        This method requires the request to represent a valid logged
        in user. See the top-level comment about the @login_required()
        decorator to achieve this property.
    """


Django models


It critical to thoroughly document each class member and function in model Classes
  • Django model classes define the interface to the database.
  • Models naturally document the database schema

  • Django uses models to automatically generates the database schema
Formatting Django model classes
  • In general, each class member will need at least a single commented line of explanation. Example:
    # date this donation was added to the db, auto added to new instances saved
    date_added = models.DateTimeField("Date host added", auto_now_add=True)
    # date we last heard from this machine, this field will be updated
    # ** every time the object is saved **
    last_heard = models.DateTimeField("Last time machine responded", auto_now=True)
    # status: "Initializing", etc
    status = models.CharField("Node status", max_length=1024)
    
  • Each model class must define a __unicode__() method, which is used to generated a meaningful string representation of the model. This method is crucial for effective debugging. Example:
    def __unicode__(self):
        return "%s:%s:%d"%(self.user.www_user.username, self.ip, self.port)
    


Django templates


Django templates define a view on data generated by the Django application. Templates are written in a mix of HTML and Django templating language. Because there is no well-defined interface between templates and Django applications. This interface must be explicitly defined and maintained in comments maintained in the template file. It is important to maintain these comments in the template file because the template may be instantiated from different points in Django code, and may be used by different Django applications.

  • a template tag looks like:
       {% if myvariable %}
         //do stuff
       {% endif %}
    

These are used for built in Django code such as if statements, comments, for loops etc. These change based on Django version so be mindful.

  • a template variable looks like:
      {{ myvessels }}
    

These are defined in views.py specifically for each web page.

  • All templates should include a header that defines all the variables expected by the template. Try to be as specific as possible. Here is an example:
    {% comment %}
    <Program>
      myvessels.html
    
    <Author>
      Originally by?:
      Justin Samuel 2009
    
      Modified:
      Gaetano Pressimone Aug 14 2012
      
    <Purpose>
      Django template file for Seattle Clearinghouse's 'My Vessels' page.  The page 
      allows a logged in user to acquire, renew or remove vessels.
    
    <extends>
      control/control_base.html
    
    <Stylesheet>
      myvessels.css
    
    <Scripts>
      myvessels.js
    
    <Template Variables>
      username:
        The currently logged in user.
            
      my_vessels: 
        list of infodicts of the user's currently acquired vessels.
        .node_ip:  last known ip
        .node_port:  last known port
        .vessel_id:  vessel name
        .node_id:  identifier for the node that the vessel is on
        .handle:  node id + ":" + vessel name
        .is_active:  whether the node is active
        .expires_in_seconds: expiration time, in seconds, for the vessel
    
      num_vessels: 
        Length of my_vessels list.
    
      sh_vessels: 
        List of shared vessels that are used by other but which belong to this user.
    
      get_form:
        The form to acquire vessels.  See forms.py for more info.
        .num: number of acquireable vessels.
        .env: enviromental variables example WAN, LAN, NAT, Random
    
      action_summary: 
        Generic error message.
    {% endcomment %}
    


CSS/HTML/JavaScript overview


Prefer CSS to HTML tags
  • When both HTML and CSS offer ways to do the same thing, use CSS.

  • CSS is easy to manage, change, and evolve. HTML is messy and terrible to maintain.
Relative positioning
  • In almost all cases you should use relative positioning on all Seattle web-pages. This means that try to avoid position: absolute in all cases. Use margin-top, margin-right, margin-bottom, margin-left properties instead.
Separate logical portions of your CSS/HTML into sections/subsections
  • Use as many sections and comments as you need to achieve a granularity that will make it easier for someone else to understand your code.
Avoid redundancy
  • Factor out common code into a separate file
  • Use Django includes to include repeating HTML code (e.g. the site banner)
For IE hacks employ CSS solutions, not JavaScript conditionals
  • Use the !important property for CSS hacks dealing with IE. Normally in CSS whichever rule is specified last takes precedence. However if you use !important after a command then this CSS command will take precedence regardless of what appears after it. This is true for all browsers except IE, making it a valuable method for adding IE-specific CSS to your codebase. An example of this would be:
    margin-top: 3.5em !important;
    margin-top: 2em;
    

So, the top margin will be set to 3.5em for all browsers except in IE, which will have a top margin set to 2em. This can come in useful when using relative margins (such as in this example) as relative margins are displayed slightly differently between IE and other browsers. For more information see  this article.

Define elements styles in CSS, not JavaScript
  • Yes
    /* in JavaScript */
    var staticvessel = document.createElement("span");
    staticvessel.id = "staticvessel";
    $("staticvessel").addClassName("staticvessel");
    
    /* in CSS */
    .staticvessel {
       display: inline-block;
       width: 192px;
       height: 172px;
       textAlign: center;
    }
    
  • No
    /* in JavaScript */
    var staticvessel = document.createElement("span");
    staticvessel.id = "staticvessel";
    staticvessel.style.display = "inline-block";
    staticvessel.style.width = "192px";
    staticvessel.style.height = "172px";
    staticvessel.style.textAlign = "center";
    


CSS Workflow


Keep containers to a minimum
  • Save your document from structural bloat.
  • Take advantage of the many structural elements to achieve layout. Do not add more div’s. Consider all options before adding additional wrappers (div’s) to achieve an effect when using a little nifty CSS can get you that same desired effect.”
Keep properties to a minimum
  • If there isn’t a point to adding a CSS property, don’t add it.
  • If you’re not sure why you’re adding a CSS property, don’t add it.
  • If you feel like you’ve added the same property in lots of places, figure out how to add it in only one place.
Keep selectors to a minimum
  • Using less selectors will mean less selectors will be needed to override any particular style — that means it’s easier to troubleshoot.
Keep CSS hacks to a minimum
  • Don’t use hacks unless its a known and documented bug.


CSS code layout


Use separate files for each aspect of the site
  • Use good judgment -- too many files make it difficult to reconstruct the full picture. For example fonts, colors, and layout can be kept in separate files but do not do this for every visual/stylistic feature of the site.
  • Each CSS file should have a comment header that has the following structure:
    /*****************************************************************
    <File Name>
      documentation.css
    
    <Started>
      December 15, 2008
    
    <Author>
      ivan@cs.washington.edu
      Ivan Beschastnikh
    
    <Purpose>
      Provides a printer-friendly documentation page
    
      Uses a hack to get IE6 fit paragraphs within div margins,
      and a hack to have IE7 display the print buttons correctly
      at the bottom of the page.
    
      As of January, 2008, this CSS file is being converted into a
      more generic style to provide printer-friendly support for other
      pages on the site.
    *****************************************************************/
    
Structure a page's CSS file in the order of XHTML elements on the page
  • If you have five divs in a row with ids "head", "navigation", "footer" then your CSS must include at least three sections.
Separate top-level sections
  • Use comments that name the section and include any explanation that is necessary to understand the context around how the CSS is used:
    /***********************
    * NAVIGATION
    * List-based navigation with JavaScript support to show\hide appropriate list elements when clicked.
    ************************/
    
  • Create sub-sections within the larger sections to create smaller blocks of related code. Use the following comment block for sub-sections:
    /*********** Right most div with installers ***********/
    
Place all custom classes at the end of file
  • Classes that can be applied to more than one section should be in a separate section of their own at the end of the file:
    /***********************
    * CUSTOM CLASSES
    ************************/
    .red{color:FF0000;}
    .left_align{float:left;}
    


CSS rules of thumb


Naming conventions for ids and classes
  • Names should be in all lower case, words separated with underscores:

Yes:

#footer_elems ul li a {...}

No:

#FooterElems ul li a {...}
Use CSS Constants
  • Create definitions at the top of your CSS file in comments, to define ‘constants’. A common use for this is to create a ‘color glossary’. This gives you a reference to the colors used on the site to avoid using alternates by mistake and, if you need to change the colors, you have a quick list to go down and do a search and replace. Example:
    /***********************
    * CSS CONSTANTS
    ************************
    Dark grey (text): #333333
    Dark Blue (headings, links) #000066
    Mid Blue (header) #333399
    Light blue (top navigation) #CCCCFF
    Mid grey: #666666
    */
    
Main DIV must be used for all page content
  • This makes complex changes in the future trivial to make implement
Reset the default browser styles
  • Different browsers render pages with different default settings. This can lead to numerous problems. For example, if you get rid of default margins/paddings across all browsers and your margins and paddings will render the same across all of them. Here is example reset code you may use:
    /*******************
    * RESET
    ********************/
    * { 
       margin:0;
       padding:0;
    }
    table {
       border-collapse:collapse;
       border-spacing:0;
    }
    fieldset,img { 
       border:0;
    }
    address,caption,cite,code,dfn,em,strong,th,var {
       font-style:normal;
       font-weight:normal;
    }
    ol,ul {
       list-style:none;
    }
    caption,th {
       text-align:left;
    }
    h1,h2,h3,h4,h5,h6 {
       font-size:100%;
       font-weight:normal;
    }
    q:before,q:after {
       content:'';
    }
    abbr,acronym {
       border:0;
    }
    
Browser-specific hacks must be well commented
  • Explain exactly the problem the code solves or provide a link to an article that documents the problem (e.g.  IE box model bug)
  • Explain where you found your solution and how it works.
  • Remember that a cryptic hack is the worst kind of hack.
Group related CSS properties
  • Positioning properties go together font properties go together, etc
  • Separate groups of properties with blank lines

  • Makes it easier to find and update related properties:
    body {  
        background: #fdfdfd;
        color: #333;
    
        font-size: 1em;  
        font-color: blue;
    
        line-height: 1.4;  
        line-width: 2.0;
          
        padding: 0;
        margin: 1.0px;
    }  
    
Whenever you make a change to an existing file
  • Indent the change

  • Comment the change with your name, date, and explanation of what you were trying to solve. Here's an example:
    #sidebar ul li a {
       display: block;
       background-color: #ccc;
          border-bottom: 1px solid #999; /* ADDED Apr. 9, 2008 */
       margin: 3px 0 3px 0;
          padding: 3px;  /* CHANGED Feb. 14, 2008 (Prev. 1px) */
    }
    


HTML specifics


Validation
  • Your HTML code should follow valid XHTML syntax
Formatting
  • Keep all HTML lines less than 80 characters long to improve readability.
  • Always indent nested tags, and use 2 spaces for indentation.
  • Always declare the DOCTYPE
  • Head section needs to be minimal and include the following:
    • Title is set
    • Character set is included
    • Stylesheets are linked
    • Scripts are linked
  • Common content across pages must be included, not copied. Django provides simple templates to make this possible.
  • Use proper ending tags -- do not ignore them, even if the page renders correctly; and close all tags (e.g. <img .. />.
  • Paragraphs elements should format text, use lists and labels if possible.
  • Use comments around logical blocks of HTML to improve navigation.


JavaScript specifics


Always keep javascript separate from HTML
  • Create separate files to hold a page's javascript

Minimize use of global variables

Naming conventions
  • Variable and function names are in all lower-case.
  • Class names begin with a capital letter.
  • Underscores separate words in variable/function/class names.
  • Constant variables should be in all caps.
  • Global variables should start with g_
Use comment blocks similar to DocStrings illustrated in the coding style guide
  • At the top of the .js file include the same style header as used for CSS files (see above)
  • The first few lines of a javascript function should describe the details of the function, as follows:
    /*****************************************************************
    function animate(delay) {
      <Purpose>
        Animates the drop-down menu by displaying each successive element with a small delay
      <Arguments>
        delay:
               The delay to use between elements
      <Side Effects>
        None.
      <Returns>
        None.
    *****************************************************************/
    
  • Classes should have a similar description in their first few lines:
    /*****************************************************************
    function Proxy(server_ip, server_port) {
      <Purpose>
        Acts as a message proxy between the js client and the django server.
      <Side Effects>
        Modifies the page's table with new server data as it arrives.
      <Example Use>
        /* create the proxy */
        p = new proxy();
        /* send the server a 'ready' message */
        p.send("ready");
        /* receive server messages */
        p.receive();
    *****************************************************************/
    


See Also


There are numerous other resources for learning about effective style guidelines for coding in CSS\HTML and for web-programming more generally. Here are a few links: