Monthly Archives: December 2016

NG-BE Conf and the Angular Community <3

By Juri Strumpflohner

I was lucky enough to be part of the Belgium’s first Angular conference: NG-BE conf. It was by far the best conference I’ve attended so far! So here’s a quick recap and a official message to you why should definitely attend the 2017 edition :wink:.

Source:: <a href=http://feedproxy.google.com/~r/juristrumpflohner/~3/w2znRL6OFsI/ target="_blank" title="NG-BE Conf and the Angular Community juristr.com

Testing Angular Directives with Custom Matchers

pic9

A few weeks ago, Pascal Precht wrote a blog article on
Testing Services with HTTP with Angular.
In this article, we want to discuss a more advanced topics on DRY Angular testing techniques
using Custom Matchers and Special Helpers.

These are techniques to make your unit-tests incredibly easy to read and to maintain. And to achieve
our learning goals, there are three (3) important testing topics that we want to cover:

  • Testing custom Angular Directives
  • Building reusable, DRY TestBed Helper methods
  • Using Typescript Jasmine Custom Matchers

These techniques are practically undocumented… yet they dramatically improve the quality of
our tests.

To whet your appetite, here are some sample DRY tests that we will be showing you how to write:

Testing Nested DOM Styles

Background

There a several excellent resources already available that developers can read to
learn about Angular testing:

The biggest take-aways from these articles is the singular concept that instead of manually
instantiating and testing classes, Angular developers should consider using
the TestBed.configureTestingModule() to prepare an entire test Angular DI environment for each
test module (*.spec.ts).

We would not use TestBed.configureTestingModule() when we are testing a service that
doesn’t have any dependencies. It’d be easier and less verbose to just instantiate using new. The
TestBed is for useful for dependencies and injections.

Traditional Approach:

Consider the traditional approach of manual construction:

import { ServiceA } from './services/ServiceA';

describe('ServiceA', () => {
  it('should emit greeting event', () => {
    let inst = new ServiceA();
    inst.greeting.subscribe(g => {
       expect(g).toEqual({greeting:'hello'});
    });
    inst.sayHello();
  });
});

Note that it’s fine to do it this way, because ServiceA obviously does not need anything
else to be instantiated; it is a self-contained service without external dependencies. So assuming
that this service won’t get any dependencies in the future, this test is the one we want to write.

Angular Approach:

The Angular TestBed allows developers to configure ngModules that provide instances/values and use
Dependency Injection. This is the same approach developers use in their regular Angular applications.

With the TestBed and its support for for component-lifecycle features, Angular components can be
easily instantiated and tested.

import { MyComponent } from './viewer/MyComponent';

/**
 * Configure testbed to register components and prepare services
 */
beforeEach(() => {
  TestBed.configureTestingModule({
    imports: [ FlexLayoutModule.forRoot() ],
    declarations: [MyComponent],
    
    // 'MatchMedia' construction requires BreakPointRegistry
    // 'MyComponent' construction requires MatchMedia parameter
    
    providers: [
      BreakPointRegistry,
      BreakPointsProvider,
      {
        provide: MatchMedia,
        useClass: MockMatchMedia
      }
    ]
  })
});

/**
 * Helper function to easily build a component Fixture using the specified template
 */
function createTestComponent(template: string): ComponentFixture<Type<any>>
{
  return TestBed
    .overrideComponent(MyComponent, {set: {template: template}} )
    .createComponent(MyComponent);
}

Before each test, we want configure a new, fresh testing module with only the providers,
components, and directives we need for the current test module.

And notice that we just created a reusable Helper function: createTestComponent().
This cool utility function will construct an instance of MyComponent [using the configured TestBed]
using any custom HTML template you specify.

At first, this complexity may seem like overkill. But let’s consider two critical requirements
shown in the sample above:

  • MatchMedia instantiation requires an injected BreakPointRegistry instance
  • MyComponent instantiation requires an injected MatchMedia instance

Even with these requirements, testing developers should NOT have to worry about all those internals just
to test MyComponent. Using ngModule, DI, and Angular… we now don’t have to worry about those
details.

This is just like those real-world scenarios where our components, directives, and services will
have complex dependencies upon providers and non-trivial construction processes.

And this is where TestBed demonstrates its real value!

We are not using external templates nor any other resources or services that are asynchronous.
So we do not discuss the async() nor the the TestBed::compileComponents() functions.

1) Testing Angular Directives

With relative ease, developers can find literature on testing Angular Services and Components.
Yet the How-to’s for testing Directives is oddly not well documented.

Unlike Components with their associated templates, Directives do not have templates. This means
that we cannot simply import a Directive and manually instantiate it.

The solution is rather easy! We only need to:

  • configure a TestBed that imports and declares the directive(s),
  • prepare a shell test Component, and
  • use a custom template which uses the Directive selector(s) as attribute(s).

Since Directives usually affect the host element, our tests will check if those changes to the host
element are present and valid.

Testing the fxLayout Directive

So let’s use the Angular Flex-Layout library as the basis
for the following discussions on Directives, Matchers, and TestBed Helpers.

Real-world solutions often provide great examples for reusable techniques.

We will be using both the fxLayout directive and excerpts from the unit test for that directive
to explore testing ideas, techniques, and solutions that we can also use in our own tests.

First, let’s import the FlexLayout library into our own tests and prepare to test the fxLayout
directive.

You can see the actual testing code in layout.spec.ts.

But don’t jump there yet! Wait until you have finished reading this article.

Configuring the TestBed, Component Shell, and Helpers

Very similar to the TestBed sample shown above, we will configure a testing module but we will
not import an external test component. My test component TestLayoutComponent is itself defined
within our test (*.spec.ts) module.

Using an internal test component enables each test module
e.g.
.spec.ts
to define
and use its own custom test component with custom properties.

Here is the initial configuration:

import {Component, OnInit} from '@angular/core';
import {ComponentFixture, TestBed } from '@angular/core/testing';
import {
  FlexLayoutModule,
  MockMatchMedia,
  MatchMedia,
  BreakPointsProvider,
  BreakPointRegistry
} from '@angular/flex-layout';

describe('layout directive', () => {

  beforeEach(() => {

    // Configure testbed to prepare services
    TestBed.configureTestingModule({
      imports: [FlexLayoutModule.forRoot()],
      declarations: [TestLayoutComponent],
      providers: [
        BreakPointRegistry, BreakPointsProvider,
        {provide: MatchMedia, useClass: MockMatchMedia}
      ]
    })
  });

  it('should add correct styles for default `fxLayout` usage', () => {
			// TEST LOGIC HERE
  });

});

/*
 * Shell component with property 'direction' that will be used
 * with our tests
 */
@Component({
  selector: 'test-layout',
  template: `<span>PlaceHolder HTML to be Replaced</span>`
})
export class TestLayoutComponent implements OnInit {
  direction = "column";
  constructor() {   }
  ngOnInit() {   }
}

/*
 * Custom Helper function to quickly create a `fixture` instance based on
 * the 'TestLayoutComponent' class
 */
function createTestComponent(template: string): ComponentFixture<TestLayoutComponent>
{
  return TestBed
    .overrideComponent(TestLayoutComponent, {set: {template: template}} )
    .createComponent(TestLayoutComponent);
}

We now have everything we need to write a Directive test quickly.

it('should compile with custom directives', () => {
  let fixture = createTestComponent(`<div fxLayout></div>`);
  expect( fixture ).toBeDefined();
});

Wow! That is pretty easy.

The component has been constructed and prepared with the same
processes and DI that your real world application will use.

2) Using DRY Helper Methods

Let’s first write our test using the traditional long-form… one without custom matchers and the
more advanced helper methods.

Since the fxLayout directive will add custom flexbox CSS to the host element, our test logic
here will confirm that the initial CSS is correctly assigned.

Test Directive Logic: Long-Form

The traditional approach would probably implement something like this:

it('should add correct styles for `fxLayout` with template bindings', () => {
  let template = '<div [fxLayout]="direction"></div>';
  let fixture = createTestComponent(template);
  let el = fixture.debugElement.children[0].nativeElement;
  
    fixture.detectChanges();
    
  expect( el.style['display'] ).toBe('flex');
  expect( el.style['box-sizing'] ).toBe('border-box');
  expect( el.style['flex-direction'] ).toBe('column');
 
    fixture.componentInstance.direction = 'row';
    fixture.detectChanges();
    
  expect( el.style['flex-direction'] ).toBe('row'); 
});

