完成像
- APIから記事を取得
- 記事のタイトルをリストで表示
- 記事のタイトルをクリックしたら、内容を表示
django部分
djangoプロジェクトの作成
django,restframework,corsheadersはインストール済み。
ターミナル
$ django-admin startproject django_blog
$ cd $_
$ python manage.py startapp blog
$ cd blog
$ touch urls.py
$ touch serializer.py
管理画面のユーザー作成
ターミナル
$ python manage.py createsuperuser
設定に追記する
settting.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'blog',#追加
'rest_framework',#追加
'corsheaders',#追加
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'corsheaders.middleware.CorsMiddleware',#追加(場所は絶対ここ)
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
#末尾に追加
CORS_ALLOW_CREDENTIALS = True
CORS_ORIGIN_ALLOW_ALL = True
modelsを定義
models.py
from django.db import models
# Create your models here.
class Blog(models.Model):
title = models.CharField(max_length=140, blank=False)
text = models.CharField(max_length=1000, blank=False)
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
ターミナル
$ python manage.py makemigrations
$ python manage.py migrate
admin.py
from django.contrib import admin
from .models import Blog
# Register your models here.
@admin.register(Blog)
class Blog(admin.ModelAdmin):
pass
serializerの作成
serializer.py
from rest_framework import serializers
from .models import Blog
class BlogSerializer(serializers.ModelSerializer):
class Meta:
model = Blog
fields = ('id', 'title', 'text', 'created_at')
viewの作成
view.py
from django.shortcuts import render
from rest_framework import viewsets
from .models import Blog
from .serializer import BlogSerializer
# Create your views here.
class BlogViewSet(viewsets.ModelViewSet):
queryset = Blog.objects.all()
serializer_class = BlogSerializer
urlsの作成
blog/urls.py
from rest_framework import routers
from .views import BlogViewSet
router = routers.DefaultRouter()
router.register(r'blog', BlogViewSet)
django_blog/urls.py
from django.contrib import admin
from django.urls import path, include
from blog.urls import router as blog_api_router
urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include(blog_api_router.urls)),
]
バックエンド完了。
angular部分
angularプロジェクトの作成
ターミナル
$ ng new angular-blog
welcomeページを削除
app.component.html
<h1>BLOG</h1>
<router-outlet></router-outlet>
コンポーネントとサービスの作成
ターミナル
$ cd src/app
$ mkdir components
$ cd $_
$ ng g c list
$ ng g c detail
$ cd ..
$ mkdir services
$ cd $_
$ ng g s blog
ルーティングの作成
app-routing.module.ts
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { ListComponent } from './components/list/list.component';
import { DetailComponent } from './components/detail/detail.component';
const routes: Routes = [
{path: '', component: ListComponent},
{path: 'detail/:id', component: DetailComponent}
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
モジュールのインストール
app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { ListComponent } from './components/list/list.component';
import { DetailComponent } from './components/detail/detail.component';
import { BlogService } from './services/blog.service';
@NgModule({
declarations: [
AppComponent,
ListComponent,
DetailComponent
],
imports: [
BrowserModule,
AppRoutingModule,
FormsModule,
HttpClientModule
],
providers: [BlogService],
bootstrap: [AppComponent]
})
export class AppModule { }
インターフェイスの作成
ターミナル
$ mkdir interfaces
$ cd $_
$ ng g i blog
blog.ts
export interface Blog {
id: number;
title: string;
text: string;
}
サービスの作成
blog.service.ts
import { Blog } from './../interfaces/blog';
import { Injectable } from '@angular/core';
import { HttpHeaders, HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
@Injectable(
)
export class BlogService {
blog: Blog[] = [];
private Url = 'http://localhost:8000/api/blog/';
private headers = new HttpHeaders({
'Content-Type': 'application/json'
});
constructor(
private http: HttpClient
) { }
getAllBlog(): Observable<any>{
return this.http.get(this.Url, {headers: this.headers});
}
}
リストコンポーネントを作成
list.component.html
<div class="container">
<h1>List</h1>
<ul class="">
<li *ngFor="let blog of blogs" class="">
<a routerLink="detail/{{blog.id}}">
<span from="name">{{blog.title}}</span>
</a>
</li>
</ul>
</div>
list.component.ts
import { BlogService } from './../../services/blog.service';
import { Blog } from './../../interfaces/blog';
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-list',
templateUrl: './list.component.html',
styleUrls: ['./list.component.css']
})
export class ListComponent implements OnInit {
blogs: Blog[] = [];
constructor(
private blogService: BlogService
) { }
ngOnInit() {
this.blogService.getAllBlog().subscribe(
blogs => this.blogs = blogs
);
}
}
APIで取得した投稿をangularで表示することができた。
detailコンポーネントの作成
blog.service.ts
getBlog(id: number): Observable<Blog>{
const url = `${this.Url}${id}`;
return this.http.get<Blog>(url);
}
detail.component.html
<h1>Detail</h1>
<div *ngIf="blog">
<h2>{{blog.title}}</h2>
<p>{{blog.text}}</p>
</div>
<button [routerLink]="['']" routerLinkActive="router-link-active" >
戻る
</button>
detail.component.ts
import { Blog } from './../../interfaces/blog';
import { BlogService } from './../../services/blog.service';
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
@Component({
selector: 'app-detail',
templateUrl: './detail.component.html',
styleUrls: ['./detail.component.css']
})
export class DetailComponent implements OnInit {
blog: Blog;
constructor(
private route: ActivatedRoute,
private blogService: BlogService
) { }
ngOnInit() {
this.getBlog();
}
getBlog(): void{
const id = +this.route.snapshot.paramMap.get('id');
this.blogService.getBlog(id).subscribe(
blog => this.blog = blog
);
}
}
urlのidを元にAPIのデータを探して詳細を表示することtができた。