Criação de API REST Django, via Django REST framework (DRF), utilizando generic views.
pip3 install django djangorestframework markdown django-filter django-cors-headers --break-system-packages
django-admin startproject mylibrary
cd mylibrary
python manage.py startapp library
INSTALLED_APPS = [
# Outras apps
'rest_framework',
'corsheaders',
'library',
]
MIDDLEWARE = [
# Outro conteúdo
'corsheaders.middleware.CorsMiddleware',
]
CORS_ALLOW_ALL_ORIGINS = True
# CORS_ALLOWED_ORIGINS = [
# "http://localhost:8080",
# ]
from django.db import models
class Book(models.Model):
title = models.CharField(max_length=255)
author = models.CharField(max_length=255)
published_date = models.DateField()
isbn = models.CharField(max_length=13, unique=True)
pages = models.IntegerField()
cover = models.CharField(max_length=255, blank=True)
language = models.CharField(max_length=50)
def __str__(self):
return self.title
from rest_framework import serializers
from .models import Book
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = '__all__'
from rest_framework import generics
from .models import Book
from .serializers import BookSerializer
class BookListCreateView(generics.ListCreateAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
class BookRetrieveUpdateDestroyView(generics.RetrieveUpdateDestroyAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
from django.urls import path
from .views import BookListCreateView, BookRetrieveUpdateDestroyView
urlpatterns = [
path('books/', BookListCreateView.as_view(), name='book-list-create'),
path('books/<int:pk>/', BookRetrieveUpdateDestroyView.as_view(), name='book-detail'),
]
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include('library.urls')),
]
python manage.py makemigrations library
python manage.py migrate
python manage.py runserver
{
"title": "The Great Gatsby",
"author": "F. Scott Fitzgerald",
"published_date": "1925-04-10",
"isbn": "9780743273565",
"pages": 180,
"cover": "hardcover",
"language": "English"
}
Confirmar Send. Retornará código status 201 e JSON de book adicionado;
{
"title": "EDITADO AQUI The Great Gatsby",
"author": "F. Scott Fitzgerald",
"published_date": "1925-04-10",
"isbn": "9787432735615",
"pages": 180,
"language": "English"
}
Confirmar Send. Retornará código status 200 e JSON de book editado;
Criação de projeto Vue.js para consumir, via Axios, API REST Django. Cada componente realizará função específica do sistema. Utilização de Bootstrap 5 para estilização dos componentes e página front-end.
npm i -g @vue/cli
vue create library-client
cd library-client
npm i axios vue-axios bootstrap@5.3.3 popper.js
npm run serve
import { createApp } from 'vue';
import App from './App.vue';
import axios from 'axios';
import VueAxios from 'vue-axios';
import 'bootstrap/dist/css/bootstrap.min.css';
import 'bootstrap/dist/js/bootstrap.bundle.min.js';
axios.defaults.baseURL = 'http://localhost:8000/api/';
createApp(App).use(VueAxios, axios).mount('#app');
<template>
<div id="app">
<h1>Livraria UB Social</h1>
<AddBook @book-added="fetchBooks" />
<ListBooks @edit-book="selectBookToEdit" ref="listBooks" />
<EditBook v-if="selectedBook" :book="selectedBook" @book-updated="handleBookUpdated" @cancel-edit="cancelEdit" />
</div>
</template>
<script>
import ListBooks from './components/ListBooks.vue';
import AddBook from './components/AddBook.vue';
import EditBook from './components/EditBook.vue';
export default {
components: {
ListBooks,
AddBook,
EditBook,
},
data() {
return {
selectedBook: null,
};
},
methods: {
fetchBooks() {
this.$refs.listBooks.fetchBooks();
},
selectBookToEdit(book) {
this.selectedBook = book;
},
handleBookUpdated() {
this.selectedBook = null;
this.fetchBooks();
},
cancelEdit() {
this.selectedBook = null;
},
},
};
</script>
<style>
#app {
max-width: 600px;
margin: 0 auto;
padding: 20px;
}
form input {
display: block;
margin: 10px 0;
padding: 5px;
}
button {
margin: 5px;
padding: 5px 10px;
cursor: pointer;
}
</style>
<template>
<div>
<h2>Livros no acervo:</h2>
<ul>
<li v-for="book in books" :key="book.id">
{{ book.title }} by {{ book.author }}
<button @click="$emit('edit-book', book)" class="btn btn-warning">Editar</button>
<button @click="deleteBook(book.id)" class="btn btn-danger">Deletar</button>
</li>
</ul>
</div>
</template>
<script>
export default {
data() {
return {
books: [],
};
},
methods: {
async fetchBooks() {
try {
const response = await this.axios.get(`books/`);
this.books = response.data;
} catch (error) {
console.error('Error fetching books:', error);
}
},
async deleteBook(bookId) {
try {
await this.axios.delete(`books/${bookId}/`);
this.fetchBooks();
} catch (error) {
console.error('Error deleting book:', error);
}
},
},
mounted() {
this.fetchBooks();
},
};
</script>
<template>
<div v-if="book">
<h2>Editar livro:</h2>
<form @submit.prevent="updateBook">
<input v-model="form.title" placeholder="Title" required />
<input v-model="form.author" placeholder="Author" required />
<input v-model="form.published_date" type="date" placeholder="Published Date" required />
<input v-model="form.isbn" placeholder="ISBN" required />
<input v-model="form.pages" type="number" placeholder="Pages" required />
<input v-model="form.cover" placeholder="Cover" />
<input v-model="form.language" placeholder="Language" required />
<button type="submit" class="btn btn-success">Confirmar</button>
<button @click="$emit('cancel-edit')">Cancelar</button>
</form>
</div>
</template>
<script>
export default {
props: {
book: Object,
},
data() {
return {
form: { ...this.book },
};
},
watch: {
book(newBook) {
this.form = { ...newBook };
},
},
methods: {
async updateBook() {
try {
await this.axios.put(`books/${this.book.id}/`, this.form);
this.$emit('book-updated');
} catch (error) {
console.error('Error updating book:', error);
}
},
},
};
</script>
<template>
<div>
<h2>Adicionar novo livro:</h2>
<form @submit.prevent="addBook">
<input v-model="form.title" placeholder="Title" required />
<input v-model="form.author" placeholder="Author" required />
<input v-model="form.published_date" type="date" placeholder="Published Date" required />
<input v-model="form.isbn" placeholder="ISBN" required />
<input v-model="form.pages" type="number" placeholder="Pages" required />
<input v-model="form.cover" placeholder="Cover" />
<input v-model="form.language" placeholder="Language" required />
<button type="submit" class="btn btn-success">Confirmar</button>
</form>
</div>
</template>
<script>
export default {
data() {
return {
form: {
title: '',
author: '',
published_date: '',
isbn: '',
pages: '',
cover: '',
language: '',
},
};
},
methods: {
async addBook() {
try {
await this.axios.post(`books/`, this.form);
this.$emit('book-added');
this.resetForm();
} catch (error) {
console.error('Error adding book:', error);
}
},
resetForm() {
this.form = {
title: '',
author: '',
published_date: '',
isbn: '',
pages: '',
cover: '',
language: '',
};
},
},
};
</script>
<template>
<button @click="deleteBook">Confirmar deleção</button>
</template>
<script>
import axios from 'axios';
export default {
props: {
bookId: Number,
},
methods: {
async deleteBook() {
try {
await axios.delete(`http://localhost:8000/api/books/${this.bookId}/`);
this.$emit('book-deleted');
} catch (error) {
console.error('Error deleting book:', error);
}
},
},
};
</script>
Integrar (juntar) back-end Django com front-end Vue.js, para tornar sistema unificado.
Elaborado por Mateus Schwede
ubsocial.github.io