Chat Room in Django Channels - javascript

I have models "Project" and "Room". Every project has own chat room. I am tring to use Django Channels. Unfortunarly, I have error. What I miss and how to fix this error.
ERROR:
Traceback (most recent call last):
File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\core\handlers\exception.py", line 39, in inner
response = get_response(request)
File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\core\handlers\base.py", line 187, in _get_response
response = self.process_exception_by_middleware(e, request)
File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\channels\handler.py", line 237, in process_exception_by_middleware
return super(AsgiHandler, self).process_exception_by_middleware(exception, request)
File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\core\handlers\base.py", line 185, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\contrib\auth\decorators.py", line 23, in _wrapped_view
return view_func(request, *args, **kwargs)
File "C:\Users\Nurzhan\PycharmProjects\RMS\project\views.py", line 176, in chat_room
room, created = Room.objects.get_or_create(project=project_code)
File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\db\models\manager.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\db\models\query.py", line 475, in get_or_create
return self._create_object_from_params(lookup, params)
File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\db\models\query.py", line 505, in _create_object_from_params
obj = self.create(**params)
File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\db\models\query.py", line 397, in create
obj = self.model(**kwargs)
File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\db\models\base.py", line 537, in __init__
setattr(self, field.name, rel_obj)
File "C:\Users\Nurzhan\AppData\Local\Programs\Python\Python35-32\lib\site-packages\django\db\models\fields\related_descriptors.py", line 211, in __set__
self.field.remote_field.model._meta.object_name,
ValueError: Cannot assign "'1744d0bc-e439-4562-9c29-4e7b2451f39c'": "Room.project" must be a "Project" instance.
urls.py:
url(r'^(?P<project_code>[0-9a-f-]+)/chat_room/$', chat_room, name='chat_room'),
settings.py:
CHANNEL_LAYERS = {
"default": {
"BACKEND": "asgi_redis.RedisChannelLayer",
"CONFIG": {
"hosts": [os.environ.get('REDIS_URL', 'redis://localhost:6379')],
},
"ROUTING": "chat.routing.channel_routing",
},
}
models.py:
class Room(models.Model):
project = models.ForeignKey(Project, on_delete=models.CASCADE)
code = models.UUIDField(_('Code'), primary_key=True, default=uuid.uuid4, editable=False)
def __str__(self):
return self.code
def get_absolute_url(self):
return reverse('project:chat_room', args=[self.project_code])
class Message(models.Model):
room = models.ForeignKey(Room, related_name='messages')
handle = models.TextField()
message = models.TextField()
timestamp = models.DateTimeField(default=timezone.now, db_index=True)
def __unicode__(self):
return '[{timestamp}] {handle}: {message}'.format(**self.as_dict())
def __str__(self):
return self.__unicode__()
#property
def formatted_timestamp(self):
return self.timestamp.strftime('%b %-d %-I:%M %p')
def as_dict(self):
return {'handle': self.handle, 'message': self.message, 'timestamp': self.formatted_timestamp}
views.py:
def chat_room(request, project_code):
# If the room with the given project_code doesn't exist, automatically create it upon first visit.
room, created = Room.objects.get_or_create(project=project_code)
# We want to show the last 50 messages, ordered most-recent-last
messages = reversed(room.messages.order_by('-timestamp')[:50])
return render(request, "project/chat/room.html", {
'room': room,
'messages': messages,
})
consumers.py:
#channel_session
def ws_connect(message):
prefix, project_code = message['path'].strip('/').strip('/').strip('/').strip('/').strip('/').strip('/')
room = Room.objects.get(project=project_code)
message.reply_channel.send({"accept": True})
Group('chat' + project_code).add(message.reply_channel)
message.channel_session['room'] = room.project
#channel_session
def ws_receive(message):
project_code = message.channel_session['room']
room = Room.objects.get(project=project_code)
data = json.loads(message['text'])
m = room.messages.create(handle=data['handle'], message=data['message'])
Group('chat' + project_code).send({'text': json.dumps(m.as_dict())})
#channel_session
def ws_disconnect(message):
project_code = message.channel_session['room']
Group('chat' + project_code).discard(message.reply_channel)
routing.py:
channel_routing = [
route("websocket.connect", ws_connect),
route("websocket.receive", ws_receive),
route("websocket.disconnect", ws_disconnect),
]
chat.js:
$(document).ready(function(){
socket = new WebSocket("ws://" + window.location.host + "/chat" + window.location.pathname);
var name = "";
swal({
title: 'Your name:',
input: 'text',
inputValidator: function (value) {
return new Promise(function (resolve, reject) {
if (value) {
resolve()
} else {
reject('You need to write something!')
}
})
}
}).then(function (result) {
name = result;
swal({
type: 'success',
html: 'Hello ' + result
})
});
socket.onopen = function(){
$('#chatform').on('submit', function(event) {
var message = {
handle: name,
message: $('#message').val(),
}
socket.send(JSON.stringify(message));
$('#message').val('');
return false;
});
}
socket.onmessage = function(message) {
var data = JSON.parse(message.data);
$('#chat').append('<tr>'
+ '<td>' + data.timestamp + '</td>'
+ '<td>' + data.handle + '</td>'
+ '<td>' + data.message + ' </td>'
+ '</tr>');
Push.create("Django Channels Example | " + room , {
body: "New Message",
icon: 'http://pa1.narvii.com/6184/91c955faf54e625b3467093bea75a6d25b813871_128.gif',
timeout: 4000,
onClick: function () {
window.focus();
this.close();
}
});
};
if (socket.readyState == WebSocket.OPEN) socket.onopen();
});

