how can I get Django-ajax popup button to work? - ajax

I am trying to create a popup form for a New Task in my calendar, but I have never get it to work. I am using Ajax for this purpose. Here is my code. The Ajax is located in the static folder under the name "plugin.js"
base.py
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Bookstore</title>
<link href="{% static 'css/bootstrap.min.css' %}" rel="stylesheet">
</head>
<body>
<div class="container">
{% block content %}
{% endblock %}
</div>
<script src="{% static 'js/jquery-3.1.1.min.js' %}"></script>
<script src="{% static 'js/bootstrap.min.js' %}"></script>
<script src="{% static 'js/plugin.js' %}"></script>
{% block javascript %}
{% endblock %}
</body>
</html>
calendar.html
{% extends 'cal/base.html' %}
{% block title %}
Quality Assurance Calendar
{% endblock %}
{% block content %}
<div class="clearfix">
<a class="btn btn-info left" href="{% url 'cal:calendar' %}?{{ prev_month }}"> Previous Month </a>
<a class="btn btn-info right" href="{% url 'cal:calendar' %}?{{ next_month }}"> Next Month </a>
{% if user.is_authenticated %}
<button type="button" class="btn btn-primary show-form">
<span class="glyphicon glyphicon-plus"></span>
New Task
</button>
{% endif %}
</div>
{{ calendar }}
<div class="modal-fad" id="modal-task">
<div class="modal-dialog">
<div class="modal-content"></div>
</div>
</div>
{% endblock %}
part of the view.py
def task_create(request, task_id=None):
# if not request.user.is_authenticated:
# return redirect('%s?next=%s' % ('account/login/', request.path))
instance = Task()
if task_id:
instance = get_object_or_404(Task, pk=task_id)
else:
instance = Task()
form = TaskForm(request.POST or None, instance=instance)
# form.user = request.user
if request.POST and form.is_valid():
# form = form.save(commit=False)
# form.user = request.user
form.save()
# return HttpResponseRedirect(reverse('cal:calendar'))
# return render(request, 'cal/task_create.html', {'form': form})
html_form=render_to_string('cal/task_create.html', {'form': form}, request=request)
return JsonResponse({'html_form':html_form})
And the plugin.js
$(document).ready(function(){
$('.show-form').click(function(){
$.ajax({
url: '/task/create',
type: 'get',
dataType:'json',
beforeSend: function(){
$('#modal-task').modal('show');
},
success: function(data){
$('#modal-task .modal-content').html(data.html_form);
}
})
})
task_create.html
{% load crispy_forms_tags %}
<button class="btn btn-primary show-form" data-url="{% url 'cal:task_create' %}"></button>
{% csrf_token %}
<!-- Modal Header -->
<div class="modal-header">
<h5 class="modal-title">Create Task</h5>
<button type="button" class="close" data-dismiss="modal" aria-lable ="Close">
<span aria-hidden="True">×</span>
</button>
</div>
{{ form|crispy}}
<div class="modal-body">
Modal body..
</div>
<!-- Modal footer -->
<div class="modal-footer">
<button type="button" class="btn btn-danger" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary" >Save changes</button>
</div>
</form>
The new task button has never responded!!!
'''''''''''''''''''''''''''''''''''''''''''''''

sorted out.
I have got all what i need in this tutorial
Here is the link (https://simpleisbetterthancomplex.com/tutorial/2016/08/29/how-to-work-with-ajax-request-with-django.html)
thanks to all for the valuable comments.

Related

Why Symfony Controller return template snipped with <html> and <body> tags?

I have a controller-action:
/**
* Get the template for the notifications in the user-navbar
*
* #Route("/notification/get-template", name="get_notifications_template")
* #param Request $request
* #return Response
*/
public function getNotificationsTemplateAction(Request $request)
{
if (!$request->isXmlHttpRequest()) {
return $this->redirect($this->generateUrl('homepage'));
}
return $this->render('Menu/_notifications_block.html.twig');
}
I want to do an AJAX call with to get this template:
refreshNotifications() {
$.ajax({
url: this.$wrapper.data('refresh-action-path'),
method: 'POST',
}).then(function (data) {
// remove old notifications
this.$wrapper.remove();
// append data to the container
$('#user-notifications-container').append(data);
console.log(data);
}.bind(this))
}
The problem is now - that the Symfony container sends a whole html page:
the template is that:
{% if app.user is not null and is_granted('ROLE_USER') %}
{% if app.user|notifications|length != 0 %}
{% set notifications = app.user|notifications %}
{% set all_notification_count = notifications|length %}
<li class="nav-item mx-2 dropdown js-notification-wrapper data-refresh-action-path="{{ path('get_notifications_template') }}"">
<a href="#" class="icon-wrapper nav-link btn-lg" data-toggle="dropdown">
<span class="icon icon-mail" aria-hidden="true"></span>
<span class="badge badge-notification">{{ all_notification_count }}</span>
</a>
<ul class="dropdown-menu dropdown-menu-right notification-list">
{% if app.user is not null and is_granted('ROLE_USER') and all_notification_count != 0 %}
{% for notification in notifications %}
<div class="notification-text">
<div class="d-flex">
<div class="col-10 px-0">
Kurszugang: {{ notification.courseAction.course }} ({{ notification.courseAction.course.school }})
- {{ notification.courseAction.schoolUser }}
</div>
<div class="col-2">
<button class="btn btn-sm btn-success" id="js-accept-course-action" data-course-action-path="{{ path('course_action_accept_join_request', {'courseAction' : notification.courseAction.id}) }}">
<i class="icon icon-thumbs-up"></i>
</button>
<button class="btn btn-sm btn-secondary" id="js-decline-course-action" data-course-action-path="{{ path('course_action_decline_join_request', {'courseAction' : notification.courseAction.id}) }}">
<i class="icon icon-thumbs-down"></i>
</button>
</div>
</div>
</div>
</li>
{% endfor %}
{% endif %}
</ul>
</li>
{% endif %}
{% endif %}
Can somebody tell me - why I can't only the snipped but a whole html page?
I can not append this whole page to the container ...
The way I understand it render returns a complete response(with headers), while renderView will just return the html.
Try changing this line:
return $this->render('Menu/_notifications_block.html.twig');
to this:
return new JsonResponse([
'html'=> $this->renderView('Menu/_notifications_block.html.twig')
]);
then in the ajax function change:
$('#user-notifications-container').append(data);
to this:
$(data.html).appendTo('#user-notifications-container');

VueJS : v-for not rendering

I'm trying vueJS (+ laravel) and i'm encountering a problem.
I made an OrdersComponent.vue with a v-for (for each order which I retrieved from my API), but nothing happens
OrderComponent.vue : (h1 is rendering, and console.log(this.orders) is working)
<template>
<div>
<h1> Commandes </h1>
<div class="card card-body" v-for="order in orders" v-bind:key="order.idCommande">
<h2> {{ order.date }} </h2>
<span> {{ order.statut }} </span>
</div>
</div>
</template>
<script>
import Vue from 'vue'
export default Vue.extend({
data() {
return {
orders: [],
order: {
idCommande: '',
date: '',
prix: '',
statut: '',
},
orderId: '',
edit: false
}
},
methods: {
fetchOrders() {
fetch('api/orders')
.then(res => res.json())
.then(res => {
this.orders = res.data;
console.log(this.orders);
})
}
},
created() {
this.fetchOrders();
}
})
</script>
Page which call the component (orders.blade.php) :
#extends('layouts.app')
#section('content')
<orders></orders>
#endsection
finally, layouts.app file :
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- CSRF Token -->
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>{{ config('app.name', 'Laravel') }}</title>
<!-- Scripts -->
<script src="{{ asset('js/app.js') }}" defer></script>
<!-- Fonts -->
<link rel="dns-prefetch" href="https://fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css?family=Nunito" rel="stylesheet" type="text/css">
<!-- Styles -->
<link href="{{ asset('css/app.css') }}" rel="stylesheet">
</head>
<body>
<div id="app">
<nav class="navbar navbar-expand-md navbar-light navbar-laravel">
<div class="container">
<a class="navbar-brand" href="{{ url('./') }}">
MyOnlineCV
</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="{{ __('Toggle navigation') }}">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<!-- Left Side Of Navbar -->
<ul class="navbar-nav mr-auto">
</ul>
<!-- Right Side Of Navbar -->
<ul class="navbar-nav ml-auto">
<!-- Authentication Links -->
#guest
<li class="nav-item">
<a class="nav-link" href="{{ route('login') }}">{{ __('Login') }}</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{ route('register') }}">{{ __('Register') }}</a>
</li>
#else
<li class="nav-item dropdown">
<a id="navbarDropdown" class="nav-link dropdown-toggle" href="#" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" v-pre>
{{ Auth::user()->username .' '. Auth::user()->email }} <span class="caret"></span>
</a>
<div class="dropdown-menu dropdown-menu-right" aria-labelledby="navbarDropdown">
<a class="dropdown-item" href="{{ route('commandes') }}"> Mes commandes </a>
<a class="dropdown-item" href="{{ route('logout') }}"
onclick="event.preventDefault();
document.getElementById('logout-form').submit();">
{{ __('Logout') }}
</a>
<form id="logout-form" action="{{ url('/logout') }}" method="GET" style="display: none;">
#csrf
</form>
</div>
</li>
#endguest
</ul>
</div>
</div>
</nav>
<main class="py-4">
<div id="app">
<div class="container">
#yield('content')
</div>
</div>
</main>
</div>
<script src="{{ asset('js/app.js') }}"></script>
</body>
</html>
Maybe you have already fixed it but in my case I was using an arrow function in methods but it was not working this way. I had to change it to "normal" function declaration like so:
methods: {
fetchOrders: function() {
fetch('api/orders').then(res => res.json())
.then(res => {
this.orders = res.data;
console.log(this.orders);
});
}
},
Try to remove this from your component`s data() method:
...
order: {
idCommande: '',
date: '',
prix: '',
statut: '',
},
orderId: '',
...
You declare "order" in v-for section:
v-for="order in orders"
May be you forgot to recompile your app after making change.
Remove order object from data()
order:{
idCommande: '',
date: '',
prix: '',
statut: '',
}
and recompile the app using:
npm run dev
Moreover:
We create this kind of objects when we are going to submit some data using a form.
For example
For signup/register, we get user name, email, age, etc and save it into an object like below by calling each value in a template (e.g. user.name)
user:{
name:'',
email:'',
age: '',
}
and then we just send user object via axios or fetch to the server.

Loading block in Twig with no refresh

i am using CodeIgniter with Twig, i wonder how can i load only the content block
without refreshing the page. I've seen this topic has been discussed but with Sympony Framework which i'm not familiar with.
I want to load only the Block Content area without refresh, I've tried to load the controller with Ajax but it keeps loading the whole page - including the header, footer etc.
Thanks.
Here is the base file - base.twig :
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>{{ site_title }} | CRM</title>
{% include 'templates/css.twig' %}
</head>
<body class="skin-blue sidebar-mini" style="height: auto;">
<div class="wrapper">
{% include 'templates/header.twig' %}
{% include 'templates/side_bar.twig' %}
<div class="content-wrapper">
<!-- Main content -->
<section class="content">
<div id="{{ site_title }}">
{% block content %}
{% endblock %}
</div>
</section>
</div>
{% include 'notifications_modal.twig' %}
</div>
{% include 'templates/footer.twig' %}
</body>
</html>
Here is the controller - about.twig
class About extends MY_Controller {
public function __construct()
{
parent::__construct();
}
public function index()
{
$this->data['site_title'] = 'about';
$this->twig->display('about',$this->data);
}
}
And here is the view - about.twig
{% extends "base.twig" %}
{% block content %}
<div class="row">
<div class="col-md-12">
<h1>TO DO {{ site_title }}</h1>
</div>
</div>
{% endblock %}

Add likes and page visit counts to Django project

I'm trying to give users ability to like/dislike objects (using ajax), and to count page visits. I've written functions and changed the templates but there's a mistake somewhere. The result of likes and views is always 0. It seems to me that the mistake is in views.py functions, but maybe I'm wrong, I'm a beginner in Django. Now according to the functions it is allowed for a user to like an object more then one time. I would like to let the user not to do so, but to give an ability to dislike the object. But first I would like at least a simple to work properly. First I tried to count the number of visits of user page and to add likes for model Day.
Could you please tell me how to correct my files?
This is a part of view:
#login_required
def like_day(request):
day_id = None
if request.method == 'GET':
if 'day_id' in request.GET:
day_id = request.GET['day_id']
likes = 0
if day_id:
day = Day.objects.get(id=int(day_id))
if day:
likes = day.likes + 1
day.likes = likes
day.save()
return HttpResponse(likes)
def track_url(request):
person_id = None
url = '/friends_plans/users/'
if request.method == 'GET':
if 'person_id' in request.GET:
person_id = request.GET['person_id']
try:
person = Person.objects.get(id=person_id)
person.views = person.views + 1
person.save()
url = person.url
except:
pass
return redirect(url)
This are list.html (there must be a number of page views for each user)
{% extends 'friends_plans/base.html' %}
{% load staticfiles %}
{% block title %} Users {% endblock %}
{% block content %}
<div id ="left">
<div id="toptitle"> Friends' Plans members:</div>
<table class="table">
<thead>
<tr>
<th>Photo</th>
<th>Name</th>
<th>Occupation</th>
<th>Days</th>
<th>Places</th>
<th>Wiews</th>
</tr>
</thead>
<tbody>
{% for person in users %}
<tr>
<td><span> <img class="small_cat" src={% static 'images/cat3.jpg' %} /> </span></td>
<td>{{ person.username|upper }}</span></td>
<td><span>Student at {{ person.place_of_work_or_study}}</span></td>
<td>{{person.day_set.all.count}}</td>
<td>{{person.wish_list_set.all.count}}</td>
<td>{{person.wish_list.comment_to_wish_list_set.all.count}}</td>
<td>{% if person.views >= 0 %}
{{person.views}} views
{% elif person.views == 1 %}
{{person.views}} view
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="pagination">
<div id="listing">
<span class="step-links">
{% if users.has_previous %}
previous
{% endif %}
<span class="current">
Page {{ users.number }} of {{ users.paginator.num_pages }}.
</span>
{% if users.has_next %}
next
{% endif %}
</span>
</div>
</div>
</div>
{% endblock %}
This is day.html (there's a like button there)
<!DOCTYPE html>
{% load staticfiles %}
<html >
<head>
<title> {{person.username}} </title>
<meta charset ="utf -8" />
<link rel="stylesheet" href="{% static 'css/style_day.css' %}">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.2/jquery.min.js"> </script>
<script src="{% static 'js/friends_plans-jquery.js' %}"></script>
<script src="{% static 'js/friends_plans-ajax.js' %}"></script>
</head>
<body>
<div id ="container">
<div id ="header">
<ul id ="menu">
<span><a href ="" >Friends' Plans</a></span>
<span><a href ="{% url 'friends_plans:user' request.user.pk %}" >My Page</a></span>
<span><a href ="{% url 'friends_plans:listing' %}" >Users</a></span>
<span><a id="helpbutton" href ="" >HELP</a></span>
</ul>
</div>
<div id ="left">
<div id="border">
<div><a class="button" href="{% url 'friends_plans:user' person.pk %}">{{person.username}}</a></div>
<img class="cat" src={% static 'images/cat5.jpg' %} />
</div>
<div id="info">
<div class ="name"> {{person.email}} </div>
<div class ="name"> {{person.phone_number}} </div>
<div class ="name"> Student of {{person.place_of_work_or_study}} </div>
</div>
<div id="empty"> </div>
</div>
<div id ="right">
<div class="sep">
<div class="title"> {{person}}'s plans for {{day}}: </div>
<div class="value"> Status: {{day.level_of_business}} </div>
{% for event in day.event_set.all %}
<div class="title1"> <a class="button" href ="">Business: {{event.business}}</a></div>
<div class="title1"> Type: {{event.type}}</div>
<div class="title1"> Period of time: {{event.start_time}}-{{event.end_time}}</div> <br />
{% endfor %}
</div>
<p>
<strong id="like_count">{{ day.likes }}</strong> users like this day
{% if user.is_authenticated %}
<button id="likes" data-catid="{{day.id}}" class="btn btn-primary" type="button">
<span class="glyphicon glyphicon-thumbs-up"></span>
Like
</button>
{% endif %}
</p>
<div>
{% if person.id == request.user.id %}
Add event
{% endif %}
</div>
</div>
<div id ="footer"> Copyright </div>
</div>
</body>
</html>
And this is ajax file:
$('#likes').click(functin()){
var catid;
catid = $(this).attr("data-catid");
$.get('/friends_plans/like_day/', {day_id: catid}, function(data){
$('#like_count').html(data);
$('#likes').hide();
});
});
And these are my models, Person:
class Person (AbstractUser):
phone_number = models.CharField(max_length=30)
place_of_work_or_study = models.CharField(max_length=100)
img = models.ImageField(upload_to='photos/', null=True, blank=True)
url = models.URLField(null=True, blank=True)
views = models.IntegerField(default=0)
class Meta:
verbose_name = 'Person'
verbose_name_plural = 'Users'
def __unicode__(self):
return self.username
And Day:
class Day(models.Model):
person = models.ManyToManyField(Person)
date = models.DateField()
url = models.URLField(null=True, blank=True)
views = models.IntegerField(default=0)
likes = models.IntegerField(default=0)
levels = (
('busy', 'busy'),
('has_suggestions', 'has_suggestions'),
('waiting_for_suggestions', 'waiting_for_suggestions')
)
level_of_business = models.CharField(choices=levels, max_length=40, default='waiting_for_suggestions')
def __unicode__(self):
return unicode(self.date)
The syntax of your AJAX code is not correct. It should be
$('#likes').click(function(){
var catid;
catid = $(this).attr("data-catid");
$.get('/friends_plans/like_day/', {day_id: catid}, function(data){
$('#like_count').html(data);
$('#likes').hide();
});
});
Furthermore, please note that you should not use GET to manipulate data on the server. This can be abused by CSRF attacks. Use POST instead.
If you choose to use POST you should not forget to generate a csrf-token in the template and send it together with the request either as a X-Header or inside a cookie.
The solution for the problem was to add $(document).ready( function(){})to AJAX request.

Get template block contents and call from ajax

I'm using django 1.9 and python 3. My english also isn't the best, so excuse the question if it is formulated bad.
I'm working on making my website a single-page application. I need to get the {% block %} contents of a given template, and then send that as a HttpResponse so that ajax can pick it up and inject it into the page.
I've tried using the answer from this question: Django - how to get the contents of a {% block %} tag from a template
But upon trying to fetch the contents of a block in my view like so:
response_data[content] = get_block_source('profile/login.html', 'content')
if request.is_ajax():
return HttpResponse(
json.dumps(response_data),
content_type="application/json"
)
I just get this error from django, no matter what I do:
ValueError at /login/ Template block content not found
The contents of the block don't even make it to the ajax call, what gives?
EDIT:
I'll include my "content" block here:
in my template:
{% extends 'base.html' %}
{% block content %}
<div class="big-title text">Log in</div>
<div class="form-container">
<form name="login-form" id="user" method="post" action="/login/" enctype="multipart/form-data" class="text">
{% csrf_token %}
<div class="title">Enter your credentials</div>
<div class="form-row">
<div class="form-flex">
<div class="field-container">
<div class="field-input-container">
<div class="field-label accent">Username</div>
<div class="field-input">
<input class="field-input-element" type="text" name="username" />
</div>
</div>
<div class="field-help">Your username is always lowercase.</div>
</div>
</div>
<div class="form-flex">
<div class="field-container" style="height: 110px">
<div class="field-input-container">
<div class="field-label accent">Password</div>
<div class="field-input">
<input class="field-input-element" type="password" name="password" />
</div>
</div>
<div class="field-help"></div>
</div>
</div>
</div>
<div class="form-button-container">
<div class="form-error"></div>
<div class="form-message"></div>
<input type="submit" name="submit" value="Accept" class="button form-button"/>
</div>
</form>
</div>
{% endblock %}
In my base (base.html)
<body>
<div id="modal-container">
<div id="modal-overlay">
<div id="modal-items">
</div>
</div>
</div>
<div id="wrapper">
<header>
<div id="header-title" class="text accent">App name</div>
<div id="header-nav">
<nav>
{% if user.is_authenticated %}
Home
Feed {% if request.user.is_superuser %}
Admin {% endif %}
N
<a href="/{{ request.user }}" class="header-avatar-small-a">
<div class="text header-greeting">Hi, {{ user.userprofile.display_name }}</div>
<div class="header-avatar-small">
{% if not user.userprofile.avatar == '' %}
<img src="{{ MEDIA_URL }}users/{{ user }}/avatar" alt=""> {% else %}
<img src="{{ MEDIA_URL }}users/avatar" alt=""> {% endif %}
</div>
</a>
{% else %}
Log in
Create account {% endif %}
</nav>
</div>
<div class="progress">
<div id="header-progress" class="fill"></div>
</div>
</header>
<main>
{% block content %} {% endblock %}
</main>
<footer></footer>
</div>
</body>
</html>
Template source is the template actual HTML, not the file reference

Resources