Am realizat recent un proiect folosind Django și React. anterior eram familiarizat cu Django, dar nu cu React, făcându-mă să mă ocup de mici probleme în a face asta. Cu această ocazie, am învățat să dezvolt aplicații cu React și cum să integrez React cu Django. Așa că vă împărtășesc ceea ce am învățat, în speranța că veți obține și un beneficiu!
Vom realiza o aplicație simplă care este Movie-Rater-App care are operațiuni CRUD în ea. Trebuie să menționez că în prezent lucrez cu Django 3.0.1 și ReactJS 6.13.

Configurarea Django

În primul rând, trebuie să ne configuram mediul virtual. Voi folosi mediul virtual aici, asigurați-vă că ați instalat virtualvenv, apoi navigați la directorul în care doriți să fie proiectul și rulați:

$ pip install virtualenv
$ cd ur_project_folder

După ce ați terminat, activați mediul virtual cu:

$ virtualenv venv
$ source venv/bin/activate

Acum va trebui să instalăm câteva pachete, inclusiv Django, Django REST framework și Django CORS headers. DRF este ceea ce vom pune peste Django pentru a ne transforma proiectul într-un API, iar anteturile Django CORS sunt necesare pentru a permite accesul resurselor mele pe front-end:

pip install django
pip install djangorestframework
pip install django-cors-headers

Odată ce acest lucru este făcut, suntem gata să creăm proiectul Django. Rulați următoarele:

django-admin startproject movierater
django-admin startapp api
python3 manage.py runserver

Acum, intrați în api/urls.py și faceți următoarele modificări:

#1
from django.urls import path
from rest_framework import routers
from django.conf.urls import include
router = routers.DefaultRouter()urlpatterns = [
    path('', include(router.urls)),
]

Aici ofer un număr de comentariu pentru fiecare pas pe care l-am făcut, dar ceea ce voi descrie este codul pentru fiecare fișier care a fost finalizat. Apoi, modificați și fișierul_2:

from django.contrib import admin
from django.urls import path
from django.conf.urls import include # 2 new line
from rest_framework.authtoken.views import obtain_auth_token #11
urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/', include('api.urls')), # 3 new line
    path('auth/', obtain_auth_token), # 11
]

Tokenul de autentificare este folosit pentru a stoca codul de criptare de la numele de utilizator în stocarea locală, astfel încât datele de acces ale utilizatorului să fie securizate. apoi, în proiectul MovieRater însetting.py adăugați codul după cum urmează:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework', #4
    'rest_framework.authtoken',#10 make login
    'corsheaders', # to connect to front end
    'api', #4
]
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'corsheaders.middleware.CorsMiddleware', #cors
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

Să creăm un model pentru a defini modul în care articolele MovieRater ar trebui să fie stocate în baza de date, să deschidem fișierul movierater/models.py și să-l actualizăm cu acest fragment:

from django.db import models
from django.contrib.auth.models import User
from django.core.validators import MaxValueValidator, MinValueValidator
# Create your models here. 5
class Movie(models.Model):
    title = models.CharField(max_length=32)
    description = models.TextField(max_length=360)
    #9
    def no_of_ratings(self):
        ratings = Rating.objects.filter(movie=self)
        return len(ratings)
    def avg_rating(self):
        ratings = Rating.objects.filter(movie=self)
        sum = 0
        for rating in ratings:
            sum += rating.stars
        if len(ratings) > 0:
            return sum / len(ratings)
        else:
            return 0
class Rating(models.Model):
    movie = models.ForeignKey(Movie, on_delete=models.CASCADE)
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    stars = models.IntegerField(validators=[MinValueValidator(1), MaxValueValidator(5)])
    class Meta:
        unique_together = (('user', 'movie'),)
        index_together = (('user', 'movie'),)
        # do makemigrations and migrate

Fragmentul de cod de mai sus descrie patru proprietăți din clasa Movie și trei proprietăți din clasa Rating pe modelul MovieRater. În continuare, trebuie să facem o migrare și să aplicăm modificările fișierului în baza de date, așa că haideți să rulăm aceste comenzi:

$ python3 manage.py makemigrations api
$ python3 manage.py migrate api

Putem testa pentru a vedea că operațiunile CRUD funcționează pe modelul API movierater pe care l-am creat folosind interfața de administrare pe care Django o oferă din cutie, dar mai întâi, vom face o mică configurare.

Deschideți fișierul api/admin.py și actualizați-l în consecință:

from django.contrib import admin
from .models import Movie, Rating #6 make register
# Register your models here.
admin.site.register(Movie) #6 new line
admin.site.register(Rating) #6 new line

Vom crea un cont de superutilizator pentru a accesa interfața de administrare.

$ python3 manage.py createsupersuser

putem încerca să ne logăm la adresa:

Apoi, trebuie să deschidem fișierul api/serializers.py și să-l actualizăm cu următorul cod:

#7
from rest_framework import serializers
from .models import Movie, Rating
from django.contrib.auth.models import User #14
from rest_framework.authtoken.models import Token #17
#14 for register and login
class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ('id', 'username', 'password')
        extra_kwargs = {'password': {'write_only': True, 'required': True}}
        #16 validate data
        def create(self, validated_data):
            user = User.objects.create_user(**validated_data)
            Token.objects.create(user=user)
            return user
class MovieSerializer(serializers.ModelSerializer):
    class Meta:
        model = Movie
        fields = ('id', 'title', 'description', 'no_of_ratings', 'avg_rating')
class RatingSerializer(serializers.ModelSerializer):
    class Meta:
        model = Rating
        fields = ('id', 'stars', 'user', 'movie')

vom crea clasa de vizualizare în api/view.py și vom face următoarele modificări:

#13
class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    permission_classes = (AllowAny, )
# Create your views here. 7
class MovieViewSet(viewsets.ModelViewSet):
    queryset = Movie.objects.all()
    serializer_class = MovieSerializer
    authentication_classes = (TokenAuthentication, ) #12
    permission_classes = (IsAuthenticated, ) #19
    #8
    @action(detail=True, methods=['POST'])
    def rate_movie(self, request, pk=None):
        if 'stars' in request.data:
            movie = Movie.objects.get(id=pk)
            stars = request.data['stars']
            user = request.user #12
            try:
                rating = Rating.objects.get(user=user.id,
movie=movie.id)
                rating.stars = stars
                rating.save()
                serializer = RatingSerializer(rating, many=False)
                response = {'message': 'rating updated', 'result': serializer.data}
                return Response(response, status=status.HTTP_200_OK)
            except:
                rating = Rating.objects.create(user=user, movie=movie, stars=stars)
                serializer = RatingSerializer(rating, many=False)
                response = {'message': 'rating created', 'result': serializer.data}
                return Response(response, status=status.HTTP_200_OK)
        else:
            response = {'message': 'you need to provide stars'}
            return Response(response, status=status.HTTP_400_BAD_REQUEST)
class RatingViewSet(viewsets.ModelViewSet):
    queryset = Rating.objects.all()
    serializer_class = RatingSerializer
    authentication_classes = (TokenAuthentication, ) #12
    permission_classes = (IsAuthenticated, ) #19
    #20
    def update(self, request, *args, **kwargs):
        response = {'message': 'you cant update rating like that'}
        return Response(response, status=status.HTTP_400_BAD_REQUEST)
    def create(self, request, *args, **kwargs):
        response = {'message': 'you cant create rating like that'}
        return Response(response, status=status.HTTP_400_BAD_REQUEST)

Mergeți la fișierul api/urls.py și adăugați-l cu codul de mai jos. Acest cod specifică calea URL pentru API:

from .views import MovieViewSet, RatingViewSet, UserViewSet #8 15userviewset
router.register('movies', MovieViewSet) #8
router.register('ratings', RatingViewSet) #8
router.register('users', UserViewSet) #15 for register and login

Acesta este pasul final care completează construirea API-ului, acum putem efectua operațiuni CRUD pe modelul MovieRater.

Configurarea React

ne vom crea frontend-ul și îl vom face să comunice cu backend-ul prin interfața pe care am creat-o. Apoi rulați:

$ npx install create-react-app movie-rater-app
$ npm start

În acest proiect, am instalat și am folosit această bibliotecă react:

Folosesc react-cookie pentru autentificare, react-fontawesome pentru atașarea pictogramei și react-router-dom pentru routerul browserului.

Să facem un folder de componente, să creăm /login.js și să-l adăugăm cu acest cod de mai jos:
https://gist.github.com/asaddam/7eead5c8a3c583fca165c6a348550ac1.js

În continuare, să definim câteva forme pentru detaliile filmului. Creați trei fișiere noi în components, movieDetails.js, movieForm.jsși movieList.js:

Vom modifica src/App.js pentru ultima dată, astfel încât acesta va solicita date de la serverul de backend și le va lista în schimb. De asemenea, dorim să ne asigurăm că toate operațiunile CRUD trimit cereri către serverul de backend în loc să interacționeze cu datele.

Deschideți fișierul și înlocuiți-l cu această versiune finală:

Felicitări! Tocmai am construit frontend-ul cu succes.

Am ajuns la sfârșitul acestui tutorial și am învățat cum să configuram Django și React pentru a interacționa corect unul cu celălalt.

Codul sursă pentru acest tutorial este disponibil aici și puteți încerca aplicația „aici”:

Backend: https://github.com/asaddam/movieRaterApp-django-backend

FrontEnd: https://github.com/asaddam/movieRaterApp-React-Frontend