In the code above, we

  • defined a custom template with bindings to the component property direction,
  • use deeply nested references to get access to the native element,
  • test each style individually.

All this in one (1) single test. And truly it is not easily read.

Now imagine that our test module has more than 20 individual it(...) tests!

That would be a lot of duplicate code. And there is certainly nothing DRY (“do not repeat yourself”) about
such code!

Test Directive Logic: Short-Form

Here is the DRY version that we want:

Testing Directives - DRY Code

Now this test is much more readable, maintainable, and DRY. All the complexities of

  • forcing change detection,
  • accessing the native element, and
  • confirming 1…n DOM CSS styles

is now easily encapsulated in a Helper function and a Custom Matcher (respectively).

The custom Helper function expectNativeEl( ) is similar to the standard expect( ) function.
In fact, it is wrapper function that internalizes the expect( ) call.

/**
 * Note: this helper only accesses the 1st-level child within a component
 *       A different helper method is need to access deep-level DOM nodes
 */
export function expectNativeEl(fixture: ComponentFixture<any>): any {
  fixture.detectChanges();

  // Return response of `expect(...)`
  return expect(fixture.debugElement.children[0].nativeElement);
}

It is important to note that these helper methods always return the value of an expect(...) call!

And the resulting code change uses a similar notation to our standard training. So

expect(...).toBe

becomes

expectNativeEl(...).toBe

Testing Complex, Nested DOM

For more complex DOM access, we can use the DebugElement’s query feature to select nested DOM nodes.

Angular’s DebugElement has several query features:

  • query(predicate: Predicate): DebugElement;
  • queryAll(predicate: Predicate): DebugElement[];
  • queryAllNodes(predicate: Predicate): DebugNode[];

Please note that all debugging apis are currently experimental.

Consider the following helper function expectDomForQuery( ):

pic6

In this example, we actually want to test the nested DOM node that hosts the attribute fxFlex.
Using another helper method expectDomForQuery( ) makes that easy.

/**
 * Create component instance using custom template, the query for the native DOM node
 * based on the query selector
 */
function expectDomForQuery(template:string, selector:string) : any {
  let fixture = createTestComponent(template);
      fixture.detectChanges();

  // Return response of `expect(...)`
  return expect( queryFor(fixture,selector).nativeElement );
};

/**
 * Don't forget to import the `By` utilities
 */
import {By} from '@angular/platform-browser';

/**
 * Reusable Query helper function
 */
function  queryFor(fixture:ComponentFixture<any>, selector:string):any {
  return fixture.debugElement.query(By.css(selector))
}

And the resulting code change is again a similar notation to our standard training:

expect(...).toBe

becomes

expectDomForQuery(...).toBe

More Special Helpers

Earlier, we showed a code snapshot that had a special helper activateMediaQuery( ):

The Flex-Layout library has a responsive engine that supports change detection when a mediaQuery
activates (aka when the viewport size changes). The API uses selectors with dot-notation to
indicate which values should be used for which mediaQuery:

<div fxLayout="row" fxLayout.md="column"></div>

Testing these features presents several additional requirements:

  • mock the window API window.matchMedia(...)
  • simulate a mediaQuery activation
  • trigger fixture.detectChange() after a simulated activation
  • hide all these details from indvidual tests (DRY)

Thankfully, the Flex-Layout library actually publishes a MockMatchMedia class; which we used in our
TestBed configuration:

let fixture: ComponentFixture<any>;

/**
 * Special Helper
 */
const activateMediaQuery = (alias) => {
  let injector = fixture.debugElement.injector;
  let matchMedia : MockMatchMedia = injector.get(MatchMedia);
  
  // simulate mediaQuery change and trigger fxLayout changes
  matchMedia.activate(alias);
};

beforeEach(() => {
  // Configure testbed to prepare services
  TestBed.configureTestingModule({
    imports: [FlexLayoutModule.forRoot()],
    declarations: [TestLayoutComponent],
    providers: [
      BreakPointRegistry, BreakPointsProvider,
      {provide: MatchMedia, useClass: MockMatchMedia}   //Special mock config
    ]
  })
});

Let’s explore three (3) very interesting things are happening in this code:

  • override DI providers, and
  • dynamic injection using injector.get(MatchMedia)
  • use special helper activateMediaQuery( ) function that hides all these details

(1) Overriding DI Providers:

{ provide: MatchMedia, useClass: MockMatchMedia }

tells the TestBed DI system to provide an instance of the MockMatchMedia whenever any code
asks for an instance of the MatchMedia token to be injected via DI.

You can read more about the Angular DI systems here:
Dependency Injection in Angular

(2) Dynamic Injection

Our special helper activateMediaQuery() needs a dynamic injected instance of the MatchMedia token.
Using the fixture instance, we can dynamically get a MockMatchMedia instance from our fixtures
injector.

Notice that all this complexity [and construction details] is encapsulated in our TestBed and special
helper… and the individual tests simply make the easy call:

activateMediayQuery('md');

That is very, very cool!

Custom Matchers

We have only one more tool [in our testing toolkit] to discuss: Custom Jasmine Matchers.

For those developers not familiar with the concepts of Jasmine matchers, we recommend the online
Jasmine documentation:


pic9

Remember that matchers are used after the expect() call and should encapsulate complex logic
and reduce code-clutter in our test code.

This allows our test(s) to remain terse, concise, readable, maintainable, and DRY.

And we should always give our custom matcher functions clear, readable names. E.g. toHaveCssStyles().

Building a TypeScript Matcher

Similar to expect(...).toBeTruthy(), we want a custom matcher toHaveCSSStyle( ):

expectNativeEl(fixture).toHaveCssStyle({
  'display': 'flex',
  'flex-direction': 'row',
  'box-sizing': 'border-box'
});

Creating a matcher in JavaScript is documented on the Jasmine site. Our challenge is the harder
goal of creating a custom matcher implemented in TypeScript using well-defined types.

  • we need to enhance the expect() API, and
  • we need to implement custom matchers.

The global Jasmine expect() method normally returns value. To use custom matchers
(with types), we want the expect( ) function to support returning either a standard matcher or
a custom matcher.

Here is a teaser that shows how that is done:

export const expect: (actual: any) => NgMatchers = <any> _global.expect;

export interface NgMatchers extends jasmine.Matchers { /* ... */ };

We assigned the global expect function reference to a new export that states that expect() calls
now return references to a NgMatchers interface.

Here are the full implementation details of our custom-matchers.ts module:

declare var global: any;
const _global = <any>(typeof window === 'undefined' ? global : window);

/**
 * Extend the API to support chaining with custom matchers
 */
export const expect: (actual: any) => NgMatchers = <any> _global.expect;

/**
 * Jasmine matchers that support checking custom CSS conditions.
 * !! important to add your custom matcher to the interface
 */
export interface NgMatchers extends jasmine.Matchers {
  toHaveCssStyle(expected: {[k: string]: string}|string): boolean;
  not: NgMatchers;
}

/**
 * Implementation of 1...n custom matchers
 */
export const customMatchers: jasmine.CustomMatcherFactories = {
  // Here is our custom matcher; cloned from @angular/core
  toHaveCssStyle: function () {
    return {
      compare: function (actual: any, styles: {[k: string]: string}|string) {
        let allPassed: boolean;
        if (typeof styles === 'string') {
          allPassed = getDOM().hasStyle(actual, styles);
        } else {
          allPassed = Object.keys(styles).length !== 0;
          Object.keys(styles).forEach(prop => {
            allPassed = allPassed && getDOM().hasStyle(actual, prop, styles[prop]);
          });
        }

        return {
          pass: allPassed,
          get message() {
            const expectedValueStr = typeof styles === 'string' ? styles : JSON.stringify(styles);
            return `Expected ${actual.outerHTML} ${!allPassed ? ' ' : 'not '}to contain the
                      CSS ${typeof styles === 'string' ? 'property' : 'styles'} "${expectedValueStr}"`;
          }
        };
      }
    };
  }

};

With the above definitions, we can now use expect(...).toHaveCssStyles(...) without any
TypeScript complaints.

Wait!

We need one to discuss one more addition to our custom-matcher code. Did you notice the call to
getDOM().hasStyle() ? But where does getDOM come from?

After some inspection of the @angular/core code, we were able to
get a reference to the special Angular DOM Adapter:

import {__platform_browser_private__} from '@angular/platform-browser';
const getDOM = __platform_browser_private__.getDOM;

