Giter Site home page Giter Site logo

terkea / django_react_template Goto Github PK

View Code? Open in Web Editor NEW
19.0 5.0 1.0 1.25 MB

A Django and React Template that will help you skip a lot of boilerplate and initial project setup

License: GNU General Public License v2.0

Dockerfile 0.86% HTML 1.06% CSS 1.05% JavaScript 75.64% Python 20.88% Shell 0.51%
django react javascript antd passwordless passwordless-login passwordless-authentication antd-design django-rest-framework react-redux

django_react_template's Introduction

A Django & React Template

All Contributors

A Django and React Template that will help you skip a lot of boilerplate and initial project setup, which features:

  • Passwordless user authentification/registration, which is a more modern and secure way of logging in, used by Medium, Microsoft and plenty more.
  • Functionality to update the user profile.
  • Responsiveness

This template is based on the Ant Design ui kit and is powered by the Django REST Framework.

login login login

Motivation

When starting a new project it can be incredibly time consuming to reach the milestone that will finally let you start implementing your ideas, and doing actual work.

The goal of this project is to be just that, a solid modern project template that you can easily pick up on and not worry too much about the boilerplate.

DISCLAIMER

Please bear in mind that this is a development version, for production you would ideally have to change a lot of settings and it is recommended that you go through them yourself and check what needs to be changed to make it safe for production deployment.

Installation

Option 1

> Docker

To install it with docker, you only need to run the following command:

# Make sure that you have Docker installed, use -d to hide logs
docker-compose up --build

You can access it through localhost:3000 by default.

To Remove the containers use:

docker-compose down

Option 2

> React

cd react
# Install the node packages
npm install
# Start the App in Development Mode
npm start

> Django

cd django
# Create the virtual environment
python -m venv env 
# You need to activate everytime you open a new terminal
./env/Scripts/activate
# Install the requirements
pip install -r requirements.txt 
python manage.py makemigrations
python manage.py migrate
# In case django complains about migrations at any point go with
python manage.py migrate --run-syncdb
# Run the server
python manage.py runserver

You can access it through localhost:3000 by default.

Documentation

> React

Introduction

This documentation will assume a fair knowledge of React as well as some of the tools that we are used, including:

Updating the Base URL

To change the Base URL all that you have to do is change it inside the file axiosConfig.js.

const instance = axios.create({
    baseURL: 'http://localhost:8000'
});

Routes

The App.js component (App.js) is being used as the main router and it is here that the main routes are defined. If you want to define other routes in your sub-components, you should not use <Router> again.

As an example of this you can take the My Profile page, where a Switch component is used:

MyProfile

<Switch>
    <Route exact path={`${basicPATH}`} component={BasicSettings} />
    <Route exact path={`${securityPATH}`} component={SecuritySettings} />
</Switch>

As you may have noticed the path is not a literal string, this is so that it can accomodate for any future path changes, you can implement this with the following code:

// ...
// inside the component
const getUrl = () => {
    // This function can be used to reliably get the current url with 1 slash at the end
    const inconsistentUrl = props.match.url;
    const lastUrlChar = inconsistentUrl[inconsistentUrl.length - 1];
    return ((lastUrlChar === '/') ? inconsistentUrl : (inconsistentUrl + '/'));
}

const url = getUrl();
//paths: 
const basicPATH = `${url}basic/`;
const securityPATH = `${url}security/`
// ...

Note: Unfortunately the getUrl can not be made into a helper function, at least for now.

Customization - Antd Theming

antd theming ANTD is using Less as the development language for styling. A set of less variables are defined for each design aspect that can be customized to your needs. There are some major variables below, all less variables could be found in Default Variables.

Your custom changes should go in react/config-overrides.js.

For all of the potential customizations don't hesitate to check their documentation which covers them all.

Layout Component

Layout Component (Layout.js)

In this template the layout component is to be used to display the main content of the webpage.

Navbar

  • When logged out:

    navbar1

  • When logged in:

    navbar2

To add more links you can just add more Menu.Item under Menu and make sure that the Link to is the same as the Menu.Item key without the / at the end, otherwise it won't show as selected, you can look at how this was done for the existing ones.

Tip: make sure that the Menu.Item is not nested in any other component and that it goes right under Menu.

