Django, загрузка изображений с ошибкой 403 токена CSRF при вызове Ajax - PullRequest
0 голосов
/ 05 апреля 2020

Я пытаюсь загрузить несколько файлов, используя Django. Идея заключается в том, что при создании сообщения в блоге пользователь также может добавлять изображения в сообщение. Я использую Ajax для отправки сообщения в блоге, однако, кажется, что после добавления формы изображения кнопка «отправить» не работает и мое сообщение не создается. Я уже построил две модели, изображения и пост. Ниже приведены мои коды, связанные с этой функциональностью. Имя моего проекта - «Register», а изображения находятся в приложении «home»: (Если я удалю функцию загрузки изображений, сообщение будет успешно создано, поэтому ajax работает правильно)

моя модель изображения:

мой просмотр post_creat в представлениях домашнего приложения:

@login_required
def post_create(request):
    data = dict()
    if request.method == 'POST':
        image_form = ImageForm(request.POST, request.FILES or None)
        images = request.FILES.getlist('image')
        form = PostForm(request.POST)
        if form.is_valid() and image_form.is_valid():    
            post = form.save(False)
            post.author = request.user
            post.save()
            for i in images:
                image_instance = Images(image=i,post=post)
                image_instance.save()
            data['form_is_valid'] = True
            posts = Post.objects.all()
            posts = Post.objects.order_by('-last_edited')
            data['posts'] = render_to_string('home/posts/home_post.html',{'posts':posts},request=request)
        else:
            data['form_is_valid'] = False
    else:
        image_form = ImageForm
        form = PostForm      
    context = {
    'form':form,
    'image_form':image_form
    }
    data['html_form'] = render_to_string('home/posts/post_create.html',context,request=request)
    return JsonResponse(data) 

мой javascript код для обработки запроса ajax:

  $(document).ready(function(){

    var ShowForm = function(e){
        e.stopImmediatePropagation();
        var btn = $(this);
        $.ajax({
            url: btn.attr("data-url"),
            type: 'get',
            dataType:'json',
            beforeSend: function(){
                $('#modal-post').modal('show');
            },
            success: function(data){
                $('#modal-post .modal-content').html(data.html_form);
            }
        });
        return false;
    };
    // change form to FormData
    // var form = $(this)
    // processData, contentType were removed
    var SaveForm =  function(e){
        e.stopImmediatePropagation();
        var data = new FormData($('form').get(0));
        $.ajax({
            url: $(this).attr('data-url'),
            type: $(this).attr('method'),
            data: data,
            processData: false,
            contentType: false,
            dataType: 'json',
            success: function(data){
                if(data.form_is_valid){
                    $('#post-list div').html(data.posts);
                    $('#modal-post').modal('hide');
                } else {
                    $('#modal-post .modal-content').html(data.html_form)
                }
            }
        })
        return false;
    }

//create
$('.create-post-btn').click(ShowForm);
$('#modal-post').on("submit",".post-create-form",SaveForm)

//update
$('#post-list').on("click",".show-form-update",ShowForm);
$('#modal-post').on("submit",".update-form",SaveForm)

//delete
$('#post-list').on("click",".show-form-delete",ShowForm);
$('#modal-post').on("submit",".delete-form",SaveForm)
});

Мой post_create. html файл:

<form method="POST" data-url="{% url 'home:post-create' %}" class="post-create-form" enctype="multipart/form-data">
    {% csrf_token %}
        <div class="modal-header">
            <h5 class="modal-title" >Create a Post</h5>
            <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                <span aria-hidden="true">&times;</span>
            </button>
        </div>
    <div class="modal-body" style="overflow-y: auto;">
        {{ form|crispy }}
        <button type="button" id="show-image-upload-inputs" class="btn btn-sm mr-auto btn-primary pb-1">
            <span><i class="fas fa-camera"></i></span>
        </button>
        <div id="image-upload-div" class="mt-1" style="display: none;">
            <hr class="my-2">
            <p class="mx-2 text-muted small">Add up to four images to your post</p>
                <div class="d-flex flex-row justify-content-between px-1">
                    {{ image_form }}    
                </div>
        </div>
    </div>
    </div>
    <div class="modal-footer">
        <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
        <button type="submit" class="btn btn-primary">Post</button>
    </div>
</form>

** скрытый экран - это просто функция javascript для отображения формы при нажатии на кнопку vamera.

модель моего изображения :

class Images(models.Model):
    post = models.ForeignKey(Post,on_delete=models.CASCADE,related_name='images')
    image = models.FileField(upload_to=upload_to_uuid('media/post_images/'),verbose_name='Image')
    date_added = models.DateTimeField(auto_now_add=True)

мой проект (регистрация) settings.py:

MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'

мой проект (регистрация) urls.py;

urlpatterns = [
    #Has to be included for Forgot Password funcitonality on main page
    path('', include('django.contrib.auth.urls')), 
    path('admin/', admin.site.urls),    
    path('',views.user_login,name='user_login'),
    path('',include('main.urls'),name='main'), 
    url(r'^home/',include(('home.urls','home'), namespace='home'))

] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT ) + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)

и папка мультимедиа создается в регистр / медиа

РЕДАКТИРОВАТЬ: я изменил свою функцию Ajax и теперь я использую FormData, однако я получаю

Forbidden (CSRF token missing or incorrect.): /home/post/create/
[06/Apr/2020 01:18:53] "POST /home/post/create/ HTTP/1.1" 403 2513

Ошибка, когда я нажимаю c при отправке, однако, у меня есть csrf_token. Как я могу решить эту проблему?

1 Ответ

0 голосов
/ 05 апреля 2020

Ваша модель поста кода должна быть такой

class Post(models.Model):
    title=models.CharField(max_length=50)
    sub_title=models.CharField(default="This is the subtitle of the post ",max_length=150)
    content=models.TextField(max_length=4000)
    date_posted=models.DateTimeField(default=timezone.now)
    blog_image_1=models.ImageField(Blank=True,Null=True,upload_to='media')
    blog_image_2=models.ImageField(Blank=True,Null=True,upload_to='media')
    blog_image_3=models.ImageField(default='default.jpg',upload_to='media')
    author =models.ForeignKey(User,on_delete=models.CASCADE) 

    def __str__(self):
        return self.title

Каталог медиа должен быть таким

    MEDIA_ROOT=os.path.join(BASE_DIR,'media')
    MEDIA_URL='/media/'

И Html Как

<body>
<div class="container">
    <form method="POST" enctype="multipart/form-data">
        {% csrf_token %}
        <fieldset class="form-group">
            <legend class="'border-bottom mb-4">Post</legend>
            {{ form|crispy }}
         </fieldset>
        <div class="form-group">
            <button class="btn-outline-info" type="submit"> Submit</button>
        </div>
    </form>
</div>
</body>

И используйте базовые представления классов. Они более мощные

class PostCreateView(LoginRequiredMixin,CreateView):
    model = Post
    fields = ['title','sub_title','content','blog_image_1','blog_image_2','blog_image_2']


    def form_valid(self, form):
        form.instance.author = self.request.user
        return super().form_valid(form)
...