У меня есть модель UserProfile
, которая имеет отношение один к одному с моделью User
.
Я столкнулся с проблемой при загрузке изображения с помощью конечной точки API остаточного каркаса во вложенную модель.
Проблема в следующем: Хотя я явно использую декоратор @action (), он также вызывает встроенный метод create () для сохранения изображения методом POST.
Затем я явно упомянул, какой метод вызывать в urls.py. Теперь он показывает ошибки.
Есть ошибки в реализации в serializer.py и views.py.
Поэтому, если возможно, пожалуйста, исправьте мои ошибки и направьте меня в правильное направление. Больше двух дней, но я все еще поражен.
В models.py :
def user_image_upload_file_path(instance, filename):
"""Generates file path for uploading user images"""
extension = filename.split('.')[-1]
file_name = f'{uuid.uuid4()}.{extension}'
date = datetime.date.today()
initial_path = f'pictures/uploads/user/{date.year}/{date.month}/{date.day}/'
full_path = os.path.join(initial_path, file_name)
return full_path
class UserManager(BaseUserManager):
def create_user(self, email, password, username, **extra_kwargs):
"""Creates and saves a new user"""
if not email:
raise ValueError(_('Email cannot be empty'))
user = self.model(email=self.normalize_email(email), **extra_kwargs)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, password, username, **extra_kwargs):
"""Creates and saves a new user with superuser permission"""
user = self.create_user(
email, password, username, **extra_kwargs)
user.is_staff = True
user.is_superuser = True
user.save(using=self._db)
return user
class User(AbstractBaseUser, PermissionsMixin):
"""Creates user model that supports using email as username"""
email = models.EmailField(_('Email'), max_length=255, unique=True)
created_date = models.DateTimeField(
_('Created Date'), default=timezone.now, editable=False)
objects = UserManager()
USERNAME_FIELD = 'email'
def __str__(self):
"""String representation of user model"""
return self.email
class UserProfile(models.Model, Languages):
"""Creates user profile model"""
user = models.OneToOneField(
'User',
related_name='profile',
on_delete=models.CASCADE
)
first_name = models.CharField(
_('First Name'), max_length=255, blank=True)
last_name = models.CharField(
_('Last Name'), max_length=255, blank=True)
image = models.ImageField(
_('Image'),
upload_to=user_image_upload_file_path,
null=True,
blank=True,
max_length=1024
)
@receiver(post_save, sender=User)
def user_is_created(sender, instance, created, **kwargs):
if created:
UserProfile.objects.create(user=instance)
else:
instance.profile.save()
В serializer.py :
class UserSerializer(serializers.ModelSerializer):
"""Minimal serializer for supporting user image upload field"""
class Meta:
model = get_user_model()
fields = ('username', )
class UserImageUploadSerializer(serializers.ModelSerializer):
"""Serializer for user profile"""
user = UserSerializer(read_only=True)
class Meta:
model = UserProfile
fields = ('id', 'user', 'image', )
read_only_fields = ('id', 'user', )
В views.py :
class UserImageUploadView(viewsets.ModelViewSet):
serializer_class = serializer.UserImageUploadSerializer
authentication_classes = [authentication.TokenAuthentication, ]
permission_classes = [permissions.IsAuthenticated, ]
queryset = get_user_model().objects.all()
def get_queryset(self):
"""Return object for only authenticated user"""
return self.queryset.filter(id=self.request.user)
@action(detail=True, methods=['POST'], url_path='user-upload-image')
def image_upload(self, pk=None):
"""Save the uploaded picture and profile data"""
user = self.get_object()
profile = user.profile
data = {'user': user, 'id': profile.pk, 'data': request.data}
serializer_ = serializer.UserImageUploadSerializer(data=data)
if serializer_.is_valid():
serializer_.save()
return Response(serializer_.data, status=status.HTTP_200_OK)
else:
return Response(serializer_.errors, status=status.HTTP_400_BAD_REQUEST)
В urls.py :
urlpatterns = [
path('<int:pk>/upload-image/', views.UserImageUploadView.as_view(
{'get': 'list', 'post': 'image_upload', }), name='user-image-upload')
]