Related

I can't pass values to database with Ajax and Django

i'm new in Ajax and Django i'm try sent videoP1 = 1 when percentage = 100 i'm use script tag on html to write js To get videoP1-videoP17 from database via views.py to set value in array and call it.
var videos = [
{
id: 1,
name: "1",
src: "../static/frontend/video/1.mp4",
videoP1: {{ video_db.videoP1 }},
},
{
id: 2,
name: "2",
src: "../static/frontend/video/2.mp4",
videoP2: {{ video_db.videoP2 }},
},
{
id: 17,
name: "17",
src: "../static/frontend/video/17.mp4",
videoP17: {{ video_db.videoP17 }},
},
];
var player = videojs("videoP");
function light(Cvideo) {
for (let i = 0; i < videos.length; i++) {
let video = videos[i];
if (videos[i].id === Cvideo) {
document.getElementById("nameV").innerHTML = videos[i].name;
player.src({ type: "video/mp4", src: videos[i].src });
player.play();
if (!video["videoP" + (i + 1)]) {
player.controlBar.progressControl.hide();
player.on("timeupdate", function() {
var percentage = (player.currentTime() / player.duration()) * 100;
document.getElementById("percentage").innerHTML =
Math.round(percentage) + "%";
if (percentage === 100) {
video["videoP" + (i + 1)] = 1;
var videopro = video["videoP" + (i + 1)] = 1;
$.ajax({
type: "POST",
url: "/update-video-progress/",
data: {
video_id: video.id,
videoPro: videopro,
},
success: function(response) {
console.log("Video progress updated");
},
error: function(xhr, textStatus, errorThrown) {
console.error("Failed to update video progress");
},
});
return;
}
});
} else {
player.controlBar.progressControl.show();
}
break;
}
}
}
<video id="videoP" class=" video-js vjs-fluid" controls data-setup='{}'>
<source src="../static/frontend/video/selectV.mp4" type="video/mp4">
</video>
<p id="percentage"class="hide_percent" >0</p>
1
2
17
this my views.py in my Django project to get the value and save to database and urls.py is path("save-data/", views.save_data, name="save-data"),
#csrf_exempt
def update_video_progress(request):
if request.method == "POST":
video_id = request.POST.get("video_id")
videoPro = request.POST.get("videoPro")
videoDB = VideoDB.objects.get(videoPro)
videoDB = videoPro
videoDB.save()
return JsonResponse({"message": "Video progress updated"})
def getDB(request):
video_db = VideoDB.objects.get(pk=5)
return render(request, 'User-page.html', {'video_db': video_db})
from django.db import models
class User(models.Model):
u_id = models.AutoField(primary_key=True)
name = models.CharField(max_length=100)
correctAnswers = models.IntegerField()
percentage = models.IntegerField(default=0)
def __str__(self):
return self.name
class VideoDB(models.Model):
u_id = models.ForeignKey(User, on_delete=models.CASCADE, related_name='videodb')
videoP1 = models.IntegerField(default=0)
videoP2 = models.IntegerField(default=0)
videoP17 = models.IntegerField(default=0)
def __str__(self):
return str(self.u_id)
and this my models.py for create database

