如何格式化 Django URL,以便 AJAX 调用将获取不依赖于当前页面但来自表单值的数据库数据?

Posted

技术标签:

【中文标题】如何格式化 Django URL,以便 AJAX 调用将获取不依赖于当前页面但来自表单值的数据库数据?【英文标题】:How do I format Django URL so that AJAX call will get database data that is not dependent on the current page, but from a form value? 【发布时间】:2021-12-27 12:23:38 【问题描述】:

我有一个页面详细介绍了一篇文章和该文章上的 cmets。这个页面的pk是post pk。我希望能够仅使用符号来构造 cmets。我有一系列符号保存到数据库中,它们都与类别类相关联。我的页面上有一个可以选择其中一个类别的表单,但是如何获得 AJAX 调用以加载该类别中的所有符号?用户将需要能够在类别之间进行切换和更改,因此我想使用 AJAX 来执行此操作,而不是每次都重新加载页面。到目前为止,我得到的只是404,而不是founds。我想这样做,以便我可以拖动或选择要添加到 cmets 的符号。我尝试了许多不同的格式来使 URL 正常工作(urls.pymain.js),所以我无法列出我尝试过的所有替代方案,因为这有点让人不知所措。我还在这里和其他网站上阅读了一堆问题,但似乎没有什么与我想要做的事情相匹配。任何帮助将不胜感激。

符号保存在media/uploads/symbol_files/

符号通过模型与 cmets 具有多对多的关系。所有这一切都很好,所以我没有在下面包含它。 目前模板已设置为使用所选类别中的符号填充第二个表单,稍后我将更改此设置,为了方便起见,我只是这样设置。

这是终端输出的示例:

Not Found: /posts/1/get_symbols/Alphabet

其中“字母”是类别之一的名称。

models.py:

class SymbolCategory(models.Model):
    name = models.CharField(max_length=50)
        
    def __str__(self):
        return self.name

    def get_symbols(self):
        return self.symbol_set.all()
    
    class Meta:
        verbose_name = "SymbolCategory"
        verbose_name_plural = "SymbolCategories"

class Symbol(models.Model):
    name = models.CharField(max_length=50)
    image = models.FileField(upload_to='uploads/symbol_files')
    category = models.ForeignKey(SymbolCategory, on_delete=models.CASCADE)

    def __str__(self):
        return f'self.name-self.pk'

class Post(models.Model):
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    title = models.CharField(max_length = 100)
    body = models.TextField(max_length = 500)
    video_file = models.FileField(blank=True, upload_to='uploads/video_files', validators = [FileExtensionValidator(allowed_extensions=['mp4', 'webm'])])
    thumbnail = models.FileField(blank=True, upload_to='uploads/thumbnails', validators = [FileExtensionValidator(allowed_extensions=['png', 'jpg','jpeg'])])
    date_posted = models.DateTimeField(default=timezone.now)
    category = models.ForeignKey(PostCategory,blank=True, on_delete=models.CASCADE)
    
    class Meta:
        verbose_name_plural = "Posts"

views.py:

class DetailPost(View):
    def get(self, request, pk, *args, **kwargs):
        post = Post.objects.get(pk=pk)
        symbol_comments = SymbolComment.objects.filter(post=post).order_by('-created_on')
        categories = SymbolCategory.objects.all()

        form_comment = CommentForm()
        symbol_get_form = SymbolGetForm()


        context = 
            'object': post,
            'form_comment': form_comment,
            'symbol_comments': symbol_comments,
            'symbol_get_form': symbol_get_form,
            'categories': categories,
        

        return render(request, 'posts/detail_post.html', context)
    
    def post(self, request, pk, *args, **kwargs):
        post = Post.objects.get(pk=pk)
        form_comment = CommentForm(request.POST)
        if form_comment.is_valid():
            symbol_comments = SymbolComment(
                user = self.request.user,
                post = post
            )
            symbol_comments.save()
            
        symbol_comments = SymbolComment.objects.filter(post=post).order_by('-created_on')
                
        context = 
            'object': post,
            'form_comment': form_comment,
            'symbol_comments': symbol_comments,
        
        return render(request, 'posts/detail_post.html', context)
      
def get_symbols(request):
    if request.is_ajax():
        if request.method == "POST": # I've tried with GET but it doesn't work either, at the moment it currently has POST but I think this is wrong.
            category_name = request.POST['category_name']
            print(category_name)
            try:
                category = SymbolCategory.objects.filter(id = category_name).first()
                symbols = Symbol.objects.filter(category = category)
            except Exception:
                data['error_message'] = 'error'
                return JsonResponse(data)
            return JsonResponse(list(symbols.values('name', 'image_field')), safe = False)

urls.py:

urlpatterns = [
    path('<int:pk>/', DetailPost.as_view(), name='detail-post'),
    path('get_symbols/', get_symbols, name='get-symbols'),
    ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)

模板:

% csrf_token %
<div class="col-md-6">
  <div class="form-group">
    <label for="inputStatus">Category</label>
    <select id="select-category" class="form-control-sm custom-select">
      <option selected disabled>Choose a symbol category</option>
      % for category in categories %
      <option value="category.name">category.name</option>
      % endfor %
    </select>
  </div>
</div>
<div class="col-md-6">
    <div class="form-group">
      <label for="inputStatus">Symbol</label>
      <select id="category-symbol" class="form-control-sm custom-select" name="symbol">
        <option selected disabled>Choose a symbol</option>
      </select>
    </div>
  </div>

main.js:

$("#select-category").change(function () 
    const categoryName = $(this).val(); 
    $.ajax(                       
        type: "POST",
        url: `get_symbols/$categoryName`,
        data: 
            'category_name': categoryName,
            'csrfmiddlewaretoken':$('input[name=csrfmiddlewaretoken]').val(),
        ,
        success: function (data)    
            let html_data = '<option value="">---------</option>';
            data.forEach(function (data) 
                html_data += `<option value="$data.id">$data.name</option>`
            );
        console.log(data)
        $("#category-symbol").html(html_data); 
        
    );
);

【问题讨论】:

【参考方案1】:

需要的网址

'&lt;int:pk&gt;/'get_symbols'/&lt;int:id&gt;/'

还有一些其他错误需要修复。

【讨论】:

以上是关于如何格式化 Django URL,以便 AJAX 调用将获取不依赖于当前页面但来自表单值的数据库数据?的主要内容,如果未能解决你的问题,请参考以下文章

python测试开发django-145.$.ajax() 请求 javascript 获取当前 URL 参数

通过 AJAX 以 JSON 格式发送 Django 表单

如何在ajax中使用django url?

Django---进阶8

Django---进阶8

Django AJAX