Django Rest framework with ajax pagination, how to switch data in the template? - ajax

How can I fill in the table data when switching to the next page using ajax pagination.
views.py
class PositionPageNumberPagination(PageNumberPagination):
page_size = 1
max_page_size = 5
def get_paginated_response(self, data):
context = {
'next': self.get_next_link(),
'previous': self.get_previous_link(),
'count': self.page.paginator.count,
'results': data,
}
return Response(context)
class PositionListAPIView(ListAPIView):
queryset = Position.objects.all().order_by('name')
serializer_class = PositionSerializer
pagination_class = PositionPageNumberPagination
def list(self, request, *args, **kwargs):
page = self.paginate_queryset(self.queryset)
if page is not None:
serializer = self.get_serializer(page, many=True)
return self.get_paginated_response(serializer.data)
serializer = self.get_serializer(self.queryset, many=True)
return Response({'data': serializer.data})
position_list.html
{% extends 'index.html' %}
{% load static %}
{% block title %}The list of positions{% endblock %}
{% block content %}
`
<div class="pagination">
<span>
<a id="previous">previous</a>
<a id="next">next</a>
</span>
<span id="count"></span>
</div>
<div>
<button id="add_position">Add</button>
<button id="edit_position">Edit</button>
<button id="delete_position">Delete</button>
</div>
{% endblock %}
{% block addscript %}
<script src="{% static 'js/positions.js' %}"></script>
{% endblock %}
urls.py
path('positions/', TemplateView.as_view(template_name='positions/position_list.html')),
position.js
When I click on 'next element', the data does not change, but the API is started (api / positions/?page=2)
$.ajax({
url : "/api/positions/",
dataType: "json",
success : function (data) {
let results = data.results;
let positions = $('.positions');
for (let i in results){
positions.append(`<tr id=${results[i].id}><td>${results[i].name}</td></tr>`)
}
$('#count').html(data.count);
$('#previous').attr('href', data.previous);
$('#next').attr('href', data.next);
}
});

Related

How to use values passed by jquery/ajax in django view

How do I retrieve and use the data passed to view via ajax? In this example I'm trying to implement a reddit like upvote/downvote system
html/js:
{% for post in posts %}
<h2>{{ post.title }}</h2>
{{ post.upvotes }}<button data-id="{{post.id}}" data-vote="up" class="vote" type="submit">Upvote</button>
{{ post.downvotes }}<button data-id="{{post.id}}" data-vote="down" class="vote" id="downvote" type="submit">Downvote</button>
{% endfor %}
<script>
$(".vote").click(function () {
var id = $(this).data("id"); //get data-id
var vote_type = $(this).data("vote"); //get data-vote
};
$.ajax({
url: '/ajax/upvote/',
data: {
'id': id,
'vote_type':vote_type,
}
});
</script>
urls.py:
url(r'^ajax/upvote/$', views.upvote, name='upvote'),
view:
def upvote(request):
#how do i use 'id' and 'vote_type' values here?
You need to first edit your javascript to send the csrf token, and register a POST url in your url.py .
{% for post in posts %}
<h2>{{ post.title }}</h2>
{{ post.upvotes }}<button data-id="{{post.id}}" data-vote="up" class="vote" type="submit">Upvote</button>
{{ post.downvotes }}<button data-id="{{post.id}}" data-vote="down" class="vote" id="downvote" type="submit">Downvote</button>
{% endfor %}
<script>
$(".vote").click(function () {
var id = $(this).data("id"); //get data-id
var vote_type = $(this).data("vote"); //get data-vote
};
$.ajax({
url: '/ajax/upvote/',
data: {
'id': id,
'vote_type':vote_type,
csrfmiddlewaretoken: '{{ csrf_token }}'
}
});
</script>
Now you can access the data you sent in your views.py in a usual way:
def upvote(request):
sentence= request.POST.get("id","")
upvote = request.POST.get("upvote","")
#continue doing your stuffs here...
Hope this helps.

Like Button In Django Ajax

my like button is working fine without ajax with page reloading but it is having problem when done by implementing ajax. the like and unlike is happening in the backend (like is created and deleted in database on ajax Post request), but the like count,like,unlike button does not change in response on ajax post request, until the page is reloaded. Need Help
here is the post model and like model for posting image and liking it in models.py
class PostModel(models.Model):
user = models.ForeignKey(UserModel)
image = models.FileField(upload_to='user_images')
image_url = models.CharField(max_length=255)
caption = models.CharField(max_length=240)
created_on = models.DateTimeField(auto_now_add=True)
updated_on = models.DateTimeField(auto_now=True)
has_liked = False
#property
def like_count(self):
return len(LikeModel.objects.filter(post=self))
class LikeModel(models.Model):
user = models.ForeignKey(UserModel)
post = models.ForeignKey(PostModel)
created_on = models.DateTimeField(auto_now_add=True)
updated_on = models.DateTimeField(auto_now=True)
url for liking in urls.py
url(r'^like/', like_view),
views.py
def like_view(request):
user = check_validation(request)
if user and request.method == 'POST':
form = LikeForm(request.POST)
if form.is_valid():
#post_id = form.cleaned_data.get('post').id
post_id=request.POST['post']
existing_like = LikeModel.objects.filter(post_id=post_id, user=user).first()
if not existing_like:
LikeModel.objects.create(post_id=post_id, user=user)
else:
existing_like.delete()
return redirect('/feed/')
else:
return redirect('/login/')
template.html
{% for post in posts %}
<form id="like_form">
{% csrf_token %}
<input type="hidden" name="post" id="post_id"value="{{ post.id }}">
{% if post.has_liked %}
<button class="btn btn-link unlike"type="submit"><i class="fa fa-heart" aria-hidden="true"style="color:#ed4956;"></i></button>
{% else %}
<button class="btn btn-link like"type="submit"><i class="fa fa-heart-o" aria-hidden="true"style=color:#333333;"></i></button>
{% endif %}
</form>
{% endfor %}
Javascript code
<script>
$(document).on('submit','#like_form',function (e) {
e.preventDefault();
$.ajax({
type:'POST',
url:'/like/',
data:{
post:$('#post_id').val(),
csrfmiddlewaretoken:$('input[name=csrfmiddlewaretoken]').val()
},
success:function (response) {
console.log("liked");
}
});
});
</script>

Get combined post from different categories using OctoberCMS RainLab Blog

I'm using Rain Lab Post in October CMS.
I have no problem using the blogPost component and get post from a single category. E.g. This is a partial where show the last 5 post from a category
[blogPosts]
pageNumber = "{{ :page }}"
categoryFilter = "{{ slug }}"
postsPerPage = 5
noPostsMessage = "No news in this category"
sortOrder = "published_at desc"
categoryPage = 404
postPage = "singlePost"
==
<li> {{category.name}}
<ul class="drop-down full-width col-5 hover-expand">
<li class="validation">
<h2 class="mm-title">{{category.name}}</h2>
</li>
{% for post in posts %}
<li>
{% for image in post.featured_images|slice(0,1) %}
<img src="{{ image.path }}" alt="">
{% endfor %}
<h3>{{post.title}}</h3>
</li>
{% endfor %}
</ul>
</li>
But now, I'm working in the home page and want to display the last post from all categories. 1 per category, 5 categories, combined.
Somebody knows how to do this?
Thanks in advance
Thanks to first aproach from Ahmed Essam, I resolve this in the next way:
function onStart(){
$categories = Db::table('rainlab_blog_categories')->get();
foreach ($categories as $key=>$category){
if($category->slug != 'uncategorized'){
$first = \Rainlab\Blog\Models\Category::with('posts')->where('id',$category->id)->first();
$data[] = $first->posts[0];
}
}
$this['posts'] = $data;
}
In the template I can use in this way
{% for post in posts %}
<li class="col-md-6 col-sm-6">
<div id="container">
{% for image in post.featured_images | slice(0,1) %}
<div class="thumb"><img src="{{image.path}}" alt=""></div>
{% endfor %}
<div class="content">
{% for category in post.categories %}
<div class="cat">{{category.name}}</div>
{% endfor %}
<h3>{{ post.title )}}</h3>
</div>
</div>
</li>
{% endfor %}
This way you have to fetch data manually in the code section of your page/layout.
function onStart() {
$first_category_post = \Rainlab\Blog\Models\Post::orderBy('id', 'desc')->where('category_id', 1)->first();
$second_category_post = \Rainlab\Blog\Models\Post::orderBy('id', 'desc')->where('category_id', 2)->first();
$third_category_post = \Rainlab\Blog\Models\Post::orderBy('id', 'desc')->where('category_id', 3)->first();
$fourth_category_post = \Rainlab\Blog\Models\Post::orderBy('id', 'desc')->where('category_id', 4)->first();
$fifth_category_post = \Rainlab\Blog\Models\Post::orderBy('id', 'desc')->where('category_id', 5)->first();
$array = $first_category_post->merge($second_category_post);
$array = $array->merge($third_category_post);
$array = $array->merge($fourth_category_post);
$array = $array->merge($fifth_category_post);
$this['posts'] = $array;
}
Another solution is to use usual php array_merge.
function onStart() {
$first_category_post = \Rainlab\Blog\Models\Post::orderBy('id', 'desc')->where('category_id', 1)->first();
$second_category_post = \Rainlab\Blog\Models\Post::orderBy('id', 'desc')->where('category_id', 2)->first();
$third_category_post = \Rainlab\Blog\Models\Post::orderBy('id', 'desc')->where('category_id', 3)->first();
$fourth_category_post = \Rainlab\Blog\Models\Post::orderBy('id', 'desc')->where('category_id', 4)->first();
$fifth_category_post = \Rainlab\Blog\Models\Post::orderBy('id', 'desc')->where('category_id', 5)->first();
$array = array_merge($first_category_post->toArray(), $second_category_posts->toArray());
$array = array_merge($array, $third_category_post->toArray());
$array = array_merge($array, $fourth_category_post->toArray());
$array = array_merge($array, $fifth_category_post->toArray());
$this['posts'] = $array->toJson();
}

Using AJAX to create an Object which then appears in dropdown box

Hi I've run into a problem where I am trying to make it so when a button is clicked an object can be made. I can't get it to work as for some reason it will not validate, however if I change input type to submit it works fine.
But the problem is when I use it as submit the page redirects which defeats the purpose of using AJAX.
I can't seem to find a good tutorial for what I'd like to do, any help or links would really be appreciated!
Models
class MemberRole(models.Model,get_fields):
name = models.CharField(max_length = 20)
Form
class MemberRoleForm(forms.ModelForm):
class Meta:
model = MemberRole
Views
This view builds the form for the memberrole model
def add_member(request):
model_url = 'member-add'
rform = MemberRoleForm(instance=MemberRole())
return render_to_response('create_model.html', {'role_form': rform,'model_url': model_url,},context_instance=RequestContext(request))
This ajax called view
#require_POST
def ajax(request):
data = request.POST.get("rolename","")
if request.method == 'POST':
rform = MemberRoleForm(request.POST, instance=MemberRole())
if rform.is_valid():
new_role = rform.save()
new_role.name = data
return HttpResponse("SuccessFully Saved")
else:
return HttpResponse("Error in saving")
Template
<div id="addRoleOnMemberForm">
<form id = "addrole" onsubmit= "return false;" method="POST">
{% csrf_token %}
{% for field in role_form %}
{{ field.errors }}
{{ field.label_tag }} {{ field }} //#id_name is in here
{% endfor %}
<input id="addrolebutton" type="button" onclick = "createit()" value="Add New Role"/>
</div>
{% for x in role_list %}
<div>
<p> This shows a role was made </p>
</div>
{% endfor %}
Script
<script>
function createit(){
$.ajax({
type: "POST",
url:"ajax",
dataType:"json",
async: true,
data: {
csrfmiddlewaretoken: '{{ csrf_token }}',
rolename: $('#id_name').val()
},
});
}
</script>
I've finally managed to get it to work. :)
I have an add_member view which allows the creation of a memberrole object if it is not available in the member.role dropdown field. The memberrole object on creation will be added without a page reload to the dropdown field so it can be selected immediatly.
I'm not entirely sure if this would be the correct way of coding it, I've included all the source and hopefully it helps someone like me. Comments would be appreciated!
Models
class MemberRole(models.Model,get_fields):
name = models.CharField(max_length = 20)
class Member(models.Model,get_fields):
first_name = models.CharField(max_length = 20)
last_name = models.CharField(max_length = 20)
role = models.ForeignKey(MemberRole, null = True, blank = True)
Forms
class MemberForm(forms.ModelForm):
class Meta:
model = Member
Script
<script>
function createit(){
$.ajax({
type: "POST",
url:"addrole",
dataType:"json",
async: true,
data: {
csrfmiddlewaretoken: '{{ csrf_token }}',
rolename: $('#role_name').val()
},
success: function (json,rolename){
$('#output').html(json.message); // Prints a message to say that the MemberRole object was created
$('#roleExistsMemberForm').load(document.URL + ' #roleExistsMemberForm'); //Refreshes the dropdown box so that the newly created MemberRole can be selected
}
});
}
</script>
Views
def add_role(request):
model_url = 'role-add'
new_role = request.POST.get("rolename","")
role_list = MemberRole.objects.all()
response_data= {}
if new_role:
x = MemberRole()
x.name = new_role
x.save()
response_data['message'] = new_role + " was created"
else:
response_data['message'] = 'Nothing created'
return HttpResponse(json.dumps(response_data),content_type="application/json")
def add_member(request):
model_url = 'member-add'
if request.method == "POST":
mform = MemberForm(request.POST, instance=Member())
if mform.is_valid():
new_member = mform.save(commit=False)
new_member.save()
return HttpResponseRedirect('members')
else:
mform = MemberForm(instance=Member())
return render_to_response('create_model.html', {'member_form': mform, 'model_url': model_url,},context_instance=RequestContext(request))
create_model.html
{% for field in member_form %}
{% if field.label == 'Role' %}
<div id="roleExistsMemberForm">
{{ field.errors }}
{{ field.label_tag }} {{ field }}
</div>
{% else %}
<div class="fieldWrapper">
{{ field.errors }}
{{ field.label_tag }} {{ field }}
</div>
{% endif %}
{% endfor %}
<div id="addRoleOnMemberForm">
<form onsubmit="return false;">
{% csrf_token %}
<input id= "role_name" type="text"/>
<input id="addrolebut" type="button" onclick = "createit()" value="Add New Role"/>
</div>
<div id="output">
<p>Nothing here</p>
</div>

Django - after submitting invalid form submit button upon click redirects

I have a django project in which i have a form in a div being loaded by ajax.
when I submit the form with empty fields it returns the form with the required fields shown.
when I hit submit again it redirects to the action of the form instead of reloading the form in the div and showing errors as it does the first time I submit.
does anyone have any idea where the error might be occurring? I imagine somewhere in the ajax or view in my django project.
here is what is returned by the second submit:
{"success": false, "form": "<head>\n\n</head>\n<body>\n<form action=\"/cookbook/createrecipe/\" method=\"POST\" name=\"recipeform\" id=\"createrecipeform\">\n\t<table>\n\t\t<div style='display:none'><input type='hidden' name='csrfmiddlewaretoken' value='c5ea952ee2144b377b375d91b0843c75' /></div>\n\t\t<tr><th><label for=\"id_name\">Name:</label></th><td><ul class=\"errorlist\"><li>This field is required.</li></ul><input id=\"id_name\" type=\"text\" name=\"name\" maxlength=\"200\" /></td></tr>\n<tr><th><label for=\"id_author\">Author:</label></th><td><ul class=\"errorlist\"><li>This field is required.</li></ul><input id=\"id_author\" type=\"text\" name=\"author\" maxlength=\"100\" /></td></tr>\n<tr><th><label for=\"id_picture\">Picture:</label></th><td><input type=\"file\" name=\"picture\" id=\"id_picture\" /></td></tr>\n<tr><th><label for=\"id_ingredients\">Ingredients:</label></th><td><ul class=\"errorlist\"><li>This field cannot be null.</li></ul><textarea id=\"id_ingredients\" rows=\"10\" cols=\"40\" name=\"ingredients\"></textarea></td></tr>\n<tr><th><label for=\"id_steps\">Steps:</label></th><td><ul class=\"errorlist\"><li>This field cannot be null.</li></ul><textarea id=\"id_steps\" rows=\"10\" cols=\"40\" name=\"steps\"></textarea></td></tr>\n<tr><th><label for=\"id_prep_time\">Prep time:</label></th><td><ul class=\"errorlist\"><li>This field is required.</li></ul><input type=\"text\" name=\"prep_time\" id=\"id_prep_time\" /></td></tr>\n<tr><th><label for=\"id_type\">Type:</label></th><td><ul class=\"errorlist\"><li>This field is required.</li></ul><select name=\"type\" id=\"id_type\">\n<option value=\"\" selected=\"selected\">---------</option>\n<option value=\"SW\">Sandwich</option>\n<option value=\"AP\">Appetizers</option>\n<option value=\"SD\">Sauces and Dressings</option>\n<option value=\"SS\">Soups and Salads</option>\n<option value=\"VG\">Vegetables</option>\n<option value=\"RG\">Rice, Grains and Beans</option>\n<option value=\"PA\">Pasta</option>\n<option value=\"BR\">Breakfast</option>\n<option value=\"MT\">Meat</option>\n<option value=\"SF\">Seafood</option>\n<option value=\"BP\">Bread and Pizza</option>\n<option value=\"DT\">Desserts</option>\n</select><input type=\"hidden\" name=\"reset_recipe\" id=\"id_reset_recipe\" /></td></tr>\n\t</table>\n\t<p><input type=\"submit\" value=\"Submit\"></p>\n</form>\n</body>"}
here is my ajax code:
<script type="text/javascript">
$(document).ready(function(){
var form = $('form#createrecipeform');
form.submit(function(e) {
e.preventDefault();
console.log('ajax form submission function called successfully.');
//form = $(this);
console.log(form)
var serialized_form = form.serialize();
$.ajax({ type: "POST", 
url: $(this).attr('action'),
data: serialized_form, 
success: (function(data) { 
console.log('ajax success function called successfully.');
data = $.parseJSON(data);
if (data.success) {
console.log('success');
} else {
console.log('failure');
var newForm = data.form;
form.replaceWith(newForm);
}
})
});
return false;
});
});
</script>
here is the view: (createrecipe is the action of the form and account is the page that is loading the ajax)
def createrecipe(request):
print "entering createrecipeview"
if request.method == 'POST':
print "form is a post"
form = RecipeForm(request.POST)
print form.errors
if form.is_valid():
print "form is valid"
form = RecipeForm(initial = {'original_cookbook' : request.user.cookbooks.all()[0]})
form = form.save()
t = loader.get_template('cookbook/create_form.html')
c = RequestContext(request, {
'form': form,
})
data = {
'replace': True,
'form': t.render(c),
'success': True,
}
json = simplejson.dumps(data)
return HttpResponse(json, mimetype='text/plain')
else:
print "form is invalid"
form = RecipeForm(request.POST)
t = loader.get_template('cookbook/create_form.html')
c = RequestContext(request, {
'form':form,
})
data ={
'form': t.render(c),
'success': False,
}
json = simplejson.dumps(data)
return HttpResponse(json, mimetype='text/plain')
def account(request):
user = request.user
if request.user.is_authenticated():
cookbooks = user.cookbooks
if cookbooks.all().exists():
cookbook = cookbooks.all()[0]
form = RecipeForm(initial = {'original_cookbook' : request.user.cookbooks.all()[0]})
recipe_list = cookbook.recipes.all()
else:
raise Http404
else:
return HttpResponseRedirect('/accounts/login')
t = loader.get_template('cookbook/account.html')
c = RequestContext(request, {
'form': form,
'recipe_list': recipe_list
})
return HttpResponse(t.render(c))
here is the create_form.html template:
<head>
</head>
<body>
<form action="{% url cookbook.views.createrecipe %}" method="POST" name="recipeform" id="createrecipeform">
<table>
{% csrf_token %}
{{ form.as_table }}
</table>
<p><input type="submit" value="Submit"></p>
</form>
</body>
and here is the account template that includes the create_form template:
{% extends "cookbook/base.html" %}
{% load pagination_tags %}
{% load comments %}
<h1>{{ user }}'s Cookbook</h1>
<ul>
{% block nav-cookbooks %}
<li><a class="nav-inactive" href="/cookbooks/">Cookbooks</a></li>
{% endblock %}
{% block nav-account %}
<li><a class="nav-active" href="/account/">My Cookbook</a></li>
{% endblock %}
</ul>
{% block content %}
{% autopaginate recipe_list 6 %}
<div id="recipe_cont">
{% for recipe in recipe_list %}
<div class="recipe">
<div class="button">
<img src="{{ STATIC_URL }}chicknbraw.jpg" alt="" height="70" width="70" style="display:inline;" />
<h4>{{ recipe.name }}</h4>
</div>
<h5>{{ recipe.author }}</h5>
<h5>Prep Time: {{ recipe.prep_time }} minutes</h5>
<h6>Add Recipe
Remove Recipe</h6>
</div>
{% endfor %}
</div>
<div id="popupContact" class="popup">
<a id="popupContactClose" style="cursor:pointer;float:right;">x</a>
<p id="contactArea">
<h1 style="text-align:center">Create New Recipe</h1>
{% include 'cookbook/create_form.html' %}
</p>
</div>
<div id="backgroundPopup">
</div>
<div id="col2-footer">
{% paginate %}
<p id="recipe_order_text"> order by: abc|date
</div>
{% endblock %}
{% block footer %}
<a class="create" style="cursor:pointer" >Create New Recipe</a>
{% endblock %}
sorry for putting so much code but it all seems to rely upon another piece of code so I figured all relevant code would be helpful
thanks for any help you can give me
katie
In your javascript, you're hijacking the form so that it submits via ajax, but then you're calling replaceWith on the form, so your hijacked form gets obliterated and is replaced with a new, non-hijacked form. To solve this you can either
1) Only replace the content of the form - this should work since you're only attaching events to the form itself and not its child elements
2) Write your js as a function which you can call firstly on the initial form, and subsequently on any new forms loaded via ajax.
UPDATE: for example,
<script type="text/javascript">
$(document).ready(function(){
function hijack() {
var form = $('form#createrecipeform');
form.submit(function(e) {
e.preventDefault();
console.log('ajax form submission function called successfully.');
//form = $(this);
console.log(form)
var serialized_form = form.serialize();
$.ajax({ type: "POST",
url: $(this).attr('action'),
data: serialized_form,
success: (function(data) {
console.log('ajax success function called successfully.');
data = $.parseJSON(data);
if (data.success) {
console.log('success');
} else {
console.log('failure');
var newForm = data.form;
form.replaceWith(newForm);
hijack();
}
})
});
return false;
});
};
hijack();
});
</script>

Resources