Please note that the getDOM() is a private Angular API and may change in the future.

Using a Custom Matcher

Now we are golden with features. Let’s import and use our custom Jasmine matcher.

import {customMatchers} from '../utils/testing/custom-matchers';

describe('layout directive', () => {

  beforeEach(() => {
    jasmine.addMatchers(customMatchers);

    // TestBed stuff here...
  });

});

Notice that we must register the custom matchers in a beforeEach() call to configure the
matchers for each subsequent test. And now everything is ready for the individual tests:

expect(...).toHaveCssStyle({
  'display': 'flex',
  'flex-direction': 'row',
  'box-sizing': 'border-box'
});

When to use Protractor + e2e

It should be noted that the above sample tests confirm whether CSS styles have been applied
correctly to the DOM element. Unit tests perform tests logic and state… but those same
tests cannot easily test how those values affect renderings in the UI.

Jasmine unit tests do not test whether the CSS styles or states render the elements in the
browser as expected. Nor do they test renderings across different browsers. Those types of visual
tests are best performed in e2e testing with Protractor and visual differencing tools.

Summary

Perhaps you will say: “Wow, this is cool… but totally overkill!” If you are tempted to say that,
then look at all the DRY tests here:
layout.spec.ts.
You will quickly see the value of using helpers and custom matchers.

You now have the techniques and tools to create your own custom matchers and deliver quality, terse
unit tests.

Enjoy!

Resources

The Flex-Layout Helper functions are actually partial applications (function currying). Here is
How to use them.

Source:: Thoughtram

Build a CRUD Web App With Python and Flask – Part Two

By mbithenzomo

WpdVgxSwRDqDEaHABrx6_flask-crud-part-two.jpg

This is Part Two of a three-part tutorial to build an employee management web app, named Project Dream Team. In Part One of the tutorial, we set up a MySQL database using MySQL-Python and Flask-SQLAlchemy. We created models, migrated the database, and worked on the home and auth blueprints and templates. By the end of Part One, we had a working app that had a homepage, registration page, login page, and dashboard. We could register a new user, login, and logout.

Here’s part one: https://scotch.io/tutorials/build-a-crud-web-app-with-python-and-flask-part-one

In Part Two, we will work on:

  1. Creating an admin user and admin dashboard
  2. Creating, listing, editing and deleting departments
  3. Creating, listing, editing and deleting roles
  4. Assigning departments and roles to employees

Admin User

We’ll start by creating an admin user through the command line. Flask provides a handy command, flask shell, that allows us to use an interactive Python shell for use with Flask apps.

$ flask shell
>>> from app.models import Employee
>>> from app import db
>>> admin = Employee(email="admin@admin.com",username="admin",password="admin2016",is_admin=True)
>>> db.session.add(admin)
>>> db.session.commit()

We’ve just created a user with a username, admin, and a password, admin2016. Recall that we set the is_admin field to default to False in the Employee model. To create the admin user above, we override the default value of is_admin and set it to True.

Admin Dashboard

Now that we have an admin user, we need to add a view for an admin dashboard. We also need to ensure that once the admin user logs in, they are redirected to the admin dashboard and not the one for non-admin users. We will do this in the home blueprint.

# app/home/views.py

# update imports
from flask import abort, render_template
from flask_login import current_user, login_required

# add admin dashboard view
@home.route('/admin/dashboard')
@login_required
def admin_dashboard():
    # prevent non-admins from accessing the page
    if not current_user.is_admin:
        abort(403)

    return render_template('home/admin_dashboard.html', title="Dashboard")
# app/auth/views.py

# Edit the login view to redirect to the admin dashboard if employee is an admin

@auth.route('/login', methods=['GET', 'POST'])
def login():
    form = LoginForm()
    if form.validate_on_submit():

        # check whether employee exists in the database and whether
        # the password entered matches the password in the database
        employee = Employee.query.filter_by(email=form.email.data).first()
        if employee is not None and employee.verify_password(
                form.password.data):
            # log employee in
            login_user(employee)

            # redirect to the appropriate dashboard page
            if employee.is_admin:
                return redirect(url_for('home.admin_dashboard'))
            else:
                return redirect(url_for('home.dashboard'))

        # when login details are incorrect
        else:
            flash('Invalid email or password.')

    # load login template
    return render_template('auth/login.html', form=form, title='Login')

Next we’ll create the admin dashboard template. Create an admin_dashboard.html file in the templates/home directory, and then add the following code in it:

<!-- app/templates/home/admin_dashboard.html -->

{% extends "base.html" %}
{% block title %}Admin Dashboard{% endblock %}
{% block body %}
<div class="intro-header">
    <div class="container">
        <div class="row">
            <div class="col-lg-12">
                <div class="intro-message">
                    <h1>Admin Dashboard</h1>
                    <h3>For administrators only!</h3>
                    <hr class="intro-divider">
                    </ul>
                </div>
            </div>
        </div>
    </div>
</div>
{% endblock %}

Now we need to edit the base template to show a different menu for the admin user.

<!-- app/templates/base.html -->

<!-- Modify nav bar menu -->
<ul class="nav navbar-nav navbar-right">
    {% if current_user.is_authenticated %}
      {% if current_user.is_admin %}
        <li><a href="{{ url_for('home.admin_dashboard') }}">Dashboard</a></li>
        <li><a href="#">Departments</a></li>
        <li><a href="#">Roles</a></li>
        <li><a href="#">Employees</a></li>
      {% else %}
        <li><a href="{{ url_for('home.dashboard') }}">Dashboard</a></li>
      {% endif %}
      <li><a href="{{ url_for('auth.logout') }}">Logout</a></li>
      <li><a><i class="fa fa-user"></i>  Hi, {{ current_user.username }}!</a></li>
    {% else %}
      <li><a href="{{ url_for('home.homepage') }}">Home</a></li>
      <li><a href="{{ url_for('auth.register') }}">Register</a></li>
      <li><a href="{{ url_for('auth.login') }}">Login</a></li>
    {% endif %}
</ul>

In the menu above, we make use of the current_user proxy from Flask-Login to check whether the current user is an admin. If they are, we display the admin menu which will allow them to navigate to the Departments, Roles and Employees pages. Notice that we use # for the links in the admin menu. We will update this after we have created the respective views.

Now run the app and login as the admin user that we just created. You should see the admin dashboard:

Let’s test the error we set in the home/views.py file to prevent non-admin users from accessing the admin dashboard. Log out and then log in as a regular user. In your browser’s address bar, manually enter the following URL: http://127.0.0.1:5000/admin/dashboard. You should get a 403 Forbidden error. It looks pretty boring now, but don’t worry, we’ll create custom error pages in Part Three!

Departments

Now we’ll start working on the admin blueprint, which has the bulk of the functionality in the application. We’ll begin by building out CRUD functionality for the departments.

Forms

We’ll start with the admin/forms.py file, where we’ll create a form to add and edit departments.

# app/admin/forms.py

from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField
from wtforms.validators import DataRequired

class DepartmentForm(FlaskForm):
    """
    Form for admin to add or edit a department
    """
    name = StringField('Name', validators=[DataRequired()])
    description = StringField('Description', validators=[DataRequired()])
    submit = SubmitField('Submit')

The form is pretty simple and has only two fields, name and department, both of which are required. We enforce this using the DataRequired() validator from WTForms. Note that we will use the same form for adding and editing departments.

Views

Now, let’s work on the views:

# app/admin/views.py

from flask import abort, flash, redirect, render_template, url_for
from flask_login import current_user, login_required

from . import admin
from forms import DepartmentForm
from .. import db
from ..models import Department

def check_admin():
    """
    Prevent non-admins from accessing the page
    """
    if not current_user.is_admin:
        abort(403)

# Department Views

@admin.route('/departments', methods=['GET', 'POST'])
@login_required
def list_departments():
    """
    List all departments
    """
    check_admin()

    departments = Department.query.all()

    return render_template('admin/departments/departments.html',
                           departments=departments, title="Departments")

@admin.route('/departments/add', methods=['GET', 'POST'])
@login_required
def add_department():
    """
    Add a department to the database
    """
    check_admin()

    add_department = True

    form = DepartmentForm()
    if form.validate_on_submit():
        department = Department(name=form.name.data,
                                description=form.description.data)
        try:
            # add department to the database
            db.session.add(department)
            db.session.commit()
            flash('You have successfully added a new department.')
        except:
            # in case department name already exists
            flash('Error: department name already exists.')

        # redirect to departments page
        return redirect(url_for('admin.list_departments'))

    # load department template
    return render_template('admin/departments/department.html', action="Add",
                           add_department=add_department, form=form,
                           title="Add Department")