Flask + Heroku: H12 Request Timeout Error

I have a Heroku app to run Scrapy Spider. After starting, I get error H12. How to fix it?
JQuery:
$.post('/wellness', {'specialty': specialty, 'state': state, 'city': city}, (res) => {
$(location).attr('href', 'http://127.0.0.1:5000/wellness')
});
flask:
if request.method == 'POST':
specialty = request.form.getlist('specialty[]')
state = request.form.getlist('state[]')
city = request.form.getlist('city[]')
settings = ''
with open(file_json, 'r') as f:
for line in f.read():
settings += line
settings = json.loads(settings)
settings['specialty'] = specialty
settings['state'] = state
settings['city'] = city
with open(file_json, 'w') as f:
f.write(json.dumps(settings, indent=4))
process = subprocess.Popen('python spiders/' + file_py, shell=True)
process.wait()
return render_template(file_html)

Flask-Socket, key error when selecting rooms

Please forgive me if i posted it in bad way, but i dont have any idea where is the mistake.
Im doing a small chat with five rooms using Flask-Socket and SocketIO. I set rooms like this:
ROOMS = ["waiting room", "food", "news", "games", "coding"]
Then i put them to html:
#app.route("/chat", methods=['GET', 'POST'])
#login_required
def chat():
return render_template('chat.html', username=current_user.username, rooms=ROOMS)
And on template:
{%for room in rooms%}
<p class="select-room"> {{ room }}</p>
{% endfor %}
The problem is when i try to send message only to room where i am by:
#socketio.on('message')
def message(data):
time_stamp = time.strftime('%b-%d %I:%M%p', time.localtime())
send({'msg': data['msg'], 'username': data['username'], 'time_stamp':time_stamp}, room=data['room'])
and from client:
document.querySelector('#send-message').onclick = () =>{
socket.send({'msg': document.querySelector('#user_message').value,
'username': username, 'room': room});
}
It makes me key error:
send({'msg': data['msg'], 'username': data['username'], 'time_stamp':time_stamp}, room=data['room'])
KeyError: 'room'
it also happens when i trying to switch rooms(leave one and connect other using this):
function leaveRoom(room) {
socket.emit('leave', {'username': username, 'room': room});
document.querySelectorAll('.select-room').forEach(p => {
p.style.color = "black";
});
}
function joinRoom(room) {
socket.emit('join', {'username' : username, 'room' : room});
// Clear message area
document.querySelector('#display-message-section').innerHTML = '';
};
For room select i use:
document.querySelectorAll('.select-room').forEach(p => {
p.onclick = () => {
let newRoom = p.innerHTML
// Check if user already in the room
if (newRoom == room) {
msg = `You are already in ${room} room.`;
printSysMsg(msg);
} else {
leaveRoom(room);
joinRoom(newRoom);
room = newRoom;
};
};
});
Where im making a mistake?
The full code is here:
https://pastebin.com/QXiBQG2u
https://pastebin.com/zfEtV4ZX
https://pastebin.com/wfkqNjf9

Ajax Call Returns HTML page as response instead of rendering page (Rails)