Sessions

The session is managed by the Redux store.

When the page is loaded, an action actions.authCheckState() is dispatched, from App.js, to the store actions which just checks for the existence of a token in localStorage and if there is no token in localStorage it logs the user out, otherwise it checks the token's validity and dispatches some other actions check authCheckState() to see the code.

When the user is not logged in the store looks the following:

user store

When the user is logged in the store looks the following:

user store

Note: To visualize the above you need to get the Redux DevTools Extension.

  • user
    • loading - is a boolean that can used, for example, in the conditional rendering of elements, this is used in Login and My Profile.
    • error - is a boolen, that can be used, for example, to set a given element to show that it errored out, such as an icon.
    • email - note that email is moved inside profile once the user has logged in.

Login / Register

Login (Login.js) / Register (App.js)

Both of these do exactly the same thing, they sign in the user whether they are registered or not, the reason why a registration page exists is to not confuse users that may be looking for the common register/login pages.

My Profile

My Profile (MyProfile/index.js)

More options will be added in the future, these existing ones are just a proof of concept or example.

Notifications

Notifications (notificationHelpers.js)

The current notification system is based on the Ant Design notifications and it is implemented as a callback for actions that are dispatched to the store, this callback is optional but it is currently the way to run a notification when the axios request returns its promise.

A good example of how to use these notifications can be seen in Basic.js.

Basic.js

import { runNotifications } from '../../../Helpers/notificationHelpers';
// ...
// Inside the component:
    const onFinish = values => {
        props.updateProfile(localStorage.getItem('token'), values, runNotifications)
    };
// ...
const mapDispatchToProps = dispatch => {
    return {    // map the callback just like a regular argument, in whatever action you want to dispatch
        updateProfile: (token, profile, callback) => dispatch(actions.updateProfile(token, profile, callback))
    }
}
// ...

user.js

// ...
// when you define your action make sure to define an empty anonymous function as the
// default function in case you don't want to call notifications on the given action
export const updateProfile = (token, profile, notificationCallback = (message, outcome) => { }) => dispatch => {
    // ...
    // axios request
        .then(res => {
            // ...
            notificationCallback("Profile Updated Successfully", "SUCCESS");
        })
        .catch(err => {
            // ...
            notificationCallback(err.message, "ERROR");
        })
}
// ...

How to add dependencies for Docker

TODO

> Django

Django user model