@admin.route('/departments/edit/<int:id>', methods=['GET', 'POST'])
@login_required
def edit_department(id):
    """
    Edit a department
    """
    check_admin()

    add_department = False

    department = Department.query.get_or_404(id)
    form = DepartmentForm(obj=department)
    if form.validate_on_submit():
        department.name = form.name.data
        department.description = form.description.data
        db.session.commit()
        flash('You have successfully edited the department.')

        # redirect to the departments page
        return redirect(url_for('admin.list_departments'))

    form.description.data = department.description
    form.name.data = department.name
    return render_template('admin/departments/department.html', action="Edit",
                           add_department=add_department, form=form,
                           department=department, title="Edit Department")

@admin.route('/departments/delete/<int:id>', methods=['GET', 'POST'])
@login_required
def delete_department(id):
    """
    Delete a department from the database
    """
    check_admin()

    department = Department.query.get_or_404(id)
    db.session.delete(department)
    db.session.commit()
    flash('You have successfully deleted the department.')

    # redirect to the departments page
    return redirect(url_for('admin.list_departments'))

    return render_template(title="Delete Department")

We begin by creating a function, check_admin, which throws a 403 Forbidden error if a non-admin user attempts to access these views. We will call this function in every admin view.

The list_departments view queries the database for all departments and assigns them to the variable departments, which we will use to list them in the template.

The add_department view creates a new department object using the form data, and adds it to the database. If the department name already exists, an error message is displayed. This view redirects to the list_departments. This means that once the admin user creates a new department, they will be redirected to the Departments page.

The edit_department view takes one parameter: id . This is the department ID, and will be passed to the view in the template. The view queries the database for a department with the ID specified. If the department doesn’t exist, a 404 Not Found error is thrown. If it does, it is updated with the form data.

The delete_department view is similar to the edit_department one, in that it takes a department ID as a parameter and throws an error if the specified department doesn’t exist. If it does, it is deleted from the database.

Note that we render the same template for adding and editing individual departments: department.html. This is why we have the add_department variable in the add_department view (where it is set to True), as well as in the edit_department view (where it is set to False). We’ll use this variable in the department.html template to determine what wording to use for the title and heading.

Templates

Create an templates/admin directory, and in it, add a departments directory. Inside it, add the departments.html and department.html files:

<!-- app/templates/admin/departments/departments.html -->

{% import "bootstrap/utils.html" as utils %}
{% extends "base.html" %}
{% block title %}Departments{% endblock %}
{% block body %}
<div class="content-section">
  <div class="outer">
    <div class="middle">
      <div class="inner">
        <br/>
        {{ utils.flashed_messages() }}
        <br/>
        <h1 style="text-align:center;">Departments</h1>
        {% if departments %}
          <hr class="intro-divider">
          <div class="center">
            <table class="table table-striped table-bordered">
              <thead>
                <tr>
                  <th width="15%"> Name </th>
                  <th width="40%"> Description </th>
                  <th width="15%"> Employee Count </th>
                  <th width="15%"> Edit </th>
                  <th width="15%"> Delete </th>
                </tr>
              </thead>
              <tbody>
              {% for department in departments %}
                <tr>
                  <td> {{ department.name }} </td>
                  <td> {{ department.description }} </td>
                  <td>
                    {% if department.employees %}
                      {{ department.employees.count() }}
                    {% else %}
                      0
                    {% endif %}
                  </td>
                  <td>
                    <a href="{{ url_for('admin.edit_department', id=department.id) }}">
                      <i class="fa fa-pencil"></i> Edit 
                    </a>
                  </td>
                  <td>
                    <a href="{{ url_for('admin.delete_department', id=department.id) }}">
                      <i class="fa fa-trash"></i> Delete 
                    </a>
                  </td>
                </tr>
              {% endfor %}
              </tbody>
            </table>
          </div>
          <div style="text-align: center">
        {% else %}
          <div style="text-align: center">
            <h3> No departments have been added. </h3>
            <hr class="intro-divider">
        {% endif %}
          <a href="{{ url_for('admin.add_department') }}" class="btn btn-default btn-lg">
            <i class="fa fa-plus"></i>
            Add Department
          </a>
        </div>
      </div>
    </div>
  </div>
</div>
{% endblock %}

We’ve created a table in the template above, where we will display all the departments with their name, description, and number of employees. Take note of the count() function, which we use in this case to get the number of employees. Each department listed will have an edit and delete link. Notice how we pass the department.id value to the edit_department and delete_department views in the respective links.

If there are no departments, the page will display “No departments have been added”. There is also a button which can be clicked to add a new department.

Now let’s work on the template for adding and editing departments:

<!-- app/templates/admin/departments/department.html -->

{% import "bootstrap/wtf.html" as wtf %}
{% extends "base.html" %}
{% block title %}
    {% if add_department %}
        Add Department
    {% else %}
        Edit Department
    {% endif %}
{% endblock %}
{% block body %}
<div class="content-section">
 <div class="outer">
    <div class="middle">
      <div class="inner">
        <div class="center">
            {% if add_department %}
                <h1>Add Department</h1>
            {% else %}
                <h1>Edit Department</h1>
            {% endif %}
            <br/>
            {{ wtf.quick_form(form) }}
        </div>
      </div>
    </div>
  </div>
</div>
{% endblock %}

Notice that we use the add_department variable which we initialized in the admin/views.py file, to determine whether the page title will be “Add Department” or “Edit Department”.

Add the following lines to your style.css file:

/* app/static/css/style.css */

.outer {
    display: table;
    position: absolute;
    height: 70%;
    width: 100%;
}

.middle {
    display: table-cell;
    vertical-align: middle;
}

.inner {
    margin-left: auto;
    margin-right: auto;
}

The .middle, .inner, and .outer classes are to center the content in the middle of the page.

Lastly, let’s put the correct link to the Departments page in the admin menu:

<!-- app/templates/base.html -->

<!-- Modify nav bar menu -->
<li><a href="{{ url_for('admin.list_departments') }}">Departments</a></li>

Re-start the flask server, and then log back in as the admin user and click on the Departments link. Because we have not added any departments, loading the page will display:

Let’s try adding a department:

It worked! We get the success message we configured in the add_department view, and can now see the department displayed.

Now let’s edit it:

Notice that the current department name and description are already pre-loaded in the form. Also, take note of the URL, which has the ID of the department we are editing.

Editing the department is successful as well. Clicking the Delete link deletes the department and redirects to the Departments page, where a confirmation message is displayed:

Roles

Now to work on the roles. This will be very similar to the departments code because the functionality for roles and departments is exactly the same.

Forms

We’ll start by creating the form to add and edit roles. Add the following code to the admin/forms.py file:

# app/admin/forms.py

# existing code remains

class RoleForm(FlaskForm):
    """
    Form for admin to add or edit a role
    """
    name = StringField('Name', validators=[DataRequired()])
    description = StringField('Description', validators=[DataRequired()])
    submit = SubmitField('Submit')

Views

Next we’ll write the views to add, list, edit, and delete roles. Add the following code to the admin/views.py file:

# app/admin/views.py

# update imports
from forms import DepartmentForm, RoleForm
from ..models import Department, Role

# existing code remains

# Role Views

@admin.route('/roles')
@login_required
def list_roles():
    check_admin()
    """
    List all roles
    """
    roles = Role.query.all()
    return render_template('admin/roles/roles.html',
                           roles=roles, title='Roles')

@admin.route('/roles/add', methods=['GET', 'POST'])
@login_required
def add_role():
    """
    Add a role to the database
    """
    check_admin()

    add_role = True

    form = RoleForm()
    if form.validate_on_submit():
        role = Role(name=form.name.data,
                    description=form.description.data)

        try:
            # add role to the database
            db.session.add(role)
            db.session.commit()
            flash('You have successfully added a new role.')
        except:
            # in case role name already exists
            flash('Error: role name already exists.')

        # redirect to the roles page
        return redirect(url_for('admin.list_roles'))

    # load role template
    return render_template('admin/roles/role.html', add_role=add_role,
                           form=form, title='Add Role')

