Как обновить поле "многие ко многим" в DRF
В моем проекте есть модель пользователя и модель школы. Моя модель пользователя имеет поле schools
, которое имеет M2M отношение с моделью школы. Теперь я хочу знать, как я могу создать представление, которое может взять email пользователя и Id школы, и добавить школу или удалить ее из школ, к которым принадлежит user
.
Вот мой user model
:
class User(AbstractBaseUser, PermissionsMixin):
username = models.CharField(max_length=255, unique=True, db_index=True)
email = models.EmailField(max_length=255, unique=True, db_index=True)
is_verified = models.BooleanField(default=False)
is_active = models.BooleanField(default=False)
is_staff = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now_add=True)
schools = models.ManyToManyField("School", related_name="members")
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username']
objects = UserManager()
def __str__(self):
return self.email
def tokens(self):
refresh = RefreshToken.for_user(self)
return {
'refresh': str(refresh),
'access': str(refresh.access_token)
}
<
class School(models.Model):
name = models.CharField(max_length=300, verbose_name='school name', )
principal = models.ForeignKey("User", related_name="my_schools", on_delete=CASCADE)
address = models.CharField(max_length=200)
class Type(models.IntegerChoices):
PUBLIC = 1, "Public"
PRIVATE = 2, "Private"
type = models.PositiveSmallIntegerField(choices=Type.choices, default=Type.PUBLIC)
class Level(models.IntegerChoices):
NATIONAL = 1, "National"
EXTRACOUNTY = 2, "Extra County"
COUNTY = 3, "County"
SUBCOUNTY = 4, "Subcounty"
level = models.PositiveSmallIntegerField(choices=Level.choices, default=Level.COUNTY)
def __str__(self):
return self.name
Вот сериализатор для регистрации членов:
class EnrollSchoolMembersSerializer():
class Meta:
model = User
field = ('email')
Я думаю, что вы можете реализовать это, используя представление API функций. Во-первых, вы можете определить сериализатор.
from rest_framework import serializers as sz
class SchoolUpdateSerializer(sz.Serializer):
school_id = sz.IntegerField()
email = sz.EmailField()
mode = sz.CharField() # can be either 'add' or 'delete'
А в файле views.py можно написать обработчик.
from rest_framework.response import Response
from rest_framework status
from rest_framework.decorators import api_view, permission_classes
from .models import School, User
from .serializers import SchoolUpdateSerializer
@api_view(['POST'])
@permission_classes([permissions.AllowAny])
def update_school_data(request):
serializer = SchoolUpdateSerializer(data = request.data)
if serializer.is_valid()
input_data = serializer.validated_data
email = input_data.get('email')
mode = input_data.get('mode')
school_id = input_data.get('school_id')
try:
user = User.objects.get(email = email)
school = School.objects.get(pk = school_id)
if mode == "add":
user.schools.add(school)
else:
user.schools.remove(school)
return Response(status = status.HTTP_200_OK)
except (User.DoesNotExist, School.DoesNotExist):
return Response(status = status.HTTP_400_BAD_REQUEST)
else:
return Response(status = status.HTTP_400_BAD_REQUEST)
Наконец, во фронтенде вы можете использовать POST API. Полезная нагрузка может быть
{
"email": "test@example.com",
"school_id": 1,
"mode": "add"
}
Смотрите документацию по REST-фреймворку Django на https://www.django-rest-framework.org/api-guide/serializers/#writing-update-methods-for-nested-representations