Niedawno zrobiłem projekt przy użyciu Django i React. wcześniej znałem Django, ale nie Reacta, co sprawiało, że radziłem sobie z drobnymi problemami podczas jego wykonywania. Przy tej okazji nauczyłem się tworzyć aplikacje w React i jak integrować React z Django. Dzielę się więc tym, czego się nauczyłem, mając nadzieję, że Ty również odniesiesz korzyści!
Stworzymy prostą aplikację, czyli Movie-Rater-App, która będzie zawierała operacje CRUD. Muszę wspomnieć, że obecnie pracuję z Django 3.0.1 i ReactJS 6.13.
Konfigurowanie Django
Na początek musimy skonfigurować nasze środowisko wirtualne. Użyję tutaj środowiska wirtualnego, upewnij się, że zainstalowałeś virtualvenv, a następnie przejdź do katalogu, w którym chcesz, aby Twój projekt się znajdował i uruchamiał:
$ pip install virtualenv $ cd ur_project_folder
Gdy już to zrobisz, aktywuj środowisko wirtualne za pomocą:
$ virtualenv venv $ source venv/bin/activate
Teraz będziemy musieli zainstalować kilka pakietów, w tym „Django”, „Django REST Framework” i „Nagłówki Django CORS”. DRF jest tym, co nałożymy na Django, aby zamienić nasz projekt w API, a nagłówki Django CORS są niezbędne, aby umożliwić dostęp do moich zasobów na moim interfejsie:
pip install django pip install djangorestframework pip install django-cors-headers
Gdy już to zrobimy, jesteśmy gotowi do stworzenia projektu Django. Uruchom następujące polecenie:
django-admin startproject movierater django-admin startapp api python3 manage.py runserver
Teraz przejdź do api/urls.py
i wprowadź następujące modyfikacje:
#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)), ]
Tutaj podaję numer komentarza do każdego wykonanego przeze mnie kroku, ale opiszę kod każdego ukończonego pliku. Następnie zmodyfikuj także plikmovierater/urls.py
:
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 ]
Token uwierzytelniający służy do przechowywania kodu szyfrującego z nazwy użytkownika w pamięci lokalnej, dzięki czemu dane dostępowe użytkownika są zabezpieczone. następnie w projekcie MovieRater insetting.py
dodaj kod jak poniżej:
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', ]
Stwórzmy model określający, w jaki sposób elementy MovieRater powinny być przechowywane w bazie danych, otwórz plik movierater/models.py
i zaktualizuj go za pomocą tego fragmentu:
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
Powyższy fragment kodu opisuje cztery właściwości klasy Movie i trzy właściwości klasy Rating w modelu MovieRater. Następnie musimy przeprowadzić migrację i zastosować zmiany w plikach do bazy danych, zatem uruchommy następujące polecenia:
$ python3 manage.py makemigrations api $ python3 manage.py migrate api
Możemy przetestować, czy operacje CRUD działają na modelu API Movierater, który stworzyliśmy przy użyciu interfejsu administracyjnego udostępnianego przez Django od razu po wyjęciu z pudełka, ale najpierw przeprowadzimy małą konfigurację.
Otwórz plik api/admin.py
i odpowiednio go zaktualizuj:
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
Utworzymy konto superużytkownika, aby uzyskać dostęp do interfejsu administratora.
$ python3 manage.py createsupersuser
możemy spróbować zalogować się pod adresem:
Następnie musimy otworzyć plik api/serializers.py
i zaktualizować go następującym kodem:
#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')
utworzymy klasę widoku w api/view.py
i dokonamy następujących modyfikacji:
#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)
Przejdź do pliku api/urls.py
i dodaj go za pomocą poniższego kodu. Ten kod określa ścieżkę URL interfejsu 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
To już ostatni krok kończący budowę API, możemy już wykonywać operacje CRUD na modelu MovieRater.
Konfigurowanie reakcji
stworzymy nasz frontend i umożliwimy mu komunikację z backendem poprzez stworzony przez nas interfejs. Następnie uruchomić:
$ npx install create-react-app movie-rater-app $ npm start
W tym projekcie zainstalowałem i używam tej biblioteki reakcji:
Używam pliku cookie reagującego do uwierzytelniania, reagującego-fontawesome do dołączania ikony i reagującego routera-dom dla routera przeglądarki.
Stwórzmy folder komponentów, utwórz /login.js
i dodaj go za pomocą poniższego kodu:
https://Gist.github.com/asaddam/7eead5c8a3c583fca165c6a348550ac1.js
Następnie zdefiniujmy niektóre formularze dla szczegółów filmu. Utwórz trzy nowe pliki w components
, movieDetails.js,
movieForm.js
i movieList.js
:
Zmodyfikujemy plik src/App.js po raz ostatni, aby zażądał danych z serwera zaplecza i zamiast tego wyświetlił je. Chcemy również mieć pewność, że wszystkie operacje CRUD wysyłają żądania do serwera zaplecza zamiast wchodzić w interakcję z danymi.
Otwórz plik i zastąp go ostateczną wersją:
Gratulacje! Właśnie pomyślnie zbudowaliśmy frontend.
Dotarliśmy do końca tego samouczka i dowiedzieliśmy się, jak skonfigurować Django i React, aby poprawnie współdziałały ze sobą.
Kod źródłowy tego samouczka jest dostępny tutaj, a aplikację możesz wypróbować tutaj:
Backend: https://github.com/asaddam/movieRaterApp-django-backend
FrontEnd: https://github.com/asaddam/movieRaterApp-React-Frontend