Saturday, 6 July 2019

django 55 react redux registration

click register





new user chuanshuoge registered

login as chuanshuoge

create a new post
#django/api/apiview

from music.models import Album, Song
from music.api.serializers import MusicSerializer, UserSerializer, SongSerializer, PasswordSerializer
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from django.http import Http404
from django.contrib.auth.models import User
from django.shortcuts import get_object_or_404
from rest_framework.decorators import authentication_classes, permission_classes
from django.contrib.auth.password_validation import validate_password
from django.core import exceptions

class AlbumList(APIView):
    def get(self, request, format=None):
        username = request.GET.get('author')
        data_length = request.GET.get('data_length')

        #filter by author
        if username==None:
            albums = Album.objects.all()
        else:
            author_id = get_object_or_404(User, username=username).pk
            albums = Album.objects.filter(author=author_id).order_by('-date_posted')

        #filter by data length
        if data_length!=None:
            try:
                int(data_length)
            except ValueError:
                return Response('data length is invvalid', status=status.HTTP_406_NOT_ACCEPTABLE)
            else:
                albums = albums[:int(data_length)]

        serializer = MusicSerializer(albums, many=True)
        return Response(serializer.data)

    def post(self, request, format=None):
        serializer = MusicSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

class AlbumDetail(APIView):

    def get_object(self, pk):
        try:
            return Album.objects.get(pk=pk)
        except Album.DoesNotExist:
            raise Http404

    def get(self, request, pk, format=None):
        album = self.get_object(pk)
        serializer = MusicSerializer(album)
        return Response(serializer.data)

    def put(self, request, pk, format=None):
        album = self.get_object(pk)

        #only owner can edit
        if album.author != request.user:
            return Response({"detail": "You do not have permission to perform this action."},
                            status= status.HTTP_403_FORBIDDEN)

        serializer = MusicSerializer(album, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    def delete(self, request, pk, format=None):
        album = self.get_object(pk)

        # only owner can delete
        if album.author != request.user:
            return Response({"detail": "You do not have permission to perform this action."},
                            status=status.HTTP_403_FORBIDDEN)

        album.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

class UserList(APIView):
    def get(self, request, format=None):
        users = User.objects.all()
        serializer = UserSerializer(users, many=True)
        return Response(serializer.data)

@authentication_classes([])
@permission_classes([])
class UserRegister(APIView):
    def post(self, request, format=None):
        serializer = UserSerializer(data=request.data)
        if serializer.is_valid():

            #email has to be unique
            email = request.POST.get('email')
            unique_email = User.objects.filter(email=email).count()
            if(unique_email > 0):
                return Response({'email': 'email already exist'}, status=status.HTTP_406_NOT_ACCEPTABLE)

            #validate password
            password = request.POST.get('password')
            try:
                validate_password(password)
            except exceptions.ValidationError as e:
                return Response(e.messages, status=status.HTTP_406_NOT_ACCEPTABLE)
            else:
                pass
            #register new user
            serializer.save()
            #set password for new user
            username = serializer.data.get('username')
            newUser = User.objects.get(username=username)
            newUser.set_password(password)
            #save password for new user
            newUser.save()

            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

class SongList(APIView):
    def get(self, request, format=None):
        songs = Song.objects.all()
        serializer = SongSerializer(songs, many=True)
        return Response(serializer.data)

class UpdatePassword(APIView):
    def get_object(self, queryset=None):
        return self.request.user

    def put(self, request, *args, **kwargs):
        currentUser = self.get_object()
        serializer = PasswordSerializer(data=request.data)

        if serializer.is_valid():
            # Check old password
            old_password = serializer.data.get("old_password")
            if not currentUser.check_password(old_password):
                return Response({"old_password": ["Wrong password."]},
                                status=status.HTTP_400_BAD_REQUEST)
            # set_password also hashes the password that the user will get
            currentUser.set_password(serializer.data.get("new_password"))
            currentUser.save()
            return Response(status=status.HTTP_204_NO_CONTENT)

        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

-----------------------------
#django/api/serializers

from rest_framework import serializers
from django.contrib.auth.models import User

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ('id', 'username', 'email')

----------------------------------
#django/api/urls

from django.urls import path
from music.api import apiview
from rest_framework.authtoken import views

app_name = 'musicAPI'

urlpatterns = [
...
    path('user_register/', apiview.UserRegister.as_view(), name='UserRegister'),
]

----------------------------------------
//react/pages/registerUser

import React, { Component } from 'react';
import '../App.css';
import { registerUser } from '../redux/actions/registerUser';
import { connect } from 'react-redux';
import { Input } from 'antd';
import { Button } from 'reactstrap';
import { MdEmail, MdAccessibility } from "react-icons/md";
import { Fa500Px } from "react-icons/fa";

class RegisterUser extends Component {

    constructor(props) {
        super(props);

        this.state = {
            email: '',
            username: '',
            password: '',
        };
    }

    inputChange = (e, p) => {
        this.setState({ [p]: e.target.value });
    }

    formSubmit = (e) => {
        e.preventDefault();

        const formData = new FormData();
        formData.set('email', this.state.email);
        formData.set('username', this.state.username);
        formData.set('password', this.state.password);

        this.props.dispatch(registerUser(formData));
    }

    render() {
        return (
            <form style={{ marginLeft: '10px', width: '300px' }}
                onSubmit={(e) => this.formSubmit(e)}>
                <legend>Register User</legend>
                <hr />
                <p style={{ color: 'red' }}>{this.props.error}</p>
                {this.props.registered ? <p style={{ color: 'green' }}>Registration success</p> : null}
                <Input placeholder="username" required='required'
                    prefix={<MdAccessibility style={{ color: 'rgba(0,0,0,.25)' }} />}
                    onChange={(e) => this.inputChange(e, 'username')}
                    style={{ marginTop: '5px' }}
                />
                <Input placeholder="email" required='required' type='email'
                    prefix={<MdEmail style={{ color: 'rgba(0,0,0,.25)' }} />}
                    onChange={(e) => this.inputChange(e, 'email')}
                    style={{ marginTop: '15px' }}
                />
                <Input.Password placeholder="password" required='required'
                    prefix={<Fa500Px style={{ color: 'rgba(0,0,0,.25)' }} />}
                    onChange={(e) => this.inputChange(e, 'password')}
                    style={{ marginTop: '15px' }}
                />
                <Button color="success" type='submit' size='sm'
                    style={{ marginTop: '15px' }}
                >Submit</Button>
            </form>
        );
    }
}

export default connect(
    (store) => {
        return {
            registered: store.users.registered,
            error: store.users.error
        };
    }
)(RegisterUser);

--------------------------------------
//redux/actions/registerUser

import axios from 'axios';

export function registerUser(data) {
    return {
        type: "register_user",
        payload: axios({
            method: 'post',
            url: 'http://127.0.0.1:8000/api/user_register/',
            data: data,
        })
    }
}

--------------------------------
//redux/reducers/userReducer

export default function reducer(
    state = {
        users: [],
        fetching: false,
        fetched: false,
        registering: false,
        registered: false,
        error: ''
    },
    action
) {
    switch (action.type) {
        case "fetch_users_PENDING": {
            return { ...state, fetching: true, fetched: false }
        }

        case "fetch_users_FULFILLED": {
            return {
                ...state,
                fetching: false,
                fetched: true,
                users: action.payload.data,
                error: ''
            }
        }

        case "fetch_users_REJECTED": {
            return {
                ...state,
                fetching: false,
                error: action.payload.toString()
            }
        }

        case "register_user_PENDING": {
            return { ...state, registering: true, registered: false, error: '' }
        }

        case "register_user_FULFILLED": {
            return {
                ...state,
                registering: false,
                registered: true,
                error: ''
            }
        }

        case "register_user_REJECTED": {
            return {
                ...state,
                registering: false,
                error: JSON.stringify(action.payload.response.data),
            }
        }

        default:
            break;
    }
    return state;
}

reference:
https://stackoverflow.com/questions/27085219/how-can-i-disable-authentication-in-django-rest-framework
https://stackoverflow.com/questions/36414804/integrate-django-password-validators-with-django-rest-framework-validate-passwor
https://stackoverflow.com/questions/17312831/what-does-request-user-refer-to-in-django

No comments:

Post a Comment