In this tutorial, we are going to build a CRUD application for storing books with React and Django. CRUD stands for Create, Read, Update and Delete, so basically this app would work like a library shelf where we can take a look at each book data being able to modify as we want or need.
For this application, we will be using two very popular solutions for building user interfaces and APIs. The user interface of the application will be built using React – prior knowledge of React is not required for this tutorial.
The back-end for this application will be built using Django, which is a high-level Python web framework that encourages rapid development and clean pragmatic design. Building APIs in Django is made easy using the Django Rest Framework.
We’ll be building the application in three stages:
1. Creating the front-end in React
2. Creating the APIs in Django
3. Connecting the front-end with the APIs
Getting Started: Configuring the Development Environment
For this tutorial, we will be using the Eclipse IDE with the CodeMix plugin installed. However, feel free to follow along in any IDE that supports both React and Python development.
- Download Eclipse IDE here.
- CodeMix can be installed from the Eclipse marketplace or via genuitec.com.
- If the React pack isn’t already installed, install it using the CodeMix Extension Browser(Help > CodeMix Extensions). It can also be installed directly from the Eclipse marketplace.
If you’re looking for an IDE to take on development with frameworks like Angular, React, and Vue.js, or languages like Python and Rust, CodeMix has you covered. Codemix is compatible with all Eclipse-based IDEs and tools, such as MyEclipse, Spring Tools Suite, and JBoss Tools.
Creating the Front-End In React
We will create our React application using the CodeMix wizard.
To create the application, navigate to File > New > Project > CodeMix > React Project.
Enter react-book-app as the name of the application in the dialog box that appears, then click finish.
The folder structure for your new CodeMix-created react application will look like:
As you can see from the folder structure, there is no node_modules folder. Hence, we need to install the node packages. Using Terminal+, run:
Add the following to the <head> section in src/index.js:
Building the Interface
React is a component-driven library. So we need to break our app into different components. Here is the interface we are trying to build:
The interface can be broken into different components:
Book Dashboard Component: This is the parent component in the application. It contains the book listing component and the Toggleable Book Form Component.
Book Listing Component: This component is saddled with the responsibility of listing all books that have been created in the application. It contains a list of Editable Book Components.
- Editable Book component: Renders a Book component and a Book Form component. If the edit icon is clicked, then the Editable Book component will render a Book Form component that allows books that have been created to be edited.
- Book component: This component shows the details of the book.
- Book Form component: This component shows a form that allows a book to be created or edited.
Toggleable Book Form Component: This component has the responsibility of creating new books. When the + button is clicked, the Book Form component will be rendered which enables us to create a new book.
The application will be able to handle all 4 CRUD (Create Read Update Delete) operations.
We will create the components hierarchically — from the parent component. The first component to be created is the Book Dashboard component.
Modify src/index.js to look like:
As seen above, the BookDashboard component stores the books in state. The books are then passed as props to the BookList component along with some functions to handle book deletion and updates.
BookDashboard also renders ToggleableBookForm and passes a function as prop which will handle book creation. React should be immutable, so we go to our handler functions:
deleteBook which update the state without mutating the initial contents of a book.
Next, we need to create the BookList component. For that, add the following code to index.js.
BookList component receives books as prop, maps over it and returns an array of
EditableBook components which is then rendered.
EditableBook is a component that renders a Book or a BookForm if the user clicks the edit book button on the
Book component. It is a stateful component that stores the edit mode status in state and using that value, knows which component to render.
The book component receives the details about the book as props. It also receives some functions which handle the clicking of the edit button and the delete button.
Let’s create the
Book component just renders the markup for displaying books.
All the data it needs and handlers for edit and delete actions are gotten from the parent component —
BookForm component, on the other hand, renders a form that contains the book details from props for an update operation.
For a create operation, which will be handled by
ToggleableBookForm, no props will be sent the form is made reactive by calling
setState when the input field is modified. We do this by creating different handlers for each field and listen for the change event.
The function to handle submit events on this form will be sent as a prop from the parent component —
The last component to be built is the
ToggleableBookForm, this component will be used for creating books.
As described earlier,
ToggleableBookForm renders a button which the user clicks to create a book. When the button gets clicked, the
BookForm component is rendered.
Finally, we render the
BookDashboard component using ReactDOM.
Reloading the browser, the book app should be functioning as expected.
Our app works!!!
However, the data is not persisted when the page reloads. This is because the data is stored in data structures in our application — state. To persist the data, we need some kind of data storage solution that our React app can communicate with. To do this, we will build a simple REST API with Python using the Django framework.
Building The Books API with Django
We’ll create the books API using Django. Let’s create a new dummy project:
If you don’t have pipenv installed already, you will need to install it by running the following in the terminal:
pip install pipenv
Using the integrated terminal, activate the pipenv shell to create the Django project:
When done, run the following commands to install Django and Django REST Framework:
Next, we create a Django project and create a Django app.
This will create new folders in the books-api folder. Update INSTALLLED_APPS in settings.py to include books and django-rest-framework.
Our database model will just contain the Book Model. Add the following to models.py.
Our Book model contains 4 fields: title, description, author, and created_at.
- The title field stores the title of the book.
- The description stores the description of a book.
- The author field stores the author of the book.
These fields will be provided from our frontend — the react app we built earlier.
- The created_at field will be auto inserted based on the time the book is created.
Run the following command to create the necessary migrations and tables.
In Terminal+, ensure you are at books-api/booksApi/ then run:
Next, we will create a serializer. Serializers are used to convert our data to JSON which will be returned when we visit the endpoints.
Next, we update views.py to add our API views.
Finally, we need to add our endpoints. Create a urls.py in books-api/booksApi/books
And update books-api/booksApi/booksApi/urls.py to look like:
Start the Django server by running the snippet below in Terminal+:
The endpoint is can now be viewed at http://localhost:8000/api/books/. Before we consume the API in our react app, we need to solve one issue that will probably arise — CORS. Run the following to install a package to help with CORS:
When that is done, add the following to the list of INSTALLED_APPS in settings.py as we did earlier. We will also need to add some new middleware.
And finally, add the line below to allow all origins to access the API:
Run the server using the integrated terminal:
Consuming the API with React
We will be using fetch to consume the books API. Add the following to index.js:
As seen above, we remove the initial content of the books array and we just initialize it with an empty array.
componentDidMount hook, we fetch the content of the book api and on line 10, update the state to use the data recieved. Currently, there is no book in the database, so every call to http://localhost:8000/api/books/ will return an empty array.
createNewBook function to use the API for book creation:
createNewBook sends a POST request to the books API with the book data gotten from the form. The API responds with the newly created book containing some additional data like id and created_at.
Next up, we need to modify books — update. To update a book, we need to send a PUT request.
As seen above, we are sending a put request to the url/<bookId>. This shows which book we are looking to update. If the update is successful, we update the state.
We are using the same state update mechanism as before. You might want to send another request to fetch all the books from the API but that will take more time.
The last method to modify is the delete action, just like this:
The delete action is probably the simplest. We send a DELETE request to the same URL as used for update, the delete action does not return any data so we can just update the state.
With this functional CRUD application, we have just learned how to build a simple REST API using the Django framework, and a frontend in React which consumes the API. In case you want to take a closer look at the code, take a look at the Github repository for the React codebase, and for the Django API.
If you haven’t tried CodeMix yet, go and experiment with all the features it has to offer! Be part of the community with the CodeMix Insiders program, or use the integrated LiveChat to receive full support from the CodeMix team right inside your IDE.