Custom fields can be appended to the default userprofile model that we provided by editing the model itself and the serializer. which can be located in django/api/models/ and `django/api/serializers/

Configuring the SMTP Server

Update the following constants to get your smtp server up and running

# SMTP SETTINGS
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_USE_TLS = True
EMAIL_PORT = 587
EMAIL_HOST_USER = ''
EMAIL_HOST_PASSWORD = ''
PASSWORDLESS_AUTH = {
    'PASSWORDLESS_AUTH_TYPES': ['EMAIL'],
    'PASSWORDLESS_EMAIL_NOREPLY_ADDRESS': "[email protected]",
}

Then be sure you change from backends console to smtp

# EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'

Contributors ✨

Thanks goes to these wonderful people (emoji key):


AName* name("Vadim");

⚠️ 📖 🚧 👀 💻

Marian Terchila

⚠️ 📖 🚧 👀 💻

This project follows the all-contributors specification. Contributions of any kind welcome!

django_react_template's People

Contributors

allcontributors[bot] avatar terkea avatar vadimstasiev avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

Forkers

vadimstasiev

django_react_template's Issues

login state

After you log in this error kicks in, this question might be related to.

index.js:1 Warning: Cannot update during an existing state transition (such as within `render`). Render methods should be a pure function of props and state.
    in Login (created by ConnectFunction)
    in ConnectFunction (created by Context.Consumer)
    in withRouter(Connect(Login)) (created by Context.Consumer)
    in Route (at BaseRouter.js:11)
    in Switch (at BaseRouter.js:9)
    in BaseRouter (at App.js:20)
    in div (at Layout.js:47)
    in main (created by Basic)
    in Basic (created by Context.Consumer)
    in Content (at Layout.js:46)
    in section (created by Context.Consumer)
    in BasicLayout (created by Context.Consumer)
    in Layout (at Layout.js:11)
    in CustomLayout (created by ConnectFunction)
    in ConnectFunction (created by Context.Consumer)
    in withRouter(Connect(CustomLayout)) (at App.js:19)
    in Router (created by BrowserRouter)
    in BrowserRouter (at App.js:18)
    in div (at App.js:17)
    in App (created by ConnectFunction)
    in ConnectFunction (at src/index.js:21)
    in Provider (at src/index.js:20)
console.<computed> @ index.js:1
r @ react_devtools_backend.js:6
printWarning @ react-dom.development.js:88
error @ react-dom.development.js:60
warnAboutRenderPhaseUpdatesInDEV @ react-dom.development.js:23283
scheduleUpdateOnFiber @ react-dom.development.js:21196
enqueueSetState @ react-dom.development.js:12661
push../node_modules/react/cjs/react.development.js.Component.setState @ react.development.js:471
(anonymous) @ Router.js:33
listener @ history.js:155
(anonymous) @ history.js:173
notifyListeners @ history.js:172
setState @ history.js:288
(anonymous) @ history.js:369
confirmTransitionTo @ history.js:145
push @ history.js:350
Login @ Login.js:37
renderWithHooks @ react-dom.development.js:14825
updateFunctionComponent @ react-dom.development.js:17058
beginWork @ react-dom.development.js:18643
beginWork$1 @ react-dom.development.js:23210
performUnitOfWork @ react-dom.development.js:22185
workLoopSync @ react-dom.development.js:22161
performSyncWorkOnRoot @ react-dom.development.js:21787
(anonymous) @ react-dom.development.js:11111
unstable_runWithPriority @ scheduler.development.js:653
runWithPriority$1 @ react-dom.development.js:11061
flushSyncCallbackQueueImpl @ react-dom.development.js:11106
flushSyncCallbackQueue @ react-dom.development.js:11094
batchedUpdates$1 @ react-dom.development.js:21893
notify @ Subscription.js:19
notifyNestedSubs @ Subscription.js:92
handleChangeWrapper @ Subscription.js:97
dispatch @ redux.js:222
e @ VM11564:1
(anonymous) @ index.js:11
dispatch @ redux.js:638
(anonymous) @ auth.js:51
Promise.then (async)
(anonymous) @ auth.js:42
(anonymous) @ index.js:8
dispatch @ VM11564:1
onAuth @ Login.js:115
onFinish @ Login.js:28
onFinish @ Form.js:73
(anonymous) @ useForm.js:590
Promise.then (async)
FormStore.submit @ useForm.js:585
onSubmit @ Form.js:118
callCallback @ react-dom.development.js:188
invokeGuardedCallbackDev @ react-dom.development.js:237
invokeGuardedCallback @ react-dom.development.js:292
invokeGuardedCallbackAndCatchFirstError @ react-dom.development.js:306
executeDispatch @ react-dom.development.js:389
executeDispatchesInOrder @ react-dom.development.js:414
executeDispatchesAndRelease @ react-dom.development.js:3278
executeDispatchesAndReleaseTopLevel @ react-dom.development.js:3287
forEachAccumulated @ react-dom.development.js:3259
runEventsInBatch @ react-dom.development.js:3304
runExtractedPluginEventsInBatch @ react-dom.development.js:3514
handleTopLevel @ react-dom.development.js:3558
batchedEventUpdates$1 @ react-dom.development.js:21902
batchedEventUpdates @ react-dom.development.js:1060
dispatchEventForLegacyPluginEventSystem @ react-dom.development.js:3568
attemptToDispatchEvent @ react-dom.development.js:4267
dispatchEvent @ react-dom.development.js:4189
unstable_runWithPriority @ scheduler.development.js:653
runWithPriority$1 @ react-dom.development.js:11061
discreteUpdates$1 @ react-dom.development.js:21918
discreteUpdates @ react-dom.development.js:1071
dispatchDiscreteEvent @ react-dom.development.js:4168
Show 8 more frames

Authentication with JWT?

I see you have drfpasswordless in the settings.py
Is JWT something you'd be interested in adding to this project?

same store

Currently, the login and signup components are sharing the same error state.

navbar active button

when you get redirected from one page to another the Menu.Item active class doesn't kick in, leaving the current page activated while browsing some other page.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.