@admin.route('/roles/edit/<int:id>', methods=['GET', 'POST'])
@login_required
def edit_role(id):
    """
    Edit a role
    """
    check_admin()

    add_role = False

    role = Role.query.get_or_404(id)
    form = RoleForm(obj=role)
    if form.validate_on_submit():
        role.name = form.name.data
        role.description = form.description.data
        db.session.add(role)
        db.session.commit()
        flash('You have successfully edited the role.')

        # redirect to the roles page
        return redirect(url_for('admin.list_roles'))

    form.description.data = role.description
    form.name.data = role.name
    return render_template('admin/roles/role.html', add_role=add_role,
                           form=form, title="Edit Role")

@admin.route('/roles/delete/<int:id>', methods=['GET', 'POST'])
@login_required
def delete_role(id):
    """
    Delete a role from the database
    """
    check_admin()

    role = Role.query.get_or_404(id)
    db.session.delete(role)
    db.session.commit()
    flash('You have successfully deleted the role.')

    # redirect to the roles page
    return redirect(url_for('admin.list_roles'))

    return render_template(title="Delete Role")

These list, add, edit, and delete views are similar to the ones for departments that we created earlier.

Templates

Create a roles directory in the templates/admin directory. In it, create the roles.html and role.html files:

<!-- app/templates/admin/roles/roles.html -->

{% import "bootstrap/utils.html" as utils %}
{% extends "base.html" %}
{% block title %}Roles{% endblock %}
{% block body %}
<div class="content-section">
  <div class="outer">
    <div class="middle">
      <div class="inner">
        <br/>
        {{ utils.flashed_messages() }}
        <br/>
        <h1 style="text-align:center;">Roles</h1>
        {% if roles %}
          <hr class="intro-divider">
          <div class="center">
            <table class="table table-striped table-bordered">
              <thead>
                <tr>
                  <th width="15%"> Name </th>
                  <th width="40%"> Description </th>
                  <th width="15%"> Employee Count </th>
                  <th width="15%"> Edit </th>
                  <th width="15%"> Delete </th>
                </tr>
              </thead>
              <tbody>
              {% for role in roles %}
                <tr>
                  <td> {{ role.name }} </td>
                  <td> {{ role.description }} </td>
                  <td>
                    {% if role.employees %}
                      {{ role.employees.count() }}
                    {% else %}
                      0
                    {% endif %}
                  </td>
                  <td>
                    <a href="{{ url_for('admin.edit_role', id=role.id) }}">
                      <i class="fa fa-pencil"></i> Edit 
                    </a>
                  </td>
                  <td>
                    <a href="{{ url_for('admin.delete_role', id=role.id) }}">
                      <i class="fa fa-trash"></i> Delete 
                    </a>
                  </td>
                </tr>
              {% endfor %}
              </tbody>
            </table>
          </div>
          <div style="text-align: center">
        {% else %}
          <div style="text-align: center">
            <h3> No roles have been added. </h3>
            <hr class="intro-divider">
        {% endif %}
          <a href="{{ url_for('admin.add_role') }}" class="btn btn-default btn-lg">
            <i class="fa fa-plus"></i>
            Add Role
          </a>
        </div>
      </div>
    </div>
  </div>
</div>
{% endblock %}

Just like we did for the departments, we have created a table where we will display all the roles with their name, description, and number of employees. Each role listed will also have an edit and delete link. If there are no roles, a message of the same will be displayed. There is also a button which can be clicked to add a new role.

<!-- app/templates/admin/roles/role.html -->

{% import "bootstrap/wtf.html" as wtf %}
{% extends "base.html" %}
{% block title %}
    {% if add_department %}
        Add Role
    {% else %}
        Edit Role
    {% endif %}
{% endblock %}
{% block body %}
<div class="content-section">
 <div class="outer">
    <div class="middle">
      <div class="inner">
        <div class="center">
            {% if add_role %}
                <h1>Add Role</h1>
            {% else %}
                <h1>Edit Role</h1>
            {% endif %}
            <br/>
            {{ wtf.quick_form(form) }}
        </div>
      </div>
    </div>
  </div>
</div>
{% endblock %}

We use the add_role variable above the same way we used the add_department variable for the department.html template.

Once again, let’s update the admin menu with the correct link:

<!-- app/templates/base.html -->

<!-- Modify nav bar menu -->
<li><a href="{{ url_for('admin.list_roles') }}">Roles</a></li>

Re-start the server. You should now be able to access the Roles page, and add, edit and delete roles.

Employees

Now to work on listing employees, as well as assigning them departments and roles.

Forms

We’ll need a form to assign each employee a department and role. Add the following to the admin/forms.py file:

# app/admin/forms.py

# update imports
from wtforms.ext.sqlalchemy.fields import QuerySelectField

from ..models import Department, Role

# existing code remains

class EmployeeAssignForm(FlaskForm):
    """
    Form for admin to assign departments and roles to employees
    """
    department = QuerySelectField(query_factory=lambda: Department.query.all(),
                                  get_label="name")
    role = QuerySelectField(query_factory=lambda: Role.query.all(),
                            get_label="name")
    submit = SubmitField('Submit')

We have imported a new field type, QuerySelectField, which we use for both the department and role fields. This will query the database for all departments and roles. The admin user will select one department and one role using the form on the front-end.

Views

Add the following code to the admin/views.py file:

# app/admin/views.py

# update imports
from forms import DepartmentForm, EmployeeAssignForm, RoleForm
from ..models import Department, Employee, Role

# existing code remains

# Employee Views

@admin.route('/employees')
@login_required
def list_employees():
    """
    List all employees
    """
    check_admin()

    employees = Employee.query.all()
    return render_template('admin/employees/employees.html',
                           employees=employees, title='Employees')

@admin.route('/employees/assign/<int:id>', methods=['GET', 'POST'])
@login_required
def assign_employee(id):
    """
    Assign a department and a role to an employee
    """
    check_admin()

    employee = Employee.query.get_or_404(id)

    # prevent admin from being assigned a department or role
    if employee.is_admin:
        abort(403)

    form = EmployeeAssignForm(obj=employee)
    if form.validate_on_submit():
        employee.department = form.department.data
        employee.role = form.role.data
        db.session.add(employee)
        db.session.commit()
        flash('You have successfully assigned a department and role.')

        # redirect to the roles page
        return redirect(url_for('admin.list_employees'))

    return render_template('admin/employees/employee.html',
                           employee=employee, form=form,
                           title='Assign Employee')

The list_employees view queries the database for all employees and assigns them to the variable employees, which we will use to list them in the template.

The assign_employee view takes an employee ID. First, it checks whether the employee is an admin user; if it is, a 403 Forbidden error is thrown. If not, it updates the employee.department and employee.role with the selected data from the form, essentially assigning the employee a new department and role.

Templates

Create a employees directory in the templates/admin directory. In it, create the employees.html and employee.html files:

<!-- app/templates/admin/employees/employees.html -->

{% import "bootstrap/utils.html" as utils %}
{% extends "base.html" %}
{% block title %}Employees{% endblock %}
{% block body %}
<div class="content-section">
  <div class="outer">
    <div class="middle">
      <div class="inner">
        <br/>
        {{ utils.flashed_messages() }}
        <br/>
        <h1 style="text-align:center;">Employees</h1>
        {% if employees %}
          <hr class="intro-divider">
          <div class="center">
            <table class="table table-striped table-bordered">
              <thead>
                <tr>
                  <th width="15%"> Name </th>
                  <th width="30%"> Department </th>
                  <th width="30%"> Role </th>
                  <th width="15%"> Assign </th>
                </tr>
              </thead>
              <tbody>
              {% for employee in employees %}
                {% if employee.is_admin %}
                    <tr style="background-color: #aec251; color: white;">
                        <td> <i class="fa fa-key"></i> Admin </td>
                        <td> N/A </td>
                        <td> N/A </td>
                        <td> N/A </td>
                    </tr>
                {% else %}
                    <tr>
                      <td> {{ employee.first_name }} {{ employee.last_name }} </td>
                      <td>
                        {% if employee.department %}
                          {{ employee.department.name }}
                        {% else %}
                          -
                        {% endif %}
                      </td>
                      <td>
                        {% if employee.role %}
                          {{ employee.role.name }}
                        {% else %}
                          -
                        {% endif %}
                      </td>
                      <td>
                        <a href="{{ url_for('admin.assign_employee', id=employee.id) }}">
                          <i class="fa fa-user-plus"></i> Assign
                        </a>
                      </td>
                    </tr>
                {% endif %}
              {% endfor %}
              </tbody>
            </table>
          </div>
        {% endif %}
        </div>
      </div>
    </div>
  </div>
