CRUD PUT, DELETE with Nuxt & Django REST Framework

Overview

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.

For the time being, this article is about hitting the API created by DRF from Nuxt to update and delete the contents of the database.

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.

Last time CRUD POST with Nuxt & Django REST Framework

Update location

Back end

Add view and url as before.

views.py


#View for editing / deleting products
class ItemEditView(generics.RetrieveUpdateDestroyAPIView):
    serializer_class = ItemSerializer
    queryset = Item.objects.all()

I didn't mention it last time, but I use the generics view because it's easy to use.

The generics.RetrieveUpdateDestroyAPIView used this time is a view that can GET, PUT, and DELETE information. The scene to use this view is when you want to combine the product editing and deleting screens like this one. In addition, this time I am using this which can also be GET to display the original registered data so that it is easy to understand where to change when editing.

See here for how to use view and a list.

urls.py


.....
path('items/<int:pk>/edit',ItemEditView.as_view()),

As was the case last time, this completes the settings.

http://localhost:8000/api/items/1/edit

Let's access.

スクリーンショット 2020-05-15 14.45.55.png

As mentioned above, the information of the product with id 1 is displayed, and PUT and DELETE can be performed.

Let's move on to the front end.

front end

This time, create ʻedit.vue in the _id` folder.

_id/edit.vue


<template>
<v-card
    light
    :loading="isUpdating"
  >
    <div id="app">
    <v-app id="inspire">
    <v-container>
    <div class="col-12 text-center my-3">
        <h3 class="mb-3 display-4 text-uppercase">
          {{ item.name }}
        </h3>
      </div>
      <div class="col-md-6 mb-4">
        <img
          class="img-fluid"
          style="width: 400px; border-radius: 10px; box-shadow: 0 1rem 1rem rgba(0,0,0,.7);"
          :src="item.image"
          alt
        >
      </div>
    <div class="col-md-6">
        <div class="item-details">
          <h4>Category</h4>
          <p>{{ item.category }}</p>
          <h4>price</h4>
          <p>{{ item.price }}</p>
          <h4>Description</h4>
          <p>{{ item.description }}</p>
          </div>
          </div>
          </v-container>
    <v-form @submit.prevent="editItem">
      <v-container>
        <v-row>
          <v-col
            cols="12"
            md="4"
          >
            <v-text-field
              v-model="item.name"
              label="Product name"
              required
            ></v-text-field>
          </v-col>
  
          <v-col
            cols="12"
            md="4"
          >
            <v-text-field
              v-model="item.category"
              :counter="10"
              label="Category"
              required
            ></v-text-field>
          </v-col>
  
          <v-col
            cols="12"
            md="4"
          >
            <v-text-field
              v-model="item.price"
              label="price"
              required
            ></v-text-field>
          </v-col>
          
          <v-col
            cols="12"
            md="4"
          >
            <v-text-field
              v-model="item.description"
              label="Description of item"
              required
            ></v-text-field>
          </v-col>
          <v-col
            cols="12"
            md="4"
          >
           <v-file-input
           v-model="item.image"
           label="Product image"
           filled
           prepend-icon="mdi-camera"
           ></v-file-input>
          </v-col>
          <v-card-actions>
      <v-spacer />
      <v-btn
        class="btn-primary"
        :loading="isUpdating"
        color="primary"
        depressed
        @click="isUpdating = true"
        type="submit"
      >
        <v-icon left>
          mdi-post
        </v-icon>
Update product
      </v-btn>
    </v-card-actions>
        </v-row>
      </v-container>
    </v-form>
    <v-form @submit.prevent="deleteItem">
    <button class="btn btn-sm btn-danger">
Delete
    </button>
    </v-form>
  </v-app>
</div>
</v-card>
</template>

<script>
export default {
    async asyncData ({ $axios, params }) {
    try {
      const item = await $axios.$get(`/items/${params.id}`)
      return { item }
    } catch (e) {
      return { item: [] }
    }
  },
  data () {
    return {
      item: {
        name: '',
        category: '',
        image: '',
        price: '',
        description: '',
      },
      preview: '',
      autoUpdate: true,
      isUpdating: false,
      title: 'Product editing',
  }
  },
  watch: {
    isUpdating (val) {
      if (val) {
        setTimeout(() => (this.isUpdating = false), 3000)
      }
    }
  },
  methods: {
    createImage (file) {
      const reader = new FileReader()
      const vm = this
      reader.onload = (e) => {
        vm.preview = e.target.result
      }
      reader.readAsDataURL(file)
    },
    async deleteItem () { // eslint-disable-line
      try {
        const deleteditem = this.item
        await this.$axios.$delete(`/items/${deleteditem.id}/edit`) // eslint-disable-line
        const newItems = await this.$axios.$get('/items/')
        this.items = newItems
        this.$router.push('/items')
      } catch (e) {
        console.log(e)
      }
    },
    async editItem () {
      const editeditem = this.item
       //if (editeditem.image.includes('http://)') !== -1) {
        //delete editeditem.image
      //}
      const config = {
        headers: { 'content-type': 'multipart/form-data' }
      }
      const formData = new FormData()
      for (const data in editeditem) {
        formData.append(data, editeditem[data])
      }
      try {
        const response = await this.$axios.$patch(`/items/${editeditem.id}/edit`, formData, config) // eslint-disable-line
        this.$router.push('/items')
      } catch (e) {
        console.log(e)
      }
    }
  }
}
</script>

Then automatically

http://localhost:3000/items/${id}/edit

The routing settings to are generated.

And to be able to dynamically transition from an existing page

_id/index.vue

Update as follows,

_id/index/vue


<template>
  <main class="container my-5">
    <div class="row">
      <div class="col-12 text-center my-3">
        <h2 class="mb-3 display-4 text-uppercase">
          {{ item.name }}
        </h2>
      </div>
      <div class="col-md-6 mb-4">
        <img
          class="img-fluid"
          style="width: 400px; border-radius: 10px; box-shadow: 0 1rem 1rem rgba(0,0,0,.7);"
          :src="item.image"
          alt
        >
      </div>
      <div class="col-md-6">
        <div class="item-details">
          <h4>Category</h4>
          <p>{{ item.category }}</p>
          <h4>price</h4>
          <p>{{ item.price }}</p>
          <h4>Description</h4>
          <p>{{ item.description }}</p>
          <h3>Edit</h3>
          <nuxt-link :to="`/items/${item.id}/edit`" class="btn btn-info">
Edit product
            </nuxt-link>
        </div>
      </div>
    </div>
  </main>
</template>
<script>
export default {
  async asyncData ({ $axios, params }) {
    try {
      const item = await $axios.$get(`/items/${params.id}`)
      return { item }
    } catch (e) {
      return { item: [] }
    }
  },
  data () {
    return {
      item: {
      id:'',
      name:'',
      category:'',
      image:'',
      price:'',
      description:'',
      }
    }
  },
  head () {
    return {
      title: 'Product Details'
    }
  }
}
</script>
<style scoped>
</style>

The main change is

nuxt-link :to ~

Added. Note that if you do dynamic routing with nuxt-link, you will get an error if there is no colon (:) before to.

A product edit page has been added to the detail page

スクリーンショット 2020-05-15 17.55.04.png

Clicking on that link will take you to the product edit page with the form below.

スクリーンショット 2020-05-15 17.55.27.png

There is a column for updating and erasing properly, and I confirmed the operation firmly here.

thank you for your hard work! Now you can do CRUD processing as you like!

If you understand the process properly, you can freely create web applications with Nuxt / DRF to some extent.

Next time, instead of making it possible to post to anyone, we will implement around authentication such as membership registration to manage authority.

Recommended Posts

CRUD PUT, DELETE with Nuxt & Django REST Framework
CRUD GET with Nuxt & Django REST Framework ②
CRUD POST with Nuxt & Django REST Framework
CRUD GET with Nuxt & Django REST Framework ①
Django REST framework with Vue.js
Login with django rest framework
[Django] Use MessagePack with Django REST framework
CRUD with Django
Implementation of CRUD using REST API with Python + Django Rest framework + igGrid
Django REST framework basics
Django Rest Framework Tips
Implementing authentication in Django REST Framework with djoser
Create a Todo app with Django REST Framework + Angular
More new user authentication methods with Django REST Framework
Create a Todo app with the Django REST framework
Create APIs around user authentication with Django REST Framework
When you want to filter with Django REST framework
Implement hierarchical URLs with drf-nested-routers in Django REST framework
Django REST framework stumbling block
Create a REST API to operate dynamodb with the Django REST Framework
Logical deletion in Django, DRF (Django REST Framework)
Understand the benefits of the Django Rest Framework
ng-admin + Django REST framework ready-to-create administration tool
Miscellaneous notes about the Django REST framework
Django REST Framework + Clean Architecture Design Consideration
How to deal with garbled characters in json of Django REST Framework
How to automatically generate API document with Django REST framework & POST from document screen
Django REST framework A little useful to know.
Implement JWT login functionality in Django REST framework
Internationalization with django
Sometimes you want to access View information from Serializer with DRF (Django REST Framework)
[CRUD] [Django] Create a CRUD site using the Python framework Django ~ 1 ~
List method for nested resources in Django REST framework
Implement APIs at explosive speed using Django REST Framework
[Django Rest Framework] Customize the filter function using Django-Filter
[CRUD] [Django] Create a CRUD site using the Python framework Django ~ 2 ~
[CRUD] [Django] Create a CRUD site using the Python framework Django ~ 3 ~
[CRUD] [Django] Create a CRUD site using the Python framework Django ~ 4 ~
[CRUD] [Django] Create a CRUD site using the Python framework Django ~ 5 ~