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 >
<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.
CodePudding user response:
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);
}
}
});
});
CodePudding user response:
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){
...
}
});
});