Недавно я сделал проект с использованием Django и React. ранее я был знаком с Django, но не с React, что заставляло меня сталкиваться с небольшими проблемами при этом. В связи с этим я научился разрабатывать приложения с помощью React и интегрировать React с Django. Итак, я делюсь тем, что узнал, в надежде, что вы также получите пользу!
Мы создадим простое приложение Movie-Rater-App, в котором есть операции CRUD. Я должен упомянуть, что в настоящее время я работаю с Django 3.0.1 и ReactJS 6.13.

Настройка Джанго

Прежде всего, нам нужно настроить нашу виртуальную среду. Здесь я буду использовать виртуальную среду, убедитесь, что вы установили virtualvenv, затем перейдите в каталог, в котором вы хотите разместить свой проект, и запустите его:

$ pip install virtualenv
$ cd ur_project_folder

Как только это будет сделано, активируйте виртуальную среду с помощью:

$ virtualenv venv
$ source venv/bin/activate

Теперь нам нужно установить некоторые пакеты, в том числе Django, Django REST framework и Django CORS headers. DRF — это то, что мы будем накладывать поверх Django, чтобы превратить наш проект в API, а заголовки Django CORS необходимы, чтобы разрешить доступ к моим ресурсам в моем интерфейсе:

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

Как только это будет сделано, мы готовы создать проект Django. Запустите следующее:

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

Теперь перейдите в api/urls.py и внесите следующие изменения:

#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)),
]

Здесь я привожу номер комментария для каждого шага, который я сделал, но я опишу код для каждого завершенного файла. Затем также измените themovierater/urls.pyfile:

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
]

Токен аутентификации используется для хранения кода шифрования из имени пользователя в локальном хранилище, чтобы данные доступа пользователя были защищены. затем в проекте MovieRater insetting.py добавьте следующий код:

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',
]

Давайте создадим модель для определения того, как элементы MovieRater должны храниться в базе данных, откроем файл movierater/models.py и обновим его с помощью этого фрагмента:

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

Фрагмент кода выше описывает четыре свойства в классе Movie и три свойства в классе Rating в модели MovieRater. Далее нам нужно выполнить миграцию и применить изменения файла к базе данных, поэтому давайте запустим эти команды:

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

Мы можем проверить, работают ли операции CRUD с моделью API Movierater, которую мы создали, используя интерфейс администратора, который Django предоставляет из коробки, но сначала мы выполним небольшую настройку.

Откройте файл api/admin.py и обновите его соответствующим образом:

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

Мы создадим учетную запись суперпользователя для доступа к интерфейсу администратора.

$ python3 manage.py createsupersuser

мы можем попробовать войти по адресу:

Затем нам нужно открыть файл api/serializers.py и обновить его следующим кодом:

#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')

мы создадим класс представления в api/view.py и внесем следующие изменения:

#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)

Перейдите к файлу api/urls.py и добавьте его с помощью приведенного ниже кода. Этот код указывает URL-адрес для 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

Это последний шаг, который завершает создание API, теперь мы можем выполнять операции CRUD с моделью MovieRater.

Настройка React

мы создадим наш интерфейс и заставим его общаться с сервером через созданный нами интерфейс. Затем запустите:

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

В этом проекте я установил и использую эту библиотеку реагирования:

Я использую react-cookie для аутентификации, react-fontawesome для прикрепления значка и react-router-dom для маршрутизатора браузера.

Давайте создадим папку компонентов, создадим /login.js и добавим ее с помощью этого кода ниже:
https://gist.github.com/asaddam/7eead5c8a3c583fca165c6a348550ac1.js

Далее, давайте определим некоторые формы для деталей фильма. Создайте три новых файла в components, movieDetails.js, movieForm.jsи movieList.js:

Мы изменим src/App.js в последний раз, чтобы он запрашивал данные с внутреннего сервера и вместо этого перечислял их. Мы также хотим убедиться, что все операции CRUD отправляют запросы на внутренний сервер, а не взаимодействуют с данными.

Откройте файл и замените его этой окончательной версией:

Поздравляем! Мы только что успешно построили интерфейс.

Мы подошли к концу этого руководства и узнали, как настроить Django и React для правильного взаимодействия друг с другом.

Исходный код этого туториала доступен здесь, а попробовать приложение можно здесь:

Бэкенд: https://github.com/asaddam/movieRaterApp-django-backend

Внешний интерфейс: https://github.com/asaddam/movieRaterApp-React-Frontend