</div>
{% endblock %}

The employees.html template shows a table of all employees. The table shows their full name, department and role, or displays a - in case no department and role has been assigned. Each employee has an assign link, which the admin user can click to assign them a department and role.

Because the admin user is an employee as well, they will be displayed in the table. However, we have formatted the table such that admin users stand out with a green background and white text.

<!-- app/templates/admin/employees/employee.html -->

{% import "bootstrap/wtf.html" as wtf %}
{% extends "base.html" %}
{% block title %}Assign Employee{% endblock %}
{% block body %}
<div class="content-section">
 <div class="outer">
    <div class="middle">
      <div class="inner">
        <div class="center">
            <h1> Assign Departments and Roles </h1>
            <br/>
            <p>
                Select a department and role to assign to
                <span style="color: #aec251;">
                    {{ employee.first_name }} {{ employee.last_name }}
                </span>
            </p>
            <br/>
            {{ wtf.quick_form(form) }}
        </div>
      </div>
    </div>
  </div>
</div>
{% endblock %}

We need to update the admin menu once more:

<!-- app/templates/base.html -->

<!-- Modify nav bar menu -->
<li><a href="{{ url_for('admin.list_employees') }}">Employees</a></li>

Navigate to the Employees page now. If there are no users other than the admin, this is what you should see:

When there is an employee registered, this is displayed:

Feel free to add a variety of departments and roles so that you can start assigning them to employees.

You can re-assign departments and roles as well.

Conclusion

We now have a completely functional CRUD web app! In Part Two of the tutorial, we’ve been able to create an admin user and an admin dashboard, as well as customise the menu for different types of users. We’ve also built out the core functionality of the app, and can now add, list, edit, and delete departments and roles, as well as assign them to employees. We have also taken security into consideration by protecting certain views from unauthorized access.

In Part Three, we will create custom error pages, write tests, and deploy the app to Heroku.

Source:: scotch.io

Working with Django Templates & Static Files

By amos

rKVKlx7RxKowxgcunwiA_django-templates-and-static-files.png.jpg

In my getting started with Django tutorial, I showed you how to get a Django site up and running. The templates we rendered were very basic though.

This is definitely not how you want your site to look like.

How do you get your site to look better? Simple! Add some styling. In this tutorial, I will show you how to add some CSS and JavaScript to your Django templates in order to make them look much better. To do that, you first need to understand the concept of static files in Django.

Setting up a Django Project

Let’s set up our test Django project. First, create a folder called projects which is where our app will live.

mkdir projects && cd projects

Inside projects, let’s use virtualenv to create an environment for our app’s dependencies.

virtualenv env --python python3

NOTE: If you do not have virtualenv installed, install it using the command pip install virtualenv.

Once that is done, activate the environment by running the activate shell script.

source env/bin/activate

If that command works, you should see an (env) prompt on your terminal.

#(env)~/projects
$

Everything look fine? Awesome! Let’s now use pip to install Django into our environment.

#(env)~/projects
$ pip install django

That command should install Django into your environment. As of the time of writing, the Django version is 1.10.4.

We are then going to call the django-admin script to create our Django app. Let’s do that like this:

#(env)~/projects
$ django-admin startproject djangotemplates

If you check your projects folder structure, you should now have a new folder called djangotemplates created by Django in addition to the earlier env folder we created.

cd into djangotemplates.

Your folder structure should now be similar to this:

djangotemplates
--djangotemplates
----__init__.py
----settings.py
----urls.py
----wsgi.py
--manage.py

All done? You are now ready to begin!

Settings for managing static files

Static files include stuff like CSS, JavaScript and images that you may want to serve alongside your site. Django is very opinionated about how you should include your static files. In this article, I will show how to go about adding static files to a Django application.

Open the settings.py file inside the inner djangotemplates folder. At the very bottom of the file you should see these lines:

# djangotemplates/djangotemplates/settings.py

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.10/howto/static-files/

STATIC_URL = '/static/'

This line tells Django to append static to the base url (in our case localhost:8000) when searching for static files. In Django, you could have a static folder almost anywhere you want. You can even have more than one static folder e.g. one in each app. However, to keep things simple, I will use just one static folder in the root of our project folder. We will create one later. For now, let’s add some lines in the settings.py file so that it looks like this.

# djangotemplates/djangotemplates/settings.py

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.10/howto/static-files/

STATIC_URL = '/static/'

# Add these new lines
STATICFILES_DIRS = (
    os.path.join(BASE_DIR, 'static'),
)

STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')

The STATICFILES_DIRS tuple tells Django where to look for static files that are not tied to a particular app. In this case, we just told Django to also look for static files in a folder called static in our root folder, not just in our apps.

Django also provides a mechanism for collecting static files into one place so that they can be served easily. Using the collectstatic command, Django looks for all static files in your apps and collects them wherever you told it to, i.e. the STATIC_ROOT. In our case, we are telling Django that when we run python manage.py collectstatic, gather all static files into a folder called staticfiles in our project root directory. This feature is very handy for serving static files, especially in production settings.

App setup

Create a folder called static on the same level as the inner djangotemplates folder and the manage.py file. You should now have this structure:

djangotemplates
--djangotemplates
----__init__.py
----settings.py
----urls.py
----wsgi.py
--static
--manage.py

Inside this folder is where we will have any custom CSS and JS we choose to write. On that note, let’s add two folders inside the static folder to hold our files, one called css and the other called js. Inside css, create a file called main.css. Add a main.js in the js folder as well. Your static folder should now look like this:

--static
----css
------main.cs
----js
------main.js

Once that is done, let’s create a new Django app called example that we will be working with. Do you remember how to do that? Don’t worry, it’s quite simple.

#(env)~/projects/djangotemplates
$ python manage.py startapp example

Once that is done, you should have a folder called example alongside djangotemplates and static. And of course you should still be able to see the manage.py file.

djangotemplates
--djangotemplates
----__init__.py
----settings.py
----urls.py
----wsgi.py
--example
--static
--manage.py

We need to tell Django about our new app. Go to the inner djangotemplates folder, open up settings.py and look for INSTALLED_APPS. Add example under the other included apps.

# djangotemplates/djangotemplates/settings.py

DEBUG = True

ALLOWED_HOSTS = []

# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'example', # Add this line
]

Just to recap, we now have the following folder structure:

djangotemplates
--djangotemplates
----__init__.py
----settings.py
----urls.py
----wsgi.py
--example
----migrations
------__init__.py
----admin.py
----apps.py
----models.py
----tests.py
----views.py
--static
----css
------main.cs
----js
------main.js
--manage.py

URL definition

Let’s define a URL to go to our new app. Let’s edit djangotemplates/djangotemplates/urls.py to effect that.

# djangotemplates/djangotemplates/urls.py

from django.conf.urls import url, include # Add include to the imports here
from django.contrib import admin

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^', include('example.urls')) # tell django to read urls.py in example app
]

After that, in the example app folder, create a new file called urls.py and add the following code:

# djangotemplates/example/urls.py

from django.conf.urls import url
from example import views

urlpatterns = [
    url(r'^$', views.HomePageView.as_view(), name='home'), # Notice the URL has been named
    url(r'^about/$', views.AboutPageView.as_view(), name='about'),
]

The code we have just written tells Django to match the empty route (i.e localhost:8000) to a view called HomePageView and the route /about/ to a view called AboutPageView. Remember, Django views take in HTTP requests and return HTTP responses. In our case, we shall use a TemplateView that returns a Home Page template and another one for the About page. To do this, inside your example app folder, create another folder called templates. Inside the new templates folder, create two new files called index.html and about.html. Your example app folder should now have this structure:

--example
----migrations
------__init__.py
----templates
------index.html
------about.html
----admin.py
----apps.py
----models.py
----tests.py
----urls.py
----views.py

Inside the index.html, paste the following code:

<!-- djangotemplates/example/templates/index.html-->

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Welcome Home</title>
</head>
<body>
  <p>"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. 
    Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. 
    Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. 
    Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
  </p>
  <a href="{% url 'home' %}">Go Home</a>
  <a href="{% url 'about' %}">About This Site</a>
</body>
</html>

Add this code to about.html:

<!-- djangotemplates/example/templates/about.html-->

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>About Us</title>
</head>
<body>
  <p>
  We are a group of Django enthusiasts with the following idiosyncrasies:

  <ol>
    <li>We only eat bananas on Saturdays.</li>
    <li>We love making playing football on rainy days.</li>
  </ol>
  </p>
  <a href="{% url 'home' %}">Go Home</a>
  <a href="{% url 'about' %}">About This Site</a>
</body>
</html>

Notice how we are referring to our links for Go Home and About This Site in our templates. We can use Django’s automatic URL reverse lookup because we named our URLs in our urls.py. Neat, huh!

We shall see the effect of this code in the next section.

Wiring up the views

Let’s add the final code to serve up our templates. We need to edit djangotemplates/example/views.py for this.

# djangotemplates/example/views.py
from django.shortcuts import render
from django.views.generic import TemplateView # Import TemplateView

# Add the two views we have been talking about  all this time :)
class HomePageView(TemplateView):
    template_name = "index.html"

class AboutPageView(TemplateView):
    template_name = "about.html"

Now we can run our app. We first need to make Django’s default migrations since this is the first time we are running our app.

#(env)~/projects/djangotemplates
$ python manage.py migrate

Once that is done, start your server.

#(env)~/projects/djangotemplates
$ python manage.py runserver

Open your browser and navigate to http://localhost:8000. You should be able to see our home page.

Clicking the links at the bottom should be able to navigate you between the pages. Here is the About page:

Template Inheritance

Let’s shift our focus to the templates folder inside the example app folder. At the moment, it contains two templates, index.html and about.html.

We would like both these templates to have some CSS included. Instead of rewriting the same code in both of them, Django allows us to create a base template which they will both inherit from. This prevents us from having to write a lot of repeated code in our templates when we need to modify anything that is shared.

Let’s create the base template now. Create a file called base.html in djangotemplates/example/templates. Write this code inside it:

<!-- djangotemplates/example/templates/base.html -->

{% load static %}
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>
      Django Sample Site - {% block title %}{% endblock %}
    </title>

    <script src="{% static 'js/main.js' %}"></script> <!-- This is how to include a static file -->
    <link rel="stylesheet" href="{% static 'css/main.css' %}" type="text/css" />
  </head>
  <body>
    <div class="container">
      {% block pagecontent %}
      {% endblock %}
    </div>
  </body>
</html>

The very first line in the file, {% load static %}, uses Django’s special template tag syntax to tell the template engine to use the files in the static folder in this template.

In the title tag, we use a Django block. What this means is that in any Django template which inherits from this base template, any HTML which is inside a block named title will be plugged into the title block. The same goes for the body tag’s pagecontent block. If this sounds confusing, don’t worry. You will see it in action soon.

If you are not running your Django server, run it by executing python manage.py runserver in your terminal. Go to http://localhost:8000. You should see the previous template.

Now edit the index.html template to inherit from the base template.

<!-- djangotemplates/example/templates/index.html -->

{% extends 'base.html' %} <!-- Add this for inheritance -->

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Welcome Home</title>
</head>
<body>
    <p>"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. 
      Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. 
      Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. 
      Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
    </p>
    <a href="{% url 'home' %}">Go Home</a>
    <a href="{% url 'about' %}">About This Site</a>
</body>
</html>

Reload the page in your browser. Nothing appears! This is because Django expects your content to be written inside the blocks we defined in the base template so that they can be rendered. Edit the index.html to add the blocks:

<!-- djangotemplates/example/templates/index.html -->

{% extends 'base.html' %}

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>{% block title %}Welcome Home {% endblock %}</title>
</head>
<body>
  {% block pagecontent %}
    <p>"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. 
      Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. 
      Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. 
      Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
    </p>
    <a href="{% url 'home' %}">Go Home</a>
    <a href="{% url 'about' %}">About This Site</a>
  {% endblock %}
</body>
</html>

Reload the page in the browser and voila! Your content should appear again!

We can also edit the about.html template to use the same.

<!-- djangotemplates/example/templates/about.html -->

{% extends 'base.html' %} <!-- Add this for inheritance -->

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{% block title %}About Us {% endblock %}</title>
</head>
<body>
  {% block pagecontent %}
    <p>
    We are a group of Django enthusiasts with the following idiosyncrasies:

    <ol>
        <li>We only eat bananas on Saturdays.</li>
        <li>We love making playing football on rainy days.</li>
    </ol>
    </p>
    <a href="{% url 'home' %}">Go Home</a>
    <a href="{% url 'about' %}">About This Site</a>
  {% endblock %}
</body>
</html>

You should now see this on the About page:

Which is exactly the same as before!

However, now since both templates inherit from a base template, I can easily style them. Open up main.css in your css folder and add these styles:

.container {
    background: #eac656;
    margin: 10 10 10 10;
    border: 3px solid black;
}

This will style the container div which we are loading our content into. Refresh your browser. You should see this:

The Home Page:

The About Page:

Rendering templates with data from views

You can use Django’s template engine to display data in very powerful ways. In this section, I will create a Django view that will pass data into a template. I will then show you how to access that data in the template and display it to the user.

First things first, open up views.py in the example app folder. We will add a new view to serve data into our yet to exist data.html template. Modify the views.py file to look like this:

# djangotemplates/example/views.py

from django.shortcuts import render
from django.views.generic import TemplateView

class HomePageView(TemplateView):
    template_name = "index.html"

class AboutPageView(TemplateView):
    template_name = "about.html"

# Add this view
class DataPageView(TemplateView):
    def get(self, request, **kwargs):
        # we will pass this context object into the
        # template so that we can access the data
        # list in the template
        context = {
            'data': [
                {
                    'name': 'Celeb 1',
                    'worth': '3567892'
                },
                {
                    'name': 'Celeb 2',
                    'worth': '23000000'
                },
                {
                    'name': 'Celeb 3',
                    'worth': '1000007'
                },
                {
                    'name': 'Celeb 4',
                    'worth': '456789'
                },
                {
                    'name': 'Celeb 5',
                    'worth': '7890000'
                },
                {
                    'name': 'Celeb 6',
                    'worth': '12000456'
                },
                {
                    'name': 'Celeb 7',
                    'worth': '896000'
                },
                {
                    'name': 'Celeb 8',
                    'worth': '670000'
                }
            ]
        }

        return render(request, 'data.html', context)

We are using the same kind of view we used to render the other templates. However, we are now passing a context object to the render method. The key-value pairs defined in the context will be available in the template being rendered and we can iterate through them just like any other list.

To finish this up, go to the urls.py file in the howdy app and add the URL pattern for our new view so that it looks like this:

# djangotemplates/example/urls.py

from django.conf.urls import url
from example import views

urlpatterns = [
    url(r'^$', views.HomePageView.as_view(), name='home'),
    url(r'^about/$', views.AboutPageView.as_view(), name='about'),
    url(r'^data/$', views.DataPageView.as_view(), name='data'),  # Add this URL pattern
]

Finally, let’s create the template. In the templates folder, create a file called data.html and write this code inside it.

<!-- djangotemplates/example/templates/data.html -->

{% extends 'base.html' %}
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body>
    {% block pagecontent %}
    <div class="table-div">
    <!-- We will display our data in a normal HTML table using Django's
    template for-loop to generate our table rows for us-->
      <table class="table">
        <thead>
          <tr>
            <th>Celebrity Name</th>
            <th>Net Worth</th>
          </tr>
        </thead>
        <tbody>
          {% for celebrity in data %}
            <tr>
              <td>{{ celebrity.name }}</td>
              <td>{{ celebrity.worth }}</td>
            </tr>
          {% endfor %}
        </tbody>
      </table>
    </div>
    {% endblock %}
  </body>
</html>

In data.html, you can see that we use what is essentially a for loop to go through the data list. Binding of values in Django templates is done using {{}} curly brackets much like in AngularJS.

With your server running, go to http://localhost:8000/data/ to see the template.

Including snippets into your templates

We now have three templates, index.html, about.html and data.html. Let’s link them together using a simple navigation bar. First up, let’s write the code for the navigation bar in another HTML template.

In the templates folder inside the example app, create a new folder called partials. Inside it, create a file called nav-bar.html. The templates folder structure should now be like this:

templates
----index.html
----about.html
----data.html
----partials
------nav-bar.html

Edit the nav-bar.html partial so that it contains this code:

<!-- djangotemplates/example/templates/partials/nav-bar.html -->

