skip to Main Content

In my server-side app created with Django, I need to show articles based on the url, which contains year, month and user_id of articles.
blog/1/2022/8 should shows all articles of august.

In client-side app (Jquery), I have to call an API which returns all articles filtered by year and month.

How can I set the url in ajax with the variable informations of year and month?

urls.py (I have to use these 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'),
]

Model:

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

Views:

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);
            }
        }
    });
});

Bonus question: I should serialize data used by API, but How can I do without rest_framework?

If you are wondering why without REST Framework, It’s for educational purpose.

2

Answers


  1. Chosen as BEST ANSWER

    This is one possible solution, after the contribution of Mathews Musukuma in answers.

    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'),
    

    I edited the view get_article() which creates the JSON file with objects. The is_ajax() method suggested is deprecated, so I overwrote it like this:

    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
    

    In jquery I used window.location (https://stackoverflow.com/a/4944460/16057975) to get the current url. So I edited it to match the correct url of 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){
               ...
            }
        });
    });
    

  2. First you need to clean the 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'),
    ]
    

    For your API view, you can use check if request is request.is_ajax() then do something within the if statement block.

    def get_articles(request, author_id, year, month):
        if request.is_ajax():
            articles = Article.objects.filter(
                author_id=author_id,
                pub_date__year=year,
                pub_date__month=month,
            ) 
    
            data = {
                'articles' : list(articles)
            }
            return JsonResponse(data)
        else:
            raise Http404
    

    Now you can use the api endpoint with AJAX as follows

    $(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);
                }
            }
        });
    });
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search