Angular 8|7 CRUD Tutorial: Python|Django REST API

Angular Tutorial - Python Backend

Angular 8 is released! Read about its new features and how to update Angular 7 to v8.

This tutorial is designed for developers that want to use Angular 8|7 to build front-end apps for their back-end REST APIs.

Note: Check out how to build a developer's portfolio web application with Angular 7.1, Firebase and Firestore from these series:

You will see by example how to build a CRUD REST API with Angular and Python.

The new features of Angular 7 include better performance, new powerful CLI additions and a new way to inject services. Throughout this tutorial, designed for beginners, you'll learn Angular by example by building a full-stack CRUD—Create, Read, Update and Delete—web application using the latest version of the most popular framework and platform for building mobile and desktop client side applications (also called SPAs or Single Page Applications), created and used internally by Google.

In the back-end we'll use Python with Django, the most popular pythonic web framework designed for perfectionists with deadlines.

In nutshell, you'll learn to generate Angular 8 apps, generate components and services and add routing.

You'll also learn to use various features such as HttpClient for sending AJAX requests and HTTP calls and subscribing to RxJS 6 Observables etc.

By the end of this Angular tutorial, you'll learn by building a real world example application:

  • How to install the latest version of Angular CLI,
  • How to use Angular CLI to generate a new Angular 8 project,
  • How to use Angular to build a simple CRM application,
  • What's a component and component-based architecture
  • How to use RxJS 6 Observables and operators (map() and filter() etc.)
  • How to create Angular components,
  • How to add component routing and navigation,
  • How to use HttpClient to consume a REST API etc.

Prerequisites