<div class="nav">
  <a href="{% url 'home' %}">Go Home</a>
  <a href="{% url 'about' %}">About This Site</a>
  <a href="{% url 'data' %}">View Data</a>
</div>

Including snippets in a template is very simple. We use the includes keyword provided by Django’s templating engine. Go ahead and modify index.html to this:

<!-- djangotemplates/example/templates/index.html -->

{% extends 'base.html' %}

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>{% block title %}Welcome Home {% endblock %}</title>
</head>
<body>
  {% block pagecontent %}
    <p>"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. 
      Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. 
      Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. 
      Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
    </p>
    {% include 'partials/nav-bar.html' %} <!--Add this-->

    <!-- Remove these two lines -- >
    <!-- <a href="{% url 'home' %}">Go Home</a> -->
    <!-- <a href="{% url 'about' %}">About This Site</a> -->
  {% endblock %}
</body>
</html>

Modify about.html to this:

<!-- djangotemplates/example/templates/about.html -->

{% extends 'base.html' %}

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{% block title %}About Us {% endblock %}</title>
</head>
<body>
  {% block pagecontent %}
    <p>
    We are a group of Django enthusiasts with the following idiosyncrasies:

    <ol>
        <li>We only eat bananas on Saturdays.</li>
        <li>We love making playing football on rainy days.</li>
    </ol>
    </p>
    {% include 'partials/nav-bar.html' %} <!--Add this-->

    <!-- Remove these two lines -- >
    <!-- <a href="{% url 'home' %}">Go Home</a> -->
    <!-- <a href="{% url 'about' %}">About This Site</a> -->
  {% endblock %}
</body>
</html>

Lastly, modify data.html to this:

<!-- djangotemplates/example/templates/data.html -->

{% extends 'base.html' %}
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body>
    {% block pagecontent %}
    <div class="table-div">
      <table class="table">
        <thead>
          <tr>
            <th>Celebrity Name</th>
            <th>Net Worth</th>
          </tr>
        </thead>
        <tbody>
          {% for celebrity in data %}
            <tr>
              <td>{{ celebrity.name }}</td>
              <td>{{ celebrity.worth }}</td>
            </tr>
          {% endfor %}
        </tbody>
      </table>
    </div>
    {% include 'partials/nav-bar.html' %} <!--Add this-->
    {% endblock %}
  </body>
</html>

Time to check out our work! Open your browser and navigate to http://localhost:8000. You should see this:

All the pages are now linked with the navbar so you can easily navigate back and forth through them, all with minimal code written. Here is the data.html template:

And here is about.html:

Note: I have added the following CSS to syle the links in the navbar. Feel free to use it or play with your own styles:

// djangtotemplates/static/css/main.css

.container {
    background: #eac656;
    margin: 10 10 10 10;
    border: 3px solid black;
}

.nav a {
    background: #dedede;
}

Filters

Filters take data piped to them and output it in a formatted way. Django templates have access to the humanize collection of filters, which make data more human readable. Let’s make the celebrity’s networth field in the data template more readable by using some of these filters.

To use Django’s humanize filters, you first need to edit some settings. Open up djangotemplates/settings.py and edit the INSTALLED_APPS list to this:

# djangotemplates/djangotemplates/settings.py

ALLOWED_HOSTS = []

# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'django.contrib.humanize', # Add this line. Don't forget the trailing comma
    'example',
]

We can now use a filter in our templates. We are going to use the intcomma filter to add comma’s in large numbers to make them easier to read. Let’s modify data.html to this:

<!-- djangotemplates/example/templates/data.html -->

{% extends 'base.html' %}
{% load humanize %} <!-- Add this-->

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body>
    {% block pagecontent %}
    <div class="table-div">
      <table class="table">
        <thead>
          <tr>
            <th>Celebrity Name</th>
            <th>Net Worth</th>
          </tr>
        </thead>
        <tbody>
          {% for celebrity in data %}
            <tr>
              <td>{{ celebrity.name }}</td>
              <td>$ {{ celebrity.worth | intcomma }}</td> <!--Modify this line-->
            </tr>
          {% endfor %}
        </tbody>
      </table>
    </div>
    {% include 'partials/nav-bar.html' %}
    {% endblock %}
  </body>
</html>

When you go to http://localhost:8000/data/, you should now have a more friendly list of net worth values:

There are many more filters included in the humanize package. Read about them here

Collecting Static Files

Remember we talked about collecting static files? Try the following command:

python manage.py collectstatic

You should see a prompt like the following:

You have requested to collect static files at the destination
location as specified in your settings:

      /Users/amos/projects/djangotemplates/staticfiles

This will overwrite existing files!
Are you sure you want to do this?

Type 'yes' to continue, or 'no' to cancel: 

Go ahead and say yes.

This command will tell Django to go through all your project folders, look for all static files and store them in one place (the static root we defined in the settings). This is very efficient especially if you are deploying your site to production.

When you run the command collectstatic, you should see a new folder called staticfiles created in the root of your project folder. You can change this location to something else by editing the static root setting in your project’s settings.py file. To use these staticfiles, in your templates you will say load staticfiles instead of load static. Everything else is the same as with using the previous static folder.

Conclusion

Congratulations on reaching the end of this tutorial! By now you should have a more detailed understanding of how Django templates work. If you need deeper information, remember the docs are your friend. You can find the full code for this tutorial here. Make sure to leave any thoughts, questions or concerns in the comments below.

Source:: scotch.io

Node.js Weekly Update - 23 Dec, 2016

By Ferenc Hamori

Node.js Weekly Update - 23 Dec, 2016

Read the most important Node.js news & updates from this week: Migrating from Java to Node, Extending Slack with Node.js, URL shortening, IoT and Node, Top 10 of 2016, Unit-testing cheat sheet.

The 7 must-read Node.js articles of this Week:

○ Migrating from Java, Spring, MySQL on AWS to Node.js, Restify, Firebase on GCP

In September 2015, Romans Bermans have joined a 2 months old startup which had a team of 4, enough funding to get going for a year and a challenging vision for the future.

In 15 months we went from a prototype of our platform through a Java, Spring, MySQL stack deployed on AWS to a total rewrite in Node.js, Restify, Firebase deployed on GCP.

○ Extend Slack with Node.js

It is 2016 and Slack is the new e-mail. For many distributed teams or companies like Auth0, Slack has become the default communication solution.

In this post I will show how you can easily extend Slack with Node.js using Slash Webtasks, a solution we have created at Auth0 that builds on the serverless concepts. Using this approach you can automate processes, run your devops, generate reports, and more, in a powerful yet simple and efficient way.

○ The 10 Most Important Node.js Articles of 2016

To summarize this year, we collected the 10 most important articles we recommend to read. These include the biggest scandals, events, and improvements surrounding Node.js in 2016.

  • Left-pad
  • Yarn
  • Debugging with Chrome DevTools
  • Node.js Security Project overtake
  • Node.js Developer Survey

and many more.. Read the full article for the details.

○ Solving IoT Problems with Node.js for Hardware

Tod Kurt knows a thing or two about IoT devices. As the creator of blink(1), he’s shipped over 30,000 units that are now out in the wild and in use for custom signaling on everything from compile status to those emotionally important social media indicators.

Tods’ talk at the 2016 Hackaday SuperConference covers the last mile that bridges your Internet of Things devices with its intended use. This is where IoT actually happens, and of course where it usually goes astray.

○ Node v7.3.0 (Current) Released

Notable changes:

  • buffer.fill() now works properly for the UCS2 encoding on Big-Endian machines.
  • disconnect() now returns a reference to the disconnected worker.
  • The built-in list of Well-Known CAs (Certificate Authorities) can now be extended via a NODEEXTRACA_CERTS environment variable.
  • Remove stale timeout listeners in order to prevent a memory leak when using keep alive.
  • Allow obvious key/passphrase combinations.
  • Including base argument in URL.originFor() to meet specification compliance.
  • Improve URLSearchParams to meet specification compliance.

○ Node.js Community Store

The Node.js Community Store got opened this week, allowing you to order Node themed t-shirts, stickers and water bottles.

Node.js Weekly Update - 23 Dec, 2016

○ The Ultimate Unit Testing Cheat-sheet

Using mocha/chai/sinon for node.js unit-tests? This list got you covered!


Previously in the Node.js Weekly Update

Last week we read fantastic articles about npm5, Clean Coding, switching to Yarn, CI with Jenkins, Node Maturity Checklist and V8 ❤️ Node.js

Source:: risingstack.com