Hey having a issue with the rendering of a .erb file, in my AJAX call I make a call to my create action on rails where I validate and process the form data and sent back the completed order data as render: json which works fine.
I have a conditional that checks to see if parameter exists, it if does then the completed order data is passed back as a response via render: json
It if doesn't exists it will render a receipt page.
The problem is when I render the receipt page, the full HTML receipt page comes back as a response instead of rendering the page. Please Help!
$scope.placeOrder = function() {
var body = composeOrderBody();
var isValid = validateForm(body.order);
if(isValid) {
var orderComplete = '<%= #orderComplete %>';
var baseUrl = '<%= request.base_url %>';
console.log('Passing order object: ', body.order);
$http({
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
url: checkout_url,
data: {
order: body.order,
xhr_request: true
},
}).then((function(_this) {
return function(response) {
if(typeof response.data == 'undefined' || response.data == null || !response.data) {
console.log('Error: missing Order Number from Order Confirmation data.', response.data);
}
console.log('Order Confirmation response data object:' , response.data);
if(orderComplete) {
var redirectUrl = 'http://' + orderComplete
var order_params = `?oid=${response.data.oid}?cart=${response.data.cart}?total=${response.data.total}`
window.location.href = redirectUrl + order_params;
} else {
console.log('Base Url: ', baseUrl);
// window.location.href = `${baseUrl}/receipt`;
}
};
})(this));
} else {
console.log('Form Validation or Stripe Validation Failed');
}
} // end placeOrder
Rails Code
# Redirect to orderComplete URL if it's set
if !#orderComplete.blank?
puts 'orderComplete parameter is not blank'
# Sum up all the line item quantities
qty = #order.line_items.inject(0) {|sum, line_item| sum + line_item.quantity}
# Get all of the coupons (and values) into a string
coupons = #order.applied_coupons.map { |coupon| coupon.coupon }.join(',')
coupon_values = #order.applied_coupons.map { |coupon| '%.2f' % coupon.applied_value.to_f }.join(',')
order_params = {
"oid" => URI::escape(#order.number),
"cart" => URI::escape(#cart),
"total" => URI::escape('%.2f' % #order.total),
}
#redirectUrl = URI.parse(URI.escape(#orderComplete))
#redirectUrl.query = [#redirectUrl.query, order_params.to_query].compact.join('&')
#redirectUrl = #redirectUrl.to_s
if params[:xhr_request]
render json: order_params.to_json
return
end
render 'receipt_redirect', :layout => 'receipt_redirect'
else
puts 'OrderComplete Parameter is blank'
render 'receipt', :layout => 'receipt', :campaign => #campaign
end

Edit in Laravel + AngularJS

I'm building a complete crud using laravel + angularjs, but I have problems in the "edit" part.
It's an internal server error, so I don't know what it means and I need help.
Error "GET localhost/crudtcc/public/api/v1/colaboradores/editar/3 500 (Internal Server Error)"
the javascript file:
app.controller('colaboradoresController', function($scope, $http, API_URL) {
$http.get(API_URL + "colaboradores")
.success(function(response) {
$scope.colaboradores = response;
});
$scope.toggle = function(modalstate, id_colaborador) {
$scope.modalstate = modalstate;
switch (modalstate) {
case 'add':
$scope.form_title = "Novo colaborador";
$scope.colaborador = null;
break;
case 'edit':
$scope.form_title = "Dados do colaborador";
$scope.id_colaborador = id_colaborador;
$http.get(API_URL + 'colaboradores/editar/' + id_colaborador)
.success(function(response) {
console.log(response);
$scope.colaborador = response;
});
break;
default:
break;
}
$('#myModal').modal('show');
}
$scope.save = function(modalstate, id_colaborador) {
var url = API_URL + "colaboradores/salvar";
if (modalstate === 'edit') {
url += "/editar/" + id_colaborador;
}
$http({
method: 'POST',
url: url,
data: $.param($scope.colaborador),
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
}).success(function(response) {
console.log(response);
location.reload();
}).error(function(response) {
console.log(response);
alert('Um erro ocorreu. Check a log para mais detalhes.');
});
}
$scope.confirmDelete = function(id_colaborador) {
var isConfirmDelete = confirm('Tem certeza que deseja excluir o registro?');
if (isConfirmDelete) {
$http({
method: 'DELETE',
url: API_URL + 'colaboradores/remover/' + id_colaborador
}).
success(function(data) {
console.log(data);
location.reload();
}).
error(function(data) {
console.log(data);
alert('Falha na exclusão');
});
} else {
return false;
}
}
});
the routes file:
<?php
namespace App\Http\Controllers;
$colaborador = new Colaborador;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Usuario;
use App\Http\Controllers\Controler;
use App\Colaborador;
class Colaboradores extends Controller
{
public function index()
{
return Colaborador::orderBy('id_colaborador', 'asc')->get();
}
public function salvar(Request $request)
{
$colaborador->nome = $request->input('nome');
$colaborador->rg = $request->input('rg');
$colaborador->orgao_expedidor = $request->input('orgao_expedidor');
$colaborador->cpf = $request->input('cpf');
$colaborador->estado_civil = $request->input('estado_civil');
$colaborador->sexo = $request->input('sexo');
$colaborador->nome_pai = $request->input('nome_pai');
$colaborador->nome_mae = $request->input('nome_mae');
$colaborador->naturalidade = $request->input('naturalidade');
$colaborador->data_nascimento = $request->input('data_nascimento');
$colaborador->login = $request->input('login');
$colaborador->senha = $request->input('senha');
$colaborador->siape = $request->input('siape');
$colaborador->pis = $request->input('pis');
$colaborador->rua = $request->input('rua');
$colaborador->numero = $request->input('numero');
$colaborador->bairro = $request->input('bairro');
$colaborador->cidade = $request->input('cidade');
$colaborador->estado = $request->input('estado');
$colaborador->cep = $request->input('cep');
$colaborador->telefone_fixo = $request->input('telefone_fixo');
$colaborador->telefone_celular= $request->input('telefone_celular');
$colaborador->telefone_comercial = $request->input('telefone_comercial');
$colaborador->email = $request->input('email');
$colaborador->save();
return 'Colaborador salvo com sucesso! ID: ' . $colaborador->id_colaborador;
}
public function update(Request $request,$id_colaborador)
{
$colaborador = Colaborador::find($id_colaborador);
$colaborador->nome = $request->input('nome');
$colaborador->rg = $request->input('rg');
$colaborador->orgao_expedidor = $request->input('orgao_expedidor');
$colaborador->cpf = $request->input('cpf');
$colaborador->estado_civil = $request->input('estado_civil');
$colaborador->sexo = $request->input('sexo');
$colaborador->nome_pai = $request->input('nome_pai');
$colaborador->nome_mae = $request->input('nome_mae');
$colaborador->naturalidade = $request->input('naturalidade');
$colaborador->data_nascimento = $request->input('data_nascimento');
$colaborador->login = $request->input('login');
$colaborador->senha = $request->input('senha');
$colaborador->siape = $request->input('siape');
$colaborador->pis = $request->input('pis');
$colaborador->rua = $request->input('rua');
$colaborador->numero = $request->input('numero');
$colaborador->bairro = $request->input('bairro');
$colaborador->cidade = $request->input('cidade');
$colaborador->estado = $request->input('estado');
$colaborador->cep = $request->input('cep');
$colaborador->telefone_fixo = $request->input('telefone_fixo');
$colaborador->telefone_celular= $request->input('telefone_celular');
$colaborador->telefone_comercial = $request->input('telefone_comercial');
$colaborador->email = $request->input('email');
$colaborador->save();
return "Sucesso atualizando Colaborador #" . $colaborador->id_colaborador;
}
public function remove(Request $request, $id_colaborador)
{
$colaborador = Colaborador::where("id_colaborador", $id_colaborador);
$colaborador->delete();
return "Colaborador #". $request->input('id_colaborador'). " excluido com sucesso!";
}
public function editar($id_colaborador)
{
return Colaborador::where("id_colaborador", $id_colaborador);
}
}
?>
and the routes file...
<?php
/*
|--------------------------------------------------------------------------
| Application Routes
|--------------------------------------------------------------------------
|
| Here is where you can register all of the routes for an application.
| It's a breeze. Simply tell Laravel the URIs it should respond to
| and give it the controller to call when that URI is requested.
|
*/
Route::get("/colaboradores/gercolaboradores",
function() {
return view("/colaboradores/gerenciarcolaboradores");
});
Route::get("/api/v1/colaboradores/","Colaboradores#index");
Route::get("/api/v1/colaboradores/editar/{id_colaborador}","Colaboradores#editar");
Route::post('/api/v1/colaboradores/salvar/editar/{id_colaborador}',
'Colaboradores#update');
Route::post('/api/v1/colaboradores/salvar', 'Colaboradores#salvar');
Route::delete('/api/v1/colaboradores/remover/{id_colaborador}', 'Colaboradores#remove');
?>
You should write your request on Angular side as:
$http.post(API_URL + 'colaboradores/editar/' + id_colaborador, {YOUR_DATA})
.success(function(response) {
console.log(response);
$scope.colaborador = response;
});
and pass the parameters you want to send to backend.
Please refer to: https://docs.angularjs.org/api/ng/service/$http.
Explanation:
you're using angular GET
$http.get(API_URL + 'colaboradores/editar/' + id_colaborador)
and you defined your route in Laravel as POST
Route::post('/api/v1/colaboradores/salvar/editar/{id_colaborador}',
'Colaboradores#update');
GET is not passing any data except trough url, and you're trying to get that data as if you've sent it trough POST request.
You can find a short explanation on GET and POST requests on the following links: http://www.w3schools.com/tags/ref_httpmethods.asp and What is the difference between POST and GET?

Categories

Resources