Получение данных API Django из нестатического url с помощью Ajax-Jquery [Без REST Framework].

В моем серверном приложении, созданном с помощью Django, мне нужно показывать статьи на основе url, который содержит год, месяц и user_id статьи. blog/1/2022/8 должен показать все статьи августа.

В приложении на стороне клиента (Jquery) мне нужно вызвать API, которое возвращает все статьи, отфильтрованные по году и месяцу.

Как я могу установить url в ajax с переменной информацией года и месяца?

urls.py (я должен использовать эти urlpatterns):

app_name = 'blog'

urlpatterns = [
    #link to API
    path('API/<int:user_id>/<int:year>/<int:month>', views.get_articles, name='get_articles'),
    
    #link to html file
    path('<int:user_id>/<int:year>/<int:month>', views.index, name='index'),
]

Модель:

from django.contrib.auth.models import User

class Article(models.Model):
    author =  models.ForeignKey(User, on_delete=models.CASCADE)
    pub_date = models.DateTimeField()
    title = models.CharField(max_length=50)
    content = models.TextField()

    def __str__(self):
        return self.title

    def get_year(self):
        return self.pub_date.year

    def get_month(self):
        return self.pub_date.month

Просмотров:

def index(request, **kwargs):
    return render(request, template_name='blog/index.html', context={'user_id':kwargs.get('user_id')})

#return json data with articles filtered by year and month of url
def get_articles(request, **kwargs):
    articles = Article.objects.filter(
        pub_date__year = kwargs.get('year'),
        pub_date__month = kwargs.get('month'),
    ).values('title','author','pub_date')

    data = {
        'articles' : list(articles)
    }
    return JsonResponse(data)

index.html:

{% block content %}
<div class="container">
    <br><h3>Articoli</h3>
    
    <div id="article_list"></div>
</div>
{% endblock content %}

blog.js:

$(document).ready(function(){
    $.ajax({
        url: WHICH URL?,
        dataType:'json',
        success: function(data){
            for(var i=0; i < data.length; i++){
                var item = $('<p>ID: '+ data[i].id +'<br>Titolo: '+ data[i].title +'<br>Autore: ' +
                    data[i].author  + '<br>Data: ' + data[i].pub_date +'</p>');
                $('#article_list').append(item);
            }
        }
    });
});

Бонусный вопрос: Я должен сериализовать данные, используемые API, но Как я могу сделать это без rest_framework?

Если вы задаетесь вопросом, почему без REST Framework, то это в образовательных целях.

Сначала необходимо очистить urlpatterns

urlpatterns = [
    # API url
    path('api/<int:author_id>/<int:year>/<int:month>/', views.get_articles, name='get_articles'),
    
    # view url
    path('<int:user_id>/', views.index, name='index'),
]

Для вашего представления API вы можете использовать @api_view декоратор из django_rest_framework для получения ajax запроса.

from rest_framework.decorators import api_view
...
@api_view
def get_articles(request, author_id, year, month):
    articles = Article.objects.filter(
        author_id=author_id
        pub_date__year=year,
        pub_date__month=month,
    ).values('title','author','pub_date')

    data = {
        'articles' : list(articles)
    }
    return JsonResponse(data)

Теперь вы можете использовать конечную точку api с помощью AJAX следующим образом

$(document).ready(function(){
    $.ajax({
        url: `localhost:8000/api/${1}/${2022}/${8}/`,
        dataType:'json',
        success: function(data){
            for(var i=0; i < data.length; i++){
                var item = $('<p>ID: '+ data[i].id +'<br>Titolo: '+ data[i].title +'<br>Autore: ' +
                    data[i].author  + '<br>Data: ' + data[i].pub_date +'</p>');
                $('#article_list').append(item);
            }
        }
    });
});

Это одно из возможных решений, после вклада Мэтьюса Мусукумы в ответы.

urls.py

#link to html files
path('<int:user_id>/<int:year>/<int:month>', views.index, name='index'),
#link to api
path('api/blog/<int:user_id>/<int:year>/<int:month>', views.get_articles, name='get_articles'),

Я отредактировал представление get_article(), которое создает JSON файл с объектами. Предложенный метод is_ajax() является устаревшим, поэтому я переписал его следующим образом:

def is_ajax(request):
    return request.META.get('HTTP_X_REQUESTED_WITH') == 'XMLHttpRequest'

def get_articles(request, **kwargs):
    if is_ajax(request=request):
        articles = Article.objects.filter(
            pub_date__year = kwargs.get('year'),
            pub_date__month = kwargs.get('month'),
        ).values('id','title','author','pub_date')

        data = {
            'articles': list(articles),
            'path_info': {
                    'month': kwargs.get('month'),
                    'year': kwargs.get('year'),
                    'user_id': kwargs.get('user_id'),
            }   
        }
        
        return JsonResponse(data, safe=False)
    else:
        raise Http404

В jquery я использовал window.location (https://stackoverflow.com/a/4944460/16057975) для получения текущего url. Поэтому я отредактировал его, чтобы он соответствовал правильному url api.

$(document).ready(function(){
    $url = window.location.pathname
    $url_api = 'http://127.0.0.1:8000/api'+$url
    $.ajax({
        data: $(this).serialize(),
        url: $url_api,
        dataType:'json',
        success: function(data){
           ...
        }
    });
});
Вернуться на верх