You will need to have the following prerequisites in order to follow this tutorial:

  • A Python development environment. We use a Ubuntu system with Python 3.7 and pip installed but you can follow these instructions in a different system as long as you have Python 3 and pip installed. Also the commands shown here are bash commands which are available in Linux-based systems and macOS but if you use Windows CMD or Powershell , make sure to use the equivalent commands or install bash for Windows.
  • Node.js and npm installed on your system. They are required by Angular CLI.
  • The MySQL database management system installed on your system since we'll be using a MySQL database in our application. If you don't want to deal with MySQL installation, you can also use SQLite (a file database that doesn't require any installation) which is configured by default in your Django project.
  • Familiarity with Python, Django and JavaScript (TypeScript).

If you meet these requirements, you are good to go!

Creating the Django REST API

Please check out: Django 2 Tutorial & Example: Build a CRUD REST API for A Simple CRM

Enabling CORS

Since we'll be using two development servers running from two different ports (considered as two separate domains) we need to enable CORS (Cross Origin Resource Sharing) in our Django application.

Start by installing django-cors-headers using pip

$ pip install django-cors-headers

Next, you need to add it to your project settings.py file:

INSTALLED_APPS = (
    ## [...]
    'corsheaders'
)

Next, you need to add corsheaders.middleware.CorsMiddleware middleware to the middleware classes in settings.py

MIDDLEWARE = (
    'corsheaders.middleware.CorsMiddleware',
    # [...]
)

You can then, either enable CORS for all domains by adding the following setting:

CORS_ORIGIN_ALLOW_ALL = True

You can find more configuration options from the docs.

The example Angular application we'll be building is the front-end for the CRM RESTful API that will allow you to create accounts, leads, opportunities and contacts. It's a perfect example for a CRUD (Create, Read, Update and Delete) application built as an SPA (Single Page Application). The example application is work on progress so we'll be building it through a series of tutorials and will be updated to contain advanced features such as RxJS 6 and JWT authentication. We'll also use Bootstrap 4 and Angular Material for building and styling the UI components. You either need Bootstrap 4 or Angular Material for styling so depending on your choice you can follow separate tutorials:

Installing the Angular CLI 8

Make sure you have Node.js installed, next run the following command in your terminal to install Angular CLI 8:

$ npm install @angular/cli@next --global

At the time of this writing @angular/cli v8.0.0-beta.11 is installed.

You can check the installed version by running the following command:

$ ng version

Now, you're ready to create a project using Angular CLI 8. Simply run the following command in your terminal:

ng new ngsimplecrm

The CLI will automatically generate a bunch of files common to most Angular projects and install the required dependencies for your project.

The CLI will prompt you if Would you like to add Angular routing? (y/N), type y. And Which stylesheet format would you like to use? Choose CSS and type Enter.

Next, you can serve your application locally using the following command:

$ cd ./ngsimplecrm
$ ng serve

You application will be running from http://localhost:4200.

This is a screen-shot of home page of the application:

Angular 8 tutorial

Setting up Angular Material

We'll be using Material Design to style our CRM UI so we need Angular Material to our project. Fortunately, this is only one command away. Open a new terminal and run the following commands:

$ cd ./ngsimplecrm
$ ng add @angular/material

The command will ask you for to Choose a prebuilt theme name, or "custom" for a custom theme: (Use arrow keys)

  • Indigo/Pink
  • Deep Purple/Amber
  • Pink/Blue Grey
  • Purple/Green

Choose Deep Purple/Amber or whatever theme you prefer.

And if you want to Set up HammerJS for gesture recognition? (Y/n) Choose the default answer which Yes.

And if you want to Set up browser animations for Angular Material? (Y/n) Also choose Yes.

That's it, Angular Material (v7.3.7 as of this writing) is configured in your application.

After that, you need to import the Angular Material components that you want to use in your project. Open the src/app/app.module.ts file and add the following changes:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { MatInputModule, MatButtonModule, MatCardModule, MatFormFieldModule,MatTableModule } from  '@angular/material';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    BrowserAnimationsModule,
    MatTableModule,
    MatCardModule,
    MatInputModule,
    MatFormFieldModule,
    MatButtonModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Components in Angular

Now what's a component?

A component is a TypeScript class with an HTML template and an optional set of CSS styles that control a part of the screen.

Components are the most important concept in Angular. An Angular application is basically a tree of components with a root component (the famous AppComponent). The root component is the one contained in the bootstrap array in the main NgModule module in the app.module.ts file.

One important aspect of components is re-usability. A component can be re-used throughout the application and even in other applications. Common and repeatable code that performs a certain task can be encapsulated into a re-usable component that can be called whenever we need the functionality it provides.

Each bootstrapped component is the base of its own tree of components. Inserting a bootstrapped component usually triggers a cascade of component creations that fill out that tree. source

Component-Based Architecture

An Angular application is made of several components forming a tree structure with parent and child components.

A component is an independent block of a big system (web application) that communicates with the other building blocks (components) of the system using inputs and outputs. A component has associated view, data and behavior and may have parent and child components.

Components allow maximum re-usability, easy testing, maintenance and separation of concerns.

Let's now see this practically. Head over to your Angular application project folder and open the src/app folder. You will find the following files:

  • app.component.css: the CSS file for the component
  • app.component.html: the HTML view for the component
  • app.component.spec.ts: the unit tests or spec file for the component
  • app.component.ts: the component code (data and behavior)
  • app.module.ts: the application main module

Except for the last file which contains the declaration of the application main (root) Module, all these files are used to create a component. It's the AppComponent: The root component of our application. All other components we are going to create next will be direct or un-direct children of the root component.

Demystifying the AppComponent (The Root Component of Angular Applications)

Go ahead and open the src/app/app.component.ts file and let's understand the code behind the main/root component of the application.

First, this is the code:

import { Component } from  '@angular/core';
@Component({
    selector:  'app-root',
    templateUrl:  './app.component.html',
    styleUrls: ['./app.component.css']
})
export  class  AppComponent {
    title  =  'app';
}

We first import the Component decorator from @angular/core then we use it to decorate the TypeScript class AppComponent. The Component decorator takes an object with many parameters such as:

  • selector: specifies the tag that can be used to call this component in HTML templates just like the standard HTML tags
  • templateUrl: indicates the path of the HTML template that will be used to display this component (you can also use the template parameter to include the template inline as a string)
  • styleUrls: specifies an array of URLs for CSS style-sheets for the component

The export keyword is used to export the component so that it can be imported from other components and modules in the application.

The title variable is a member variable that holds the string 'app'. There is nothing special about this variable and it's not a part of the canonical definition of an Angular component.

Now let's see the corresponding template for this component. If you open src/app/app.component.html this is what you'll find:

<div  style="text-align:center">
<h1>
Welcome to !
</h1>
    <img  width="300"  alt="Angular Logo"  src="data:image/svg+xml;....">
</div>

    <h2>Here are some links to help you start: </h2>
<ul>
    <li>
    <h2><a  target="_blank"  rel="noopener"  href="https://angular.io/tutorial">Tour of Heroes</a></h2>
    </li>
    <li>
    <h2><a  target="_blank"  rel="noopener"  href="https://github.com/angular/angular-cli/wiki">CLI Documentation</a></h2>
    </li>
    <li>
    <h2><a  target="_blank"  rel="noopener"  href="https://blog.angular.io/">Angular blog</a></h2>
    </li>
</ul>

The template is a normal HTML file (almost all HTML tags are valid to be used inside Angular templates except for some tags such as <script>, <html> and <body> etc.) with the exception that it can contain template variables (in this case the title variable) or expressions ({{...}}) that can be used to insert values in the DOM dynamically. This is called interpolation or data binding. You can find more information about templates from the docs.

You can also use other components directly inside Angular templates (via the selector property) just like normal HTML.

If you are familiar with the MVC (Model View Controller) pattern, the component class plays the role of the Controller and the HTML template plays the role of the View.

Angular 8 Components by Example

After getting the theory behind Angular components, let's now create the components for our simple CRM application.

Our REST API, built with Django, exposes these endpoints:

  • /accounts: create or read a paginated list of accounts
  • /accounts/<id>: read, update or delete an account

  • /contacts: create or read a paginated list of contacts

  • /contacts/<id>: read, update or delete a contact

  • /api/activities: create or read a paginated list of activities

  • /api/activities/<id>: read, update or delete an activity

Before adding routing to our application we first need to create the application's components so based on the exposed REST API architecture we can initially divide our application into these components:

  • AccountListComponent: this component displays and controls a tabular list of accounts
  • AccountCreateComponent: this component displays and controls a form for creating or updating accounts

  • ContactListComponent: displays a table of contacts

  • ContactCreateComponent: displays a form to create or update a contact

  • ActivityListComponent: displays a table of activities

  • ActivityCreateComponent: displays a form to create or update an activity

Let's use the Angular CLI to create the components

$ ng generate component AccountList
$ ng generate component AccountCreate

$ ng generate component ContactList
$ ng generate component ContactCreate

$ ng generate component ActivityList
$ ng generate component ActivityCreate

This is the output of the first command:

CREATE src/app/account-list/account-list.component.css (0 bytes)
CREATE src/app/account-list/account-list.component.html (31 bytes)
CREATE src/app/account-list/account-list.component.spec.ts (664 bytes)
CREATE src/app/account-list/account-list.component.ts (292 bytes)
UPDATE src/app/app.module.ts (418 bytes)

You can see that the command generates all the files to define a component and also updates src/app/app.module.ts.

If you open src/app/app.module.ts after running all commands, you can see that all components are automatically added to the AppModule declarations array:

import { BrowserModule } from  '@angular/platform-browser';
import { NgModule } from  '@angular/core';



import { AppComponent } from  './app.component';
import { AccountListComponent } from  './account-list/account-list.component';
import { AccountCreateComponent } from  './account-create/account-create.component';
import { ContactListComponent } from  './contact-list/contact-list.component';
import { ContactCreateComponent } from  './contact-create/contact-create.component';


@NgModule({

declarations: [
    AppComponent,
    AccountListComponent,
    AccountCreateComponent,
    ContactListComponent,
    ContactCreateComponent,
    ActivityListComponent,
    ActivityCreateComponent 
],
imports: [
    BrowserModule
],
providers: [],
bootstrap: [AppComponent]
})
export  class  AppModule { }

Note: If you are creating components manually, you need to make sure to include them manually so they can be recognized as part of the module.

Adding Angular Routing

Now, let's add routing and navigation links in our application.

This is the initial content of src/app/app-routing.module.ts:

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';

const routes: Routes = [
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

The routes array will contain all the routes of the application. After creating the components we'll now see how to add the routes to this array.

First, add the following imports:

import { AccountListComponent } from './account-list/account-list.component';
import { AccountCreateComponent } from './account-create/account-create.component';
import { ContactListComponent } from './contact-list/contact-list.component';
import { ContactCreateComponent } from './contact-create/contact-create.component';
import { ActivityListComponent } from './activity-list/activity-list.component';
import { ActivityCreateComponent } from './activity-create/activity-create.component';

For now, we want to redirect the visitor to the /contacts path when the home URL is visited so the first path we'll add is:

{ path:  '', redirectTo:  'contacts', pathMatch:  'full' },

The pathMatch property specifies the matching strategy. The full value means that we want to fully match the path.

Next let's add the other paths:

  { path: '', redirectTo: 'contacts', pathMatch: 'full' },
  {
    path: 'accounts',
    component: AccountListComponent
  },
  {
    path: 'create-account',
    component: AccountCreateComponent
  },
  {
    path: 'contacts',
    component: ContactListComponent
  },
  {
    path: 'create-contact',
    component: ContactCreateComponent
  },
  {
    path: 'activities',
    component: ActivityListComponent
  },
  {
    path: 'create-activity',
    component: ActivityCreateComponent
  }

Finally, open the src/app/app.component.html file and add the navigation links, then the router outlet:

<a [routerLink]="'/accounts'"> Accounts </a>
<a [routerLink]="'/create-account'"> Create Account </a>

<a [routerLink]="'/contacts'"> Contacts </a>
<a [routerLink]="'/create-contact'"> Create Contact </a>

<a [routerLink]="'/activities'"> Activities </a>
<a [routerLink]="'/create-activity'"> Create Activity </a>

<div>
    <router-outlet></router-outlet>
</div>

An Example for Consuming the REST API Using Angular 8 HttpClient

Now that we've created the different components and added routing and navigation, let's see an example of how to use the HttpClient of Angular 8 to consume the RESTful API back-end.

First, you need to add the HttpClientModule module to the imports array of the main application module:

// [...]
import { HttpClientModule } from  '@angular/common/http';

@NgModule({

declarations: [
// [...]
],

imports: [

// [...]

HttpClientModule
],
providers: [],
bootstrap: [AppComponent]

})

export  class  AppModule { }

Create Angular 8 Services

A service is a global class that can be injected in any component. It's used to encapsulate code that can be common between multiple components in one place instead of repeating it throughout various components.

Now, let's create the services that encapsulates all the code needed for interacting with the REST API. Using Angular CLI 8 run the following commands:

$ ng generate service services/contact
$ ng generate service services/activity
$ ng generate service services/account

Note: Since we have multiple services, we put them in a services folder.

Open src/app/services/contact.service.ts then import and inject the HttpClient class:

import { Injectable } from  '@angular/core';
import { HttpClient} from  '@angular/common/http';

@Injectable({
providedIn:  'root'
})

export  class  ContactService {

    constructor(private  httpClient:  HttpClient) {}

}

Note: You will need to do the same for the other services.

Angular 8 provides a way to register services/providers directly in the @Injectable() decorator by using the new providedIn attribute. This attribute accepts any module of your application or 'root' for the main app module. Now you don't have to include your service in the providers array of your module.

Getting Contacts/Sending HTTP GET Request Example

Let's start with the contacts API endpoint.

First we'll add a method to consume this endpoint in our global API service, next we'll inject the API service and call the method from the corresponding component class (ContactListComponent) and finally we'll display the result (the list of contacts) in the component template.

Open src/app/contact.service.ts and add the following method:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Injectable({
  providedIn: 'root'
})
export class ContactService {

  API_URL  =  'http://localhost:8000';
  constructor(private  httpClient:  HttpClient) { }
  getFirstPage(){
    return  this.httpClient.get(`${this.API_URL}/contacts`);
  }
}

Next, open src/app/contact-list/contact-list.component.ts and inject the ContactService then call the getFirstPage() method:

import { Component, OnInit } from '@angular/core';
import { ContactService } from '../services/contact.service';

@Component({
  selector: 'app-contact-list',
  templateUrl: './contact-list.component.html',
  styleUrls: ['./contact-list.component.css']
})
export class ContactListComponent implements OnInit {

  displayedColumns  :  string[] = ['id', 'first_name', 'last_name', 'email', 'phone', 'account', 'address', 'description', 'createdBy', 'createdAt', 'isActive', 'actions'];
  dataSource  = [];

  constructor(private contactService: ContactService) { }

  ngOnInit() {
    this.fetchContacts();
  }

  fetchContacts(){
    this.contactService.getFirstPage().subscribe((data:  Array<object>) => {
      this.dataSource  =  data;
      console.log(data);
    });
  }

}

Conclusion

Throughout this Angular 8 tutorial for beginners, we've seen, by building a simple real world CRUD example, how to use different Angular concepts to create simple full-stack CRUD application with Angular and Django.


Author


SUBSCRIBE


JOIN OUR COMMUNITY!


comments powered by Disqus