Front: Nuxt Backend: Django REST Framework (DRF) When I started a new project etc. in, it became troublesome to check the settings etc. one by one, so I will summarize it.
However, writing only the configuration file is not enough as an article personally.
So, I plan to write up to the point of implementing membership registration by hitting the API, which is the basic operation, to perform CRUD. This time, DB uses SQLite. If you want to use another RDB such as PostgreSQL or MySQL, just rewrite the DB settings on the DRF side, so please make those settings yourself.
In this article, you can get detailed product information by hitting the API created by DRF from Nuxt.
The source code can be found at here, so if you have any questions, please take a look.
You can also answer by asking Twitter or in the comments section of this article if you have any questions.
First, create a familiar project. Let's arrange from the setting from the DRF side.
$ mkdir nuxt-django
$ cd nuxt-django
$ django-admin startproject server
$ cd server
$ django-admin startapp practice
First, let's change the configuration file.
settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'practice', #add to
'rest_framework', #add to
'corsheaders', #add to
]
......
#add to
#Origin to allow
CORS_ORIGIN_WHITELIST = (
'http://localhost:3000',
'http://127.0.0.1:3000',
)
CORS_ORIGIN_ALLOW_ALL = True
......
#The following changes and additions
# Internationalization
# https://docs.djangoproject.com/en/2.2/topics/i18n/
LANGUAGE_CODE = 'ja-JP'
TIME_ZONE = 'Asia/Tokyo'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.2/howto/static-files/
STATIC_URL = '/static/'
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
What I added to ʻINSTALLED_APPS is the
rest_frameworkwhich is required to use the app and DRF added by
startapp, and the
corsheaders` which is necessary to access with axios.
CORS_ORIGIN_WHITELIST
needs to be written to set where to allow access.
After that, change LANGUAGE_CODE
and TIME_ZONE
to support Japanese.
The last MEDIA ...
was added to handle images after this. It is not necessary if you do not use the image file, but it is recommended to describe it because it will be used in many cases.
urls.py
from django.contrib import admin
from django.urls import path,include #add to
from django.conf.urls.static import static #add to
from django.conf import settings #add to
urlpatterns = [
path('admin/', admin.site.urls),
path('api/',include('practice.urls')),
]
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL,document_root=settings.MEDIA_ROOT)
models.py
from django.db import models
# Create your models here.
CATEGORY = (
(1, 'Beverage'),
(2, 'flower arrangement'),
)
class Item(models.Model):
name = models.CharField(verbose_name='Product name',max_length=255,null=False)
category = models.IntegerField(verbose_name='category',choices=CATEGORY)
image = models.FileField(verbose_name='image')
price = models.PositiveIntegerField(verbose_name='image',null=False)
description = models.TextField(verbose_name='Details',blank=True,null=True)
def __str__(self):
return self.name
This time I made a model of a common product. Then create a serializer to handle this item.
serializers.py
from rest_framework import serializers
from .models import Item
class ItemSerializer(serializers.ModelSerializer):
class Meta:
model = Item
fields = '__all__'
Then write views.py and urls.py to route this.
views.py
from django.shortcuts import render
from rest_framework import viewsets,filters,permissions,generics
from .serializers import ItemSerializer
from .models import Item
# Create your views here.
class ItemListView(generics.ListAPIView):
serializer_class = ItemSerializer
queryset = Item.objects.all()
class ItemDetailView(generics.RetrieveAPIView):
serializer_class = ItemSerializer
queryset = Item.objects.all()
practice/urls.py
from django.urls import path
from .views import ItemListView,ItemDetailView
urlpatterns = [
path('items/',ItemListView.as_view()),
path('items/<int:pk>/',ItemDetailView.as_view()),
]
Finally, add the following so that admin can handle the data.
admin.py
from django.contrib import admin
from .models import Item
# Register your models here.
admin.site.register(Item)
Regarding why ʻItemListView and ʻItemDetailView
are separated, it will be easier to use if they are separated when implementing permissions, and it will be necessary to separate them later.
This completes the basic backend settings.
$ python manage.py makemigrations
$ python manage.py migrate
$ python manage.py createsuperuser
username(leave blank to use 'kuehar'): kueharx
mail address:
Password:
Password (again):
Superuser created successfully.
$ python manage.py runserver
With the local server running http://localhost:8000/admin Let's access and add data like this.
After that http://localhost:8000/api/items When you access, you should see a screen like the one below.
At this stage, the construction of the backend for GET from the frontend is complete.
Now let's move on to building the front end.
First, let's create a project. This time I made it with the following settings.
$ npx create-nuxt-app client
create-nuxt-app v2.15.0
✨ Generating Nuxt.js project in client
? Project name client
? Project description nuxt-django-auth sample app
? Author name kueharx
? Choose programming language JavaScript
? Choose the package manager Npm
? Choose UI framework Vuetify.js
? Choose custom server framework Express
? Choose Nuxt.js modules Axios
? Choose linting tools ESLint
? Choose test framework None
? Choose rendering mode Universal (SSR)
? Choose development tools (Press <space> to select, <a> to toggle all, <i> to invert selection)
$ cd client
do it
$ npm run dev
Then
I feel like this.
I will add settings. First of all,
$ npm install -s @nuxtjs/axios
After doing, add the following description to the configuration file.
JavaScript:nuxt.config.js
....
modules: [
'@nuxtjs/axios',
],
axios: {
baseURL: 'http://localhost:8000/api/',
},
To add. This is an element that indicates which local server to connect to when using axios, and if you do not add this, you will not be able to hit the api you created earlier.
Well, inspire looks like this at first,
Let's add some code.
This time, I will make a card that displays the product outline and link.
Let's make that card first.
ItemCard.vue
<template>
<div class="card item-card">
<img :src="item.image" class="card-img-top">
<div class="card-body">
<h5 class="card-title">
{{ item.name }}
</h5>
<p class="card-text">
<strong>Category</strong> {{ item.category }}
</p>
<p class="card-text">
<strong>price:</strong> {{ item.price }}
</p>
<div class="action-buttons">
<nuxt-link :to="`/items/${item.id}/`" class="btn btn-sm btn-primary">
Details
</nuxt-link>
</div>
</div>
</div>
</template>
<script>
export default {
props: ['item', 'onDelete']
}
</script>
<style>
.item-card {
box-shadow: 0 1rem 1.5rem rgba(0,0,0,.6);
}
img.card-img-top{
height:200px;
}
.action-buttons {
text-align: right;
}
</style>
The card layout is now complete.
Let's read this card with inspire.
inspire.vue
<template>
<v-layout>
<v-flex class="text-center">
<img
src="/v.png "
alt="Vuetify.js"
class="mb-5"
>
<blockquote class="blockquote">
“First, solve the problem. Then, write the code.”
<footer>
<small>
<em>—John Johnson</em>
</small>
<div class="row">
<div class="col-12 text-right mb-4">
<div class="d-flex justify-content-between">
<h3>Product list</h3>
<!-- <nuxt-link to="/items/add" class="btn btn-info">
Add a product
</nuxt-link> -->
</div>
</div>
<template v-for="item in items">
<div :key="item.id" class="col-lg-3 col-md-4 col-sm-6 mb-4">
<item-card :on-delete="deleteitem" :item="item" />
</div>
</template>
</div>
</footer>
</blockquote>
</v-flex>
</v-layout>
</template>
<script>
import ItemCard from '~/components/ItemCard.vue'
export default {
components: {
ItemCard
},
async asyncData ({ $axios, params }) {
try {
const items = await $axios.$get('items/')
return { items }
} catch (e) {
return { items: [] }
}
},
data () {
return {
items: []
}
},
methods: {
async deleteitem (item_id) { //eslint-disable-line
try {
await this.$axios.$delete(`/items/${item_id}/`) //eslint-disable-line
const newitems = await this.$axios.$get('/items/')
this.items = newitems
} catch (e) {
console.log(e)
}
}
},
head () {
return {
title: 'Product list'
}
}
}
</script>
Applying these ...
As mentioned above, I was able to get the list properly.
~~ This time, we will make a product detail page next time. ~~
I have written! CRUD GET with Nuxt & Django REST Framework ②
Recommended Posts