django ImageField не сохраняет файлы в надлежащем каталоге с помощью django rest framework

#django #django-rest-framework

#django #django-rest-framework

Вопрос:

При отправке запроса post изображения сохраняются в media/user_None/pic/1602746423.311224_profile.png вместо media/user_{id}/pic/1602746423.311224_profile.png

Модель учителя

 class Teacher(AbstractUser):
    profile_pic = models.ImageField(verbose_name="Profile Picture",blank=True,null=True,upload_to=file_pic,default='default.png')
    middle_name = models.CharField(max_length=30, blank=True, null=True)
    dob = models.DateField(verbose_name='Date Of Birth', null=True)
    doj = models.DateField(verbose_name='Date Of Join', null=True)
    mobile_num = models.CharField(verbose_name='Mobile Number',max_length=10,null=True,blank=True)

    SEX_CHOICE = (
        ('m','Male'),
        ('f','Female'),
        ('t','Transgender'),
        ('o','Others')
    )
    sex = models.CharField(max_length=1,choices=SEX_CHOICE,default='m')
    department = models.ForeignKey('Department',on_delete=models.SET_NULL,null=True)
  

функция file_pic для ImageField для сохранения фотографий в папке пользователя на основе его идентификатора

 def file_pic(instance, filename):
    return 'user_{0}/pic/{2}_{1}'.format(instance.id, filename, time.time())
  

Сериализатор для создания учителя

 class TeacherCreateSerializer(ModelSerializer):
    password2 = CharField(write_only=True, style={'input_type':'password'})
    class Meta:
        model = Teacher
        fields = [
            'username',
            'email',
            'mobile_num',
            'first_name',
            'middle_name',
            'last_name',
            'dob',
            'doj',
            'sex',
            'department',
            'profile_pic',
            'password',
            'password2'
        ]
        extra_kwargs = {
            'password' : {'write_only':True, 'style':{'input_type':'password'}}
        }

    def create(self,validated_data):
        vd_cpy = validated_data
        password1 = vd_cpy['password']
        password2 = vd_cpy['password2']
        vd_cpy.pop('password2')
        vd_cpy.pop('password')
        teacher = Teacher(**vd_cpy)

        if(password1!=password2):
            raise ValidationError('password doesn't match')
        teacher.set_password(password1)
        teacher.save()
        return validated_data
    
    def validate_mobile_num(self,value):
        value = self.initial_data.get('mobile_num',None)
        if value is None or len(value) == 0:
            return None
        if(re.search(r'^(( ?91|0)?){1}[1-9]{1}[0-9]{9}$',value) is None):
            raise ValidationError('Invalid Mobile Number')
        return value
    
    def validate_email(self,value):
        if(Teacher.objects.filter(email=value).exists()):
            raise ValidationError('email already registered')
        return value
  

APIView для создания учителя

 class TeacherCreateAPIView(CreateAPIView):
    queryset = Teacher.objects.all()
    serializer_class = TeacherCreateSerializer
    permission_classes = [AllowAny]
    parser_classes = (JSONParser,FormParser,MultiPartParser)
  

Что DRF API Explorer показывает сразу после регистрации

 
HTTP 201 Created
Allow: POST, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "username": "ramverma",
    "email": "ram@gmail.com",
    "mobile_num": null,
    "first_name": "Ram",
    "middle_name": "",
    "last_name": "Verma",
    "dob": null,
    "doj": null,
    "sex": "m",
    "department": 6,
    "profile_pic": http://localhost:8000/media/user_None/pic/1602764174.8516657_ProfiePic.png
}

**1st Issue**
  

** profile_pic сохраняется в папке user_none, но вместо этого он должен быть сохранен в user_{user.id } как написано в функции file_pic. Идея состоит в том, чтобы сохранить все, что связано с пользователем, в одной папке.

  {
        "profile_pic": "http://localhost:8000/media/user_None/pic/1602764174.8516657_ProfiePic.png",
        "first_name": "Ram",
        "last_name": "Verma",
        "username": "ramverma",
        "url": "http://localhost:8000/api/teacher/23"
    }
  

2-я проблема
Если в POST-запросе не указано изображение профиля, то значение profile_pic устанавливается равным null вместо значения по умолчанию, которое указано в ImageFiled в модели

обе проблемы возникают при взаимодействии с API, при веб-взаимодействии проблема не сохраняется

Ответ №1:

Если вы хотите получить доступ к идентификатору объекта, вы должны сначала сохранить () его, поскольку значение вычисляется базой данных, а не django, и нет способа узнать это раньше. Затем вы можете обновить ImageField, вызвав сигнал post_save.

Я не уверен в проблеме с изображением по умолчанию.