2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

angularとDRFでブログアプリ

Posted at

完成像

  1. APIから記事を取得
  2. 記事のタイトルをリストで表示
  3. 記事のタイトルをクリックしたら、内容を表示

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)),
]
スクリーンショット 2020-02-08 15.39.46.png

バックエンド完了。

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
    );
  }

}
スクリーンショット 2020-02-08 17.22.23.png

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
      );
  }

}
スクリーンショット 2020-02-09 2.06.02.png

urlのidを元にAPIのデータを探して詳細を表示することtができた。

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?