Editor’s note: This post was updated on 15 July 2022 to reflect the most recent versions of React and Django, as well as to add information about how to send data between React and Django.
Django is one of the most complete web development frameworks available. It’s fast, secure, and scalable. With the power of Python, we can get an application up and running in just about no time. It manages everything, from the database to the final HTML sent to the client.
However, with the advent of single-page applications (SPAs), it’s become increasingly common to create applications that use Django only to provide an API that responds to JSON data consumed by applications developed in the most varied JavaScript frameworks.
This architecture, which separates the frontend from the backend, allows a better decoupling of both interfaces so that teams can develop in their respective domains completely independently.
It also enables multiple client apps to interact with the same API, while ensuring data integrity and business rules, and a variety of user interfaces.
On the other hand, two different projects generate even more work: two separate deployments, two environments to configure, etc. One way to simplify this is to use Django’s own capabilities to serve static files. After all, the frontend is nothing more than a set of files of this type.
In this article, we’ll outline how to create a simple CRUD API with Django and its famous Django REST framework free from common Cross-Origin Resource Sharing (CORS) issues. We’ll also learn how to integrate Django with a React app.
We’ll cover everything, from setup and configuration to customizing our frontend components and backend API:
You can expose your API in different ways with Django. You can use a REST API, a GraphQL API, or RPC API, each with their own pros and cons. While GraphQL is a safe bet, we’re going to use traditional REST endpoints.
By the end of this tutorial, this will be our final output:
For this article, we’re not going to cover how to install basic tools, so make sure you review this list of what you need to have set up in your machine before you can follow this article:
If you’re using Linux, chances are that Python is already installed. Run the python3 -V
command to check.
In certain environments, you may have have Python 2 and Python 3 installed. In this case, you should use python3
instead of python
when running commands. You can avoid this by installing PyEnv to be able to switch which version of Python the python
command uses.
In the article, we’ll also make use of a handy Python feature called venv
, also known as Python Virtual Environment. This feature basically allows developers to create a folder that’ll act exactly like a specific Python environment.
Open your preferred IDE to an empty directory and follow along as we begin. Remember to always give your directory a good name.
Let’s run the command inside this folder to create our venv
:
python -m venv logrocket_env
After you enter the created folder, you’ll see some other files, such as bin
, lib
, and share
. These files guarantee you are in an isolated context of Python configuration. To make use of the bin
file, you have to make sure it’s activated:
source ./logrocket_env/bin/activate
Then your command line will look like the example below, with the name in parentheses confirming that you’re in the venv
:
(logrocket_env) username@localhost: _
Note that once you are inside the venv
, you can use the commands pip
or python
normally. If you are outside the venv
, you must use pip3
and python3
.
That’s it. You’re good to go with your venv.
Next, let’s start installing Django by running the following command inside of your venv
:
pip install django djangorestframework django-cors-headers
Note that we’re installing two more dependencies for our API:
django-cors-headers
: an app for handling the server headers required for CORSThese dependencies are useful for when we try to access the API from a different application. In this case, they help to connect Django and React.
We’ll also make use of two other Django features designed to help us with boilerplate configs: django-admin
and manage.py
.
django-admin
is Django’s automatic admin interface. It’s basically a command-line utility to perform handy operations with Django.
manage.py
is a script that will help us manage our database, create tables from our models, handle migration and versioning, and properly create our projects.
Now, we’ll run the following command to create our API project — remember that you must be inside the venv
:
django-admin startproject django_react_proj
After the project is created, check the root folder for the manage.py
file we mentioned earlier. We’ll explore the rest of the files further.
Let’s start our Django configuration using the settings.py
file inside the django_react_proj/
folder. When you open this file, you’ll see a lot of configs. INSTALLED_APPS
is the one that matters to us.
Add the following three lines to the array:
INSTALLED_APPS = [ ... 'rest_framework', 'corsheaders', 'students' ]
These three lines are the dependencies we’ve previously installed, along with the name of our to-be-created API folder.
Now, add the following into the MIDDLEWARE
array:
MIDDLEWARE = [ .... 'corsheaders.middleware.CorsMiddleware', 'django.middleware.common.CommonMiddleware', ]
These correspond to a filter that will intercept all of our application’s requests and apply CORS logic to them.
However, since we’re working full localhost
, we’ll disable the CORS feature by adding the following to the same file:
CORS_ORIGIN_ALLOW_ALL = True
Great! Now, let’s move on to the models and views of our application.
In order to create some preset files, we’ll make use of the manage.py
script once again. This time, run the following:
django-admin startapp students
After that, a students/
folder will be created, along with models.py
and views.py
. Initially, these files will have little to no content inside.
Let’s start by removing everything currently in the models.py
file and adding our models instead:
from django.db import models class Student(models.Model): name = models.CharField("Name", max_length=240) email = models.EmailField() document = models.CharField("Document", max_length=20) phone = models.CharField(max_length=20) registrationDate = models.DateField("Registration Date", auto_now_add=True) def __str__(self): return self.name
Notice that our Student
class extends from Django’s Model
class. This will make our lives easier once it connects directly to the Django models framework, which we’ll use to create our database tables.
It’s also important to set all the fields with the proper types and configurations, including max length
if it’s required, description
, autocreation
, etc.
Now, let’s export our models to the database through Django’s migrations feature.
Migrations are Django’s way of propagating changes you make to your models — such as adding a field or deleting a model — into your database schema.
They’re designed to be mostly automatic, but you’ll need to know when to make migrations, when to run them, and what common problems you may run into.
Go to the root of the application and run the following:
python manage.py makemigrations
You’ll see the name and location of the file created for versioning these changes. Then, we need to apply the changes to the database itself:
python manage.py migrate
The next step consists of creating what we call a data migration file. It represents the direct manipulation of data into the database. To create this file, run the following command:
python manage.py makemigrations --empty --name students students
Note that the versioning is made upon numbers by the end of the file to maintain the order.
After that, go to the django_react_proj/students/migrations/
folder and change the content to the following:
from django.db import migrations def create_data(apps, schema_editor): Student = apps.get_model('students', 'Student') Student(name="Joe Silver", email="[email protected]", document="22342342", phone="00000000").save() class Migration(migrations.Migration): dependencies = [ ('students', '0001_initial'), ] operations = [ migrations.RunPython(create_data), ]
In short, the create_data
method recovers the Student
model object and creates initial data, just so that our database isn’t empty when the API starts.
The dependencies
property relates the other files to be considered into the migration process.
The operations
are basically the actions Django has to perform once the migration is triggered.
Now we’re ready to run the migrate command again. In the django_react_proj/
folder, run:
python manage.py migrate
Now it’s time to dive into the REST API that we’re going to build on top of Django REST framework. Here, you’ll get in touch with two main worlds: views and URLs. A view is the initial entrypoint of a request made upon a specific endpoint served by a URL.
This is all mapped by the Django REST framework once we connect the function itself to the endpoint. We’ll also make use of serializers.
They allow complex data, such as QuerySets and model instances, to be converted to native Python datatypes that can then be easily rendered into JSON. Let’s start there.
Create a new file serializers.py
into the students/
folder and add the following content:
from rest_framework import serializers from .models import Student class StudentSerializer(serializers.ModelSerializer): class Meta: model = Student fields = ('pk', 'name', 'email', 'document', 'phone', 'registrationDate')
The Meta
class is important here because it defines the metadata information that our model has (database) and that must be converted to the Student
class.
Next, let’s open the urls.py
file located in the django_react_proj/
folder and change its content to the following:
from django.contrib import admin from django.urls import path, re_path from students import views urlpatterns = [ path('admin/', admin.site.urls), re_path(r'^api/students/$', views.students_list), re_path(r'^api/students/([0-9])$', views.students_detail), ]
The admin
path was already there. The only things we added are the students
endpoints. Note that each of them is connected to a to-be-created view function, so this is the place where we route our requests.
The first endpoint will handle both creations (POST
) and listing (GET
). The second one will remove (DELETE
) or update (PUT
) the data of a single student. Simple, right?
Now, let’s go to the views. Open up the students/views.py
file and copy in the following code:
from rest_framework.response import Response from rest_framework.decorators import api_view from rest_framework import status from .models import Student from .serializers import * @api_view(['GET', 'POST']) def students_list(request): if request.method == 'GET': data = Student.objects.all() serializer = StudentSerializer(data, context={'request': request}, many=True) return Response(serializer.data) elif request.method == 'POST': serializer = StudentSerializer(data=request.data) if serializer.is_valid(): serializer.save() return Response(status=status.HTTP_201_CREATED) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) @api_view(['PUT', 'DELETE']) def students_detail(request, pk): try: student = Student.objects.get(pk=pk) except Student.DoesNotExist: return Response(status=status.HTTP_404_NOT_FOUND) if request.method == 'PUT': serializer = StudentSerializer(student, data=request.data,context={'request': request}) if serializer.is_valid(): serializer.save() return Response(status=status.HTTP_204_NO_CONTENT) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) elif request.method == 'DELETE': student.delete() return Response(status=status.HTTP_204_NO_CONTENT)
The first method, students_list
, is handling both GET
and POST
operations over the root endpoint of our API.
This means every time we make a request over http://localhost:8000/api/students with GET
and POST
HTTP verbs, we’ll execute this method.
The first thing is to get all the students from our model through the Student
object. It provides an implicit object called object
with a method to access the entire database: all()
.
Then, we pass the result to our serializer, which will take care of the converting process before we return it as a response.
For the POST
method, note that we’re first calling the is_valid()
method on the serializer to ensure that the data received is conformed with our model. Otherwise, the serializer would throw an exception here. If all is fine, we save it to the datastore.
The next PUT
and DELETE
operations are pretty much the same, changing only the HTTP verbs and the responses.
That’s it!
Now, let’s run our Django application in order to test these endpoints. Run the following command into the root folder:
python manage.py runserver
After you see the log showing our server is up and running, go to the browser and access http://localhost:8000/api/students/. You’ll see something like this:
What you see here is Django’s Browsable API, a human-friendly HTML output that allows for easy browsing of resources, as well as forms for submitting data to the resources. It’s very handy for testing your endpoints easily without having to make use of cURL
or other UI tools.
You can also use the other HTTP methods through the form in the bottom of the image. Go ahead and play around with it.
Now it’s frontend time.
It’s important to note that we’re not going to dive into React details here, so take some time to read up on React if you’re a beginner. The focus of this tutorial is to show you how to consume a Django API quickly from a React app.
In this article, we’ll use the latest version of React. However, feel free to use whichever version you prefer. We also won’t discuss the use of React Hooks or other side features of React, since the purpose is the API consumption itself.
Once you have Node and npm installed, let’s run the following command in the root folder of our Django project to create our React app:
npx create-react-app students-fe
If you don’t know create-react-app
, read through a quick setup guide for some help getting started.
We’ll divide our front end in some smaller components, as seen in the following figure:
The header component will store the header information, logo, etc.
The home component will be our main container, storing the rest of the other components, such as the listing of the students in a table.
We’ll also have two more components for the forms. The “update” and “add” forms will have pretty much the same components and will be placed in modals. Having both functions depends on which modal is active now.
Let’s go right to it. We’ll use Bootstrap with React for styling with the powerful reactstrap
package. We’ll also use the promise-based HTTP client Axios to make HTTP request calls to our Django API.
First, we’ll add some important dependencies to our students-fe
project, so cd
into the project and run the following command:
npm install bootstrap reactstrap axios --save
Next, go to the src/index.js
file and add the following import statement:
import "bootstrap/dist/css/bootstrap.min.css";
In your src/
folder, create another folder called constants
, and then a file index.js
. This file will store the utility constants of our React project. Add a single constant to hold the URL of our API:
export const API_URL = "http://localhost:8000/api/students/";
Then, let’s begin creating our components, starting with the header.
Create another folder called components
and, within it, a JavaScript file called Header.js
. Add the following content:
import React, { Component } from "react"; class Header extends Component { render() { return ( <div className="text-center"> <img src="https://logrocket-assets.io/img/logo.png" width="300" className="img-thumbnail" style={{ marginTop: "20px" }} /> <hr /> <h5> <i>presents</i> </h5> <h1>App with React + Django</h1> </div> ); } } export default Header;
This is pretty much static HTML represented under JSX. Nothing much of note here.
Now, let’s change our strategy and build the next components from the innermost to the outermost ones. In the same components
folder, create a new file called NewStudentForm.js
and add the following:
import React from "react"; import { Button, Form, FormGroup, Input, Label } from "reactstrap"; import axios from "axios"; import { API_URL } from "../constants"; class NewStudentForm extends React.Component { state = { pk: 0, name: "", email: "", document: "", phone: "" }; componentDidMount() { if (this.props.student) { const { pk, name, document, email, phone } = this.props.student; this.setState({ pk, name, document, email, phone }); } } onChange = e => { this.setState({ [e.target.name]: e.target.value }); }; createStudent = e => { e.preventDefault(); axios.post(API_URL, this.state).then(() => { this.props.resetState(); this.props.toggle(); }); }; editStudent = e => { e.preventDefault(); axios.put(API_URL + this.state.pk, this.state).then(() => { this.props.resetState(); this.props.toggle(); }); }; defaultIfEmpty = value => { return value === "" ? "" : value; }; render() { return ( <Form onSubmit={this.props.student ? this.editStudent : this.createStudent}> <FormGroup> <Label for="name">Name:</Label> <Input type="text" name="name" onChange={this.onChange} value={this.defaultIfEmpty(this.state.name)} /> </FormGroup> <FormGroup> <Label for="email">Email:</Label> <Input type="email" name="email" onChange={this.onChange} value={this.defaultIfEmpty(this.state.email)} /> </FormGroup> <FormGroup> <Label for="document">Document:</Label> <Input type="text" name="document" onChange={this.onChange} value={this.defaultIfEmpty(this.state.document)} /> </FormGroup> <FormGroup> <Label for="phone">Phone:</Label> <Input type="text" name="phone" onChange={this.onChange} value={this.defaultIfEmpty(this.state.phone)} /> </FormGroup> <Button>Send</Button> </Form> ); } } export default NewStudentForm;
Here, we have some important things going on.
In the first lines, we’re importing some reactstrap
components for the first time, including Form
, Button
, and other components that will comprise our form.
Then, we created our state
object with the corresponding properties of our NewStudentForm
model. This is going to be useful for manipulating each prop individually.
The componentDidMount
function will run after the component finishes its startup, so we can recover the student’s props
from the parent component (this.props
) here, and set the state
with them (if they exist, for the editing scenario.)
The onChange
function will handle the update of each state
’s prop with the current value typed in each respective field.
The createStudent
function will deal with the HTTP POST
requests of our form. Every time we press the “submit” button, this function will be called, triggering the Axios post()
function and passing the current state
in the request’s body.
Once it’s completed, we’ll call two props
functions: resetState
to refresh the table, and toggle
to close the modal. We’ll go over how to create these later on.
The editStudent
function works almost like the previous one, but by calling our PUT
operation instead.
The defaultIfEmpty
function was created as an auxiliary function that’ll check the current value of each field in order to determine if they’re going to be filled with the value of the state
— in case any exists, for editing — or not, when creating a new student.
The render
function will just compose our form with the help of reactstrap
components. Note the onSubmit
property, which checks for a props
property called student
. If the property exists, the submit function will be for editing (the value was passed by the parent component); otherwise, it’s for creation.
Next, we’ll turn our attention to the modal component that’ll contain the form we’ve just created. For this, create a new component file called NewStudentModal.js
and add the code below:
import React, { Component, Fragment } from "react"; import { Button, Modal, ModalHeader, ModalBody } from "reactstrap"; import NewStudentForm from "./NewStudentForm"; class NewStudentModal extends Component { state = { modal: false }; toggle = () => { this.setState(previous => ({ modal: !previous.modal })); }; render() { const create = this.props.create; var title = "Editing Student"; var button = <Button onClick={this.toggle}>Edit</Button>; if (create) { title = "Creating New Student"; button = ( <Button color="primary" className="float-right" onClick={this.toggle} style={{ minWidth: "200px" }} > Create New </Button> ); } return ( <Fragment> {button} <Modal isOpen={this.state.modal} toggle={this.toggle}> <ModalHeader toggle={this.toggle}>{title}</ModalHeader> <ModalBody> <NewStudentForm resetState={this.props.resetState} toggle={this.toggle} student={this.props.student} /> </ModalBody> </Modal> </Fragment> ); } } export default NewStudentModal;
This time, the only state
prop we’re creating is the modal’s state
in order to check whether it must be open or closed.
The toggle
function (the one our form receives as a parameter) will switch the current modal’s value to the opposite every time it’s called.
In the render
function, we’re first checking if a create
boolean was passed as a parameter from the parent caller to decide if the button is for editing or creating. The buttons are created dynamically depending on what the parent said to us.
Then, the Modal
component can be mounted upon these conditions further down. Pay attention to where we’re placing the <NewStudentForm />
component we’ve just created.
The NewStudentModal
component will be placed into the StudentList.js
we’re going to create now:
import React, { Component } from "react"; import { Table } from "reactstrap"; import NewStudentModal from "./NewStudentModal"; import ConfirmRemovalModal from "./ConfirmRemovalModal"; class StudentList extends Component { render() { const students = this.props.students; return ( <Table dark> <thead> <tr> <th>Name</th> <th>Email</th> <th>Document</th> <th>Phone</th> <th>Registration</th> <th></th> </tr> </thead> <tbody> {!students || students.length <= 0 ? ( <tr> <td colSpan="6" align="center"> <b>Ops, no one here yet</b> </td> </tr> ) : ( students.map(student => ( <tr key={student.pk}> <td>{student.name}</td> <td>{student.email}</td> <td>{student.document}</td> <td>{student.phone}</td> <td>{student.registrationDate}</td> <td align="center"> <NewStudentModal create={false} student={student} resetState={this.props.resetState} /> <ConfirmRemovalModal pk={student.pk} resetState={this.props.resetState} /> </td> </tr> )) )} </tbody> </Table> ); } } export default StudentList;
Here, the focus is explicitly the students
listing and nothing else. Be careful not to mix different logic and rules that don’t belong here.
The heart of this component is the iteration over the students
prop we’ll receive from the parent component (Home
). The map
function will take care of the iteration by providing a variable (student
) for us to access each value.
Again, take a look at the NewStudentModal
and ConfirmRemovalModal
components, which are just placed under the last <td>
.
The following is the content of the ConfirmRemovalModal
component:
import React, { Component, Fragment } from "react"; import { Modal, ModalHeader, Button, ModalFooter } from "reactstrap"; import axios from "axios"; import { API_URL } from "../constants"; class ConfirmRemovalModal extends Component { state = { modal: false }; toggle = () => { this.setState(previous => ({ modal: !previous.modal })); }; deleteStudent = pk => { axios.delete(API_URL + pk).then(() => { this.props.resetState(); this.toggle(); }); }; render() { return ( <Fragment> <Button color="danger" onClick={() => this.toggle()}> Remove </Button> <Modal isOpen={this.state.modal} toggle={this.toggle}> <ModalHeader toggle={this.toggle}> Do you really wanna delete the student? </ModalHeader> <ModalFooter> <Button type="button" onClick={() => this.toggle()}> Cancel </Button> <Button type="button" color="primary" onClick={() => this.deleteStudent(this.props.pk)} > Yes </Button> </ModalFooter> </Modal> </Fragment> ); } } export default ConfirmRemovalModal;
This component is also very simple; it hosts the removal operation. We’ll call this one our DELETE
endpoint.
Since it’s also a modal, we must have the state’s modal
prop too, as well as the toggle
function.
The deleteStudent
function will handle the HTTP call to delete the given student.
The rest of the code is very similar to what we’ve seen already.
Let’s build our Home.js
component now. Create the file and add the following to it:
import React, { Component } from "react"; import { Col, Container, Row } from "reactstrap"; import StudentList from "./StudentList"; import NewStudentModal from "./NewStudentModal"; import axios from "axios"; import { API_URL } from "../constants"; class Home extends Component { state = { students: [] }; componentDidMount() { this.resetState(); } getStudents = () => { axios.get(API_URL).then(res => this.setState({ students: res.data })); }; resetState = () => { this.getStudents(); }; render() { return ( <Container style={{ marginTop: "20px" }}> <Row> <Col> <StudentList students={this.state.students} resetState={this.resetState} /> </Col> </Row> <Row> <Col> <NewStudentModal create={true} resetState={this.resetState} /> </Col> </Row> </Container> ); } } export default Home;
Here, our state
will host the array of students
we’ll recover from the server.
The resetState
function (which we called earlier) will just call getStudents
, which in turn calls the GET
endpoint in our API with the full list of students.
The rest of the listing refers to the use of StudentList
and NewStudentModal
components. Feel free to organize the exhibition of your components on your own.
Next comes the last step before we can test our app. Import the Header
and Home
components to our App.js
file:
import React, { Component, Fragment } from "react"; import Header from "./components/Header"; import Home from "./components/Home"; class App extends Component { render() { return ( <Fragment> <Header /> <Home /> </Fragment> ); } } export default App;
Now, run the command npm start
and your React app will open the browser to the http://localhost:3000/ URL. Make sure to have your Django API up and running as well.
You can access the full source code of this project here.
Of course, this is only one way of doing this. The good thing about using React is that you can organize your components (or even create more components out of the ones you have) in many different ways to achieve the same goal.
In the world of SPAs, your backend APIs are practically fully independent from the frontend clients. This gives you the flexibility to change the whole architecture of your API (like switching from Django to Flask, for example) without any side effects to your React apps.
As a challenge, try to add a pagination system to your API/React app. The Django REST Framework provides support for customizable pagination styles.
Install LogRocket via npm or script tag. LogRocket.init()
must be called client-side, not
server-side
$ npm i --save logrocket // Code: import LogRocket from 'logrocket'; LogRocket.init('app/id');
// Add to your HTML: <script src="https://cdn.lr-ingest.com/LogRocket.min.js"></script> <script>window.LogRocket && window.LogRocket.init('app/id');</script>
Hey there, want to help make our blog better?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowBuild scalable admin dashboards with Filament and Laravel using Form Builder, Notifications, and Actions for clean, interactive panels.
Break down the parts of a URL and explore APIs for working with them in JavaScript, parsing them, building query strings, checking their validity, etc.
In this guide, explore lazy loading and error loading as two techniques for fetching data in React apps.
Deno is a popular JavaScript runtime, and it recently launched version 2.0 with several new features, bug fixes, and improvements […]
28 Replies to "Using React with Django to create an app: Tutorial"
Hello,
I was trying the app and stop in 2 errors:
Error: 1
========
….
re.error: unknown extension ?P[ at position 15
….
“^api/students/(?P[0-9]+)$” is not a valid regular expression: unknown extension ?P[ at position 15
Error: 2
========
whilie visiting http://localhost:8000/api/students/
“…Exception Value: name ‘StudentSerializer’ is not defined…”
How to solve these?
Thanks.
Same problem here.
Looking into it – it seems you have put the incorrect code for us to copy to serializers.py
Also the regex pattern is incorrect for python. I deleted the ?P and it worked (although I am sure thats not the real fix)
I found something to do with serializers here but struggling to figure out how to apply it https://micropyramid.com/blog/customizing-django-rest-api-serializers/
OK I managed to get it working by
1. NOTE you cannot add students to settings.py before running the migrate command as it says it cant find module students – it works by first running migrate then amending settings.py
2. on the regex – deleting ?P works (for now)
3. instead of the code above for serializers.py, rather put this code in instead:
from rest_framework import serializers
from students.models import Student
class StudentSerializer(serializers.ModelSerializer):
class Meta:
model = Student
fields = [‘name’, ’email’, ‘document’, ‘phone’, ‘registrationDate’]
1. Perhaps use P to represent pk kwarg in the view
url(r’^api/students/(?P[0-9]+)$’, views.students_detail)
2. need to add bootstrap css into /src/index.js by adding the below line
import ‘bootstrap/dist/css/bootstrap.min.css’;
3. define Student model id as pk field in StudentSerializer or call id in Serializer and update react to use student.id instaed of student.pk
Hi Diogo,
The ‘python manage.py startapp students’ command which you have mentioned in the article is incorrect the correct command is as follows:
(logrocket_env) osi@osi-ThinkPad-T420:~/Project/django_react_proj$ django-admin startapp students
Hey guys, Im sorry for the delay. I’m going to answer everyone here, instead of individually, ok?
So, let’s break it down:
1. The ?P comes from the need for a regular expression that allows only numbers to the “pk” param. That’s it. You can read more here: https://docs.djangoproject.com/en/3.0/topics/http/urls/#using-regular-expressions
In the docs, the recommended usage is with the re_path() function. So, I’ve updated the code alike:
from django.urls import path, re_path
urlpatterns = [
path(‘admin/’, admin.site.urls),
re_path(r’^api/students/$’, views.students_list),
re_path(r’^api/students/(?P[0-9]+)$’, views.students_detail),
]
Please, let me know if it works fine with you.
2. Regarding the following code:
students.models import Student
It’s not necessary if you have the files into the same folder. Please check that.
3. Great catch with the Bootstrap import, many thanks. 🙂
I’ll update the article.
4. It’s not necessary to create an id field, but feel free to if you want a different name.
5. Kashyap, manage.py is automatically created in each Django project. It does the same thing as django-admin but also sets the DJANGO_SETTINGS_MODULE environment variable so that it points to your project’s settings.py file.
Refer to https://docs.djangoproject.com/en/3.0/ref/django-admin/ for more.
6. Finally, I’ve update the README.md on the GitHub project, so then you and everyone can check how to run the final project locally. I hope this helps. 🙂
Please, let me know if you have any other questions.
Hi Paul,
On your first point, it also works if instead of running the command
`python manage.py startapp students`
you run
`django-admin startapp students`
This completely fixed my issue with that point of the tutorial
Thanks for the rest!
It’s ok, I saw the correction above by @Paul
instead of the code above for serializers.py, rather put this code in instead:
from rest_framework import serializers
from students.models import Student
class StudentSerializer(serializers.ModelSerializer):
class Meta:
model = Student
fields = [‘name’, ’email’, ‘document’, ‘phone’, ‘registrationDate’]
hello thank for the tutorial, whoever am not able to remove student using the modal when ever i clicked on the remove button it does not work and return :
createError.js:16 Uncaught (in promise) Error: Request failed with status code 404
same as the edit button pls help
Hey Udeh, have you tried to download the source code and compare your files one by one?
Your error is too generic, it could be a lot of things. Please, do it and let me know.
It’s ok, I saw the correction above by @Paul
instead of the code above for serializers.py, rather put this code in instead:
from rest_framework import serializers
from students.models import Student
from django.db import models
class StudentSerializer(serializers.ModelSerializer):
class Meta:
model = Student
fields = ‘__all__’
The only problem I see is that I was expecting to see an article about integrating both, not using them apart, because well… this is using a development server for React and another server for Django which isn’t practical at all to implement these technologies in a production project. Anyway I’ll keep searching how to do it because there must be an efficient way. Thanks anyway.
Diogo, thank you for this article. However, you still haven’t fixed the incorrect code for the Serializers.py, as several people in the comments have suggested. I think a lot of people will be confused by that and it’s quite simple to fix.
Thanks for the artcle. I cloned the code and it workd fine and understand most ot the artcle but I can’t figure out how this Fragment:
{button}
{title}
Is able to display the edit/create fields from the imported NewStudentForm class a generic mechanism. IOW does this mechanism of rendering parts of referenced imported classes only work in modal forms or perhaps only in Fragments? Any reference to a tutorial or sample that explains this is more detail would be greatly appreciated.
Hey Carl,
So, the curly braces {} in React work to allow the injection of variables into the current JSX code, i.e, the current component formation.
Note that we’re creating the two of them right above the code, before the import into the { … }
I’d suggest you to take a look at https://stackoverflow.com/questions/43904825/what-do-curly-braces-mean-in-jsx-react
I’m sorry for that, we had an editing error. Now, it’s fixed.
Super helpful. That fixed the module not found error I got! thank you
Hello, Thanks for the wonderful tutorial. I have successfully created the student form but when click on the send button, it keeps giving an error that “this.props.resetState” is not a function. It send the data to the api created though. How do I fix this?
using django 3.0.8
if the regex for the path to CRUD operation like DELETE and PUT are not working for you i changed mine into
urlpatterns = [
path(‘admin/’, admin.site.urls),
re_path(r’^api/students/$’, views.students_list),
re_path(r’^api/students/([0-9])$’, views.students_detail)
]
and they are working how they are suppose to :
this is my function definition inside views.py
@api_view([‘PUT’, ‘DELETE’])
def students_detail(request, pk):
hope this can help anyone out there.
hey there is one problem when we click on the send button it does not do anything
.
The url path is wrong.
django.core.exceptions.ImproperlyConfigured: “^api/students/(?P[0-9]+)$” is not a valid regular expression: unknown extension ?P[ at position 15
C:\Users\3738254\code\react\example\backend\backend\urls.py changed, reloading.
Watching for file changes with StatReloader
You should have something like this:
re_path(r’^api/students/(?P\w+)/$’, views.students_detail),
or pass the pk
Access to XMLHttpRequest at ‘http://localhost:8000/api/students’ from origin ‘http://localhost:3000’ has been blocked by CORS policy: Response to preflight request doesn’t pass access control check: Redirect is not allowed for a preflight request.
For CORS issues, follow the directions here:
https://github.com/adamchainz/django-cors-headers
on react interface data is not removing and also when edit the data send does not work.
when press “yes” on toggle and edit on send data its not working?
createError.js:16 Uncaught (in promise) Error: Request failed with status code 404
at createError (createError.js:16)
at settle (settle.js:17)
at XMLHttpRequest.handleLoad (xhr.js:62)
Yes I am getting the same error. Can someone tell me what I should do?
I really appreciate the tutorial. It cleared up a lot of things – especially on the React end. That said…
> “One way to simplify this is to use Django’s own capabilities to serve static files. After all, the front end application is nothing more than a set of files of this type.”
– But the steps we follow here really don’t serve static files (HTML, JavaScript, CSS) that Django serves up. Instead we create a full blown React app for the front end and run on a node web server. The Django back end does nothing except serving the API and handing the HTTP requests from the React app. I followed a different approach where I bundle everything on the React end with webpack and serve it on a second app on Django.
> “In this article, we’ll outline how to create a simple CRUD API with Django and its famous Django REST Framework free from CORS common issues, and integrate it with a React app.”
– In the beginning I was running a simple react module that just listed the items that it got from the API with a GET request on a page and did nothing else. I also didn’t face any CORS issues. However, after I incorporated this tutorial and added the new functions in the views.py file, I started get the “Cross-Origin Request Blocked” error on Firefox. After I incorporated the “django-cors-headers” to backend and added the `CORS_ALLOWED_ORIGINS = ( ‘http://127.0.0.1:8000’, )` settings.py file the issue went away.
Other than these two secondary issues, this tutorial really worked for me. Thank you!
It seems it would be better to serve react from Django, and .gitignore.
This example is unnecessarily bloated.
Hi There,
Thank you so much for the tutorial. It worked perfectly for me!