Search code examples
djangovue.jsdjango-rest-frameworkckeditorckeditor5

Image upload to the rich text field from vue to amazon s3 via django REST framework


I'm experimenting Vue with Django and creating a simple blog.

But I'm stuck about usage of uploading images vie CKEditor from vue.

uploading images to S3 is working within django-admin. But I couldn't figure out how can I serialize RichTextUploadField and make it work with vue.

My model is;

class Challenge(models.Model):

    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    title = models.CharField(max_length = 240)
    content = RichTextUploadingField(verbose_name='Code',null=True,blank=True)
    slug = models.SlugField(max_length=255, unique=True)
    author = models.ForeignKey(settings.AUTH_USER_MODEL,
                                on_delete=models.CASCADE,
                                related_name="challenges")
    image = models.ImageField(upload_to=upload_image_to, editable=True, null=True, blank=True)

    def __str__(self):
        return self.title

serializers.py;

    author = serializers.StringRelatedField(read_only=True)
    created_at = serializers.SerializerMethodField()
    slug = serializers.SlugField(read_only=True)
    moments_count = serializers.SerializerMethodField()
    user_has_momented = serializers.SerializerMethodField()

    class Meta:
        model = Challenge
        exclude = ["updated_at"]

    def get_created_at(self, instance):
        return instance.created_at.strftime("%B %d %Y")

    def get_moments_count(self, instance):
        return instance.moments.count()

    def get_user_has_momented(self, instance):
        request = self.context.get("request")
        return instance.moments.filter(author=request.user).exists()

views.py

    queryset = Challenge.objects.all().order_by("-created_at")
    lookup_field = "slug"
    serializer_class = ChallengeSerializer
    permission_classes = [IsAuthenticated, IsAuthorOrReadOnly]

    def perform_create(self, serializer):
        serializer.save(author=self.request.user)

urls.py

router.register(r"challenges", cv.ChallengeViewSet)

urlpatterns = [
    path("", include(router.urls)),
    path("challenges/<slug:slug>/moments/", cv.ChallengeMomentListAPIView.as_view(), name="answer-list"),
    path("challenges/<slug:slug>/moment/", cv.MomentCreateAPIView.as_view(), name="moment-create"),
    path("moments/<int:pk>/", cv.MomentRUDAPIView.as_view(), name="moment-detail"),
    path("moments/<int:pk>/like/", cv.MomentLikeAPIView.as_view(), name="moment-like"),
    path('ckeditor/', include('ckeditor_uploader.urls')),
]

if settings.DEBUG:
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

frontend vue.js;

    return this.loader.file
        .then( uploadedFile => {
            return new Promise( ( resolve, reject ) => {
            const data = new FormData();
            data.append( 'upload', uploadedFile );

            axios( {
                url: '/challenges/uploadsCK/',
                method: 'post',
                data,
                headers: {
                    'Content-Type': 'multipart/form-data;'
                },
                withCredentials: false
            } ).then( response => {
                if ( response.data.result == 'success' ) {
                    resolve( {
                        default: response.data.url
                    } );
                } else {
                    reject( response.data.message );
                }
            } ).catch( response => {
                reject( 'Upload failed' );
            } );

        } );
    } );
}

Everything is working as I expected. The only problem is imageupload via vue.js and I couldn't figure out how to configure it.

any help is appreciated.


Solution

  • after a very tiring trial - error session I found a solution by examining the django-admin behaviour. when I upload an image I get the path of upload endpoint and viola! just add the following path for ckfinder.

            editorConfig: {
                ckfinder: {
                    uploadUrl: "http://127.0.0.1:8000/ckeditor/upload/&responseType=json"
                }
            }
    

    p.s: you can use relative path.