I'm trying to update the content of a database item using fetch. However, I get 403 Forbidden error in the console. I'm not using a form in my HTML template, just appending the elements to a div. The log says CSRF token missing.
document.addEventListener("DOMContentLoaded", function(){
const button = document.querySelectorAll("#edit_profile")
button.forEach(function(button){
button.onclick = function(){
const memberID = button.dataset.id;
const usernameID = button.dataset.username;
const username = document.getElementById(`username_${memberID}`);
let edit_username = document.createElement("textarea");
edit_username.setAttribute("rows", "1");
edit_username.innerHTML = username.innerHTML
edit_username.id = `edit_username_${memberID}`;
edit_username.className = `form-control username ${usernameID}`;
const saveButton = document.createElement("button");
saveButton.innerHTML = "Save";
saveButton.id = `saveButton_${memberID}`;
saveButton.className = "btn btn-success col-3";
saveButton.style.margin = "10px";
document.getElementById(`edit_${memberID}`).append(edit_username);
document.getElementById(`edit_${memberID}`).append(saveButton);
saveButton.addEventListener("click", function(){
edit_username = document.getElementById(`edit_username_${memberID}`);
fetch(`/edit_profile/${memberID}`,{
method: "POST",
body: JSON.stringify({
username: edit_username.value,
})
})
.then(response => response.json())
.then(result => {
console.log(result);
if(result[`error`]){
reset(memberID)
}
else {
username.innerHTML = result.username;
reset(memberID)
}
})
.catch(error => {
console.error(error);
})
})
}
});
I added the following decorator in views.py and it solved the problem:
from django.views.decorators.csrf import csrf_exempt
#csrf_exempt
def edit_profile(request, member_id):
if request.method != "POST":
return JsonResponse({"error": "POST request required."}, status=400)
team_members = Team.objects.get(id = member_id)
body_unicode = request.body.decode('utf-8')
body = json.loads(body_unicode)
username = body['username']
skills = body['skills']
bio = body['bio']
Team.objects.filter(id=member_id).update(username=f'{username}',skills=f'{skills}',bio=f'{bio}')
return JsonResponse({"message": "Successful", "username": username, "skills": skills, "bio": bio}, status=200)
Related
To explain what I mean in the title, let me show you the output.
This is the like button counter when the user did not click on the like button:
This is the like button counter when the user clicked on the like button:
This is the like button counter when the user clicked on the like button again to remove their like:
The program I wrote seems to be kind of messed up. Here it is:
This is the route info for this particular page:
#app.route('/postlikes/<string:post_name>', methods=["GET","POST"])
def postlikes(post_name):
if request.method == "POST":
JSONdata = request.json
posts = Image.query.filter_by(post_name=post_name)
if JSONdata['is_liked'] == True:
for post in posts:
post.likes += 1
db.session.commit()
elif JSONdata['removed_like'] == True:
for post in posts:
post.likes = post.likes
db.session.commit()
else:
post = Image.query.filter_by(post_name=post_name).first()
return {"post_likes":post.likes}
#app.route('/hasliked/<string:post_name>', methods=['GET','POST'])
def hasliked(post_name):
post = Image.query.filter_by(post_name=post_name).first()
user = User.query.filter_by(username=current_user.username).first()
is_liked = posts_liked_by_users.query.filter_by(post_name=post_name).first()
if is_liked.post_name == post.post_name and is_liked.user_id == user.id:
return {"has_liked":True}
else:
return {"has_liked":False}
This is the JS involved in the program:
<script>
const likebtn = document.getElementById('likebtn');
const currentURL = window.location.href;
const likenum = document.getElementById('likenumber');
const postarray = currentURL.split("/");
const postName = postarray[4];
function setLikeBtnColor() {
likebtn.style.color = JSON.parse(localStorage.getItem('likebtn')) ? 'cornflowerblue':'black';
}
setLikeBtnColor();
async function current_color() {
const fetchData = await fetch('/hasliked/'+postName)
.then(response => response.json())
.then(function newdata(data) {
let strdata = JSON.stringify(data)
let JSONdata = JSON.parse(strdata)
return JSONdata
})
return fetchData
}
async function set_color() {
const jsondata = await current_color()
if (jsondata['has_liked'] === true) {
likebtn.style.color = 'cornflowerblue'
} else {
likebtn.style.color = 'black'
}
}
async function getLikeNumber() {
const fetchData = await fetch('/postlikes/'+postName)
.then(response => response.json())
.then(function getdata(data) {
let strdata = JSON.stringify(data)
let JSONdata = JSON.parse(strdata)
likenum.textContent = JSONdata.post_likes
return JSONdata.post_likes
})
return fetchData
}
async function displayLikes() {
let initialnum = await getLikeNumber()
likenum.innerHTML = initialnum
}
displayLikes()
async function myFunction() {
localStorage.setItem('likebtn', !JSON.parse(localStorage.getItem('likebtn')));
setLikeBtnColor();
if (likebtn.style.color === 'cornflowerblue') {
fetch('/postlikes/'+postName, {
method:"POST",
body: JSON.stringify({
removed_like: false,
liked_post:postName,
is_liked:true
}),
headers:{
"Content-type":"application/json; charset=UTF-8"
}
})
let currentLikeNum = await getLikeNumber();
likenum.innerHTML = currentLikeNum
} else {
fetch('/postlikes/'+postName, {
method:"POST",
body: JSON.stringify({
removed_like:true,
is_liked:false
}),
headers:{
"Content-type":"application/json; charset=UTF-8"
}
})
let currentLikeNum = await getLikeNumber();
likenum.innerHTML = currentLikeNum
}};
likebtn.addEventListener('click', myFunction);
</script>
This is the Image Table:
class Image(db.Model):
id = db.Column(db.Integer, primary_key=True)
title=db.Column(db.String(120), nullable=False)
date_posted = db.Column(db.DateTime, nullable=False, default=datetime.datetime.utcnow)
img_location = db.Column(db.String(600), nullable=False)
mimetype = db.Column(db.String(10))
post_name = db.Column(db.String(150),nullable=False, unique=False)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
manga_name = db.Column(db.String(100), unique=False, nullable=False)
likes = db.Column(db.Integer, nullable=False)
reports = db.Column(db.Integer, nullable=False)
number_of_comments = db.Column(db.Integer, nullable=False)
(Yes, I am very well aware of the fact that I should be using multiple tables but I have specifically intended to use one table, for now.)
The app was made using flask.
Please help me.
You add one like when the button that was clicked was a button with the color 'cornflowerblue'. It should add one when the button was black. Change it.
async function myFunction() {
.......
if (likebtn.style.color === 'cornflowerblue') {
........
}
........
}
to it
async function myFunction() {
.........
if (likebtn.style.color !== 'cornflowerblue') {
.........
}
........
}
So the first piece of code is the backend end point and second is the front end.
It does not send the token to an email address on the server or using Postman raw data.
But it does send a token using form-data. Any ideas I'm new to this. thanks
class RegisterView(View):
def post(self, request, *args, **kwargs):
data = request.POST.get('email')
check_if_email_exists = []
for email in Registration.objects.all().values_list('email', flat=True):
check_if_email_exists.append(email)
if data in check_if_email_exists:
return JsonResponse('Email already provided', safe=False, status=200)
else:
new_user = Registration.objects.create(email=data)
new_user.save()
content = {'code': new_user.code}
send_mail(
"Thanks for Registering",
f'Here is your signup Token:{content}',
'djangod192#gmail.com',
[data],
fail_silently=False,
)
return JsonResponse(content, status=201)
const SignUpStep1 = () => {
const navigate = useNavigate();
const [email,setEmail] = useState("");
const dispatch = useDispatch();
const url = "https://motion.propulsion-learn.ch/app/api/auth/registration/";
const updateEmail = (event) => {
setEmail(event.target.value);
}
const sendVerificationCode = (event) => {
event.preventDefault();
if (email.length > 0) {
const data = {
email: email
};
const fetchConfig = {
method: 'POST',
headers: new Headers({
"Content-Type": "application/json",
}),
body: JSON.stringify(data),
};
fetch(url,fetchConfig)
.then((response) => {
return response.json();
})
const action = {
type:"setEmail",
payload:email
};
dispatch(action)
navigate("/SignUpStep2")
}else{
alert("please enter email address");
}
}
I want to take the video data and convert it using cv2. Which part is the video data? It's a code that might be related.
I want to send video data from the client to the server using webrtc, and convert and send the converted video from server to cv2 from the client again.
app.js
from flask import Flask, render_template, request, redirect, url_for, session
from flask_socketio import SocketIO, emit, join_room, leave_room
# Next two lines are for the issue: https://github.com/miguelgrinberg/python-engineio/issues/142
import os
secretKey = os.urandom(24)
app = Flask(__name__)
app.config['SECRET_KEY'] = secretKey
print("secretKey is ",secretKey)
socketio = SocketIO(app)
_users_in_room = {} # stores room wise user list
_room_of_sid = {} # stores room joined by an used
_name_of_sid = {} # stores display name of users
#app.route("/",methods=["GET", "POST"]) #첫번째 로그인화면
def loginPage():
if request.method == "POST":
room_id = request.form['room_id']
return redirect(url_for('enter_room',room_id=room_id))
return render_template("home.html")
#app.route("/<string:room_id>/checkpoint/", methods=["GET", "POST"]) #두번째 화면
def entry_checkpoint(room_id):
if request.method == "POST":
display_name = request.form['display_name']
mute_video = request.form['mute_video']
session[room_id] = {"name": display_name, "mute_video":mute_video}
return redirect(url_for("enter_room", room_id=room_id))
return render_template("chatroom_checkpoint.html", room_id=room_id)
#app.route("/<string:room_id>/") #세번째 스트림화면
def enter_room(room_id):
if room_id not in session:
return redirect(url_for("entry_checkpoint", room_id=room_id))
return render_template("chatroom.html", room_id=room_id, display_name=session[room_id]["name"], mute_video=session[room_id]["mute_video"])
#socketio.on("connect")
def on_connect():
sid = request.sid
print("New socket connected ", sid)
#socketio.on("join-room")
def on_join_room(data):
sid = request.sid
room_id = data["room_id"]
display_name = session[room_id]["name"]
# register sid to the room
join_room(room_id)
_room_of_sid[sid] = room_id
_name_of_sid[sid] = display_name
# broadcast to others in the room
print("[{}] New member joined: {}<{}>".format(room_id, display_name, sid))
emit("user-connect", {"sid": sid, "name": display_name}, broadcast=True, include_self=False, room=room_id)
# add to user list maintained on server
if room_id not in _users_in_room:
_users_in_room[room_id] = [sid]
emit("user-list", {"my_id": sid}) # send own id only
else:
usrlist = {u_id:_name_of_sid[u_id] for u_id in _users_in_room[room_id]}
emit("user-list", {"list": usrlist, "my_id": sid}) # send list of existing users to the new member
_users_in_room[room_id].append(sid) # add new member to user list maintained on server
print("\nusers: ", _users_in_room, "\n")
#socketio.on("disconnect")
def on_disconnect():
sid = request.sid
room_id = _room_of_sid[sid]
display_name = _name_of_sid[sid]
print("[{}] Member left: {}<{}>".format(room_id, display_name, sid))
emit("user-disconnect", {"sid": sid}, broadcast=True, include_self=False, room=room_id)
_users_in_room[room_id].remove(sid)
if len(_users_in_room[room_id]) == 0:
_users_in_room.pop(room_id)
_room_of_sid.pop(sid)
_name_of_sid.pop(sid)
print("\nusers: ", _users_in_room, "\n")
#socketio.on("data")
def on_data(data):
sender_sid = data['sender_id']
target_sid = data['target_id']
if sender_sid != request.sid:
print("[Not supposed to happen!] request.sid and sender_id don't match!!!")
if data["type"] != "new-ice-candidate":
print('{} message from {} to {}'.format(data["type"], sender_sid, target_sid))
socketio.emit('data', data, room=target_sid)
if __name__ == "__main__":
socketio.run(app, host='0.0.0.0', port='5050', debug=True)
chatroom_networking.js
var myID;
var _peer_list = {};
// socketio
var protocol = window.location.protocol;
var socket = io(protocol + '//' + document.domain + ':' + location.port, {autoConnect: false});
document.addEventListener("DOMContentLoaded", (event)=>{
startCamera();
});
var camera_allowed=false;
var mediaConstraints = {
audio: true, // We want an audio track
video: true
}
function startCamera()
{
navigator.mediaDevices.getUserMedia(mediaConstraints)
.then((stream)=>{
myVideo.srcObject = stream;
camera_allowed = true;
//start the socketio connection
socket.connect();
})
.catch((e)=>{
console.log("getUserMedia Error! ", e);
alert("Error! Unable to access camera or mic! ");
});
}
socket.on("connect", ()=>{
console.log("socket connected....");
socket.emit("join-room", {"room_id": myRoomID});
});
socket.on("disconnect", (data)=>{
console.log("disconnect");
});
socket.on("user-connect", (data)=>{
console.log("user-connect ", data);
let peer_id = data["sid"];
let display_name = data["name"];
_peer_list[peer_id] = undefined; // add new user to user list
addVideoElement(peer_id, display_name);
});
socket.on("user-disconnect", (data)=>{
console.log("user-disconnect ", data);
let peer_id = data["sid"];
closeConnection(peer_id);
removeVideoElement(peer_id);
});
socket.on("user-list", (data)=>{
console.log("user list recvd ", data);
myID = data["my_id"];
if( "list" in data) // not the first to connect to room, existing user list recieved
{
let recvd_list = data["list"];
// add existing users to user list
for(peer_id in recvd_list)
{
display_name = recvd_list[peer_id];
_peer_list[peer_id] = undefined;
addVideoElement(peer_id, display_name);
}
start_webrtc();
}
});
function closeConnection(peer_id)
{
if(peer_id in _peer_list)
{
_peer_list[peer_id].onicecandidate = null;
_peer_list[peer_id].ontrack = null;
_peer_list[peer_id].onnegotiationneeded = null;
delete _peer_list[peer_id]; // remove user from user list
}
}
function log_user_list()
{
for(let key in _peer_list)
{
console.log(`${key}: ${_peer_list[key]}`);
}
}
//---------------[ webrtc ]--------------------
var PC_CONFIG = {
iceServers: [
{
urls: ['stun:stun.l.google.com:19302',
'stun:stun1.l.google.com:19302',
'stun:stun2.l.google.com:19302',
'stun:stun3.l.google.com:19302',
'stun:stun4.l.google.com:19302'
]
},
]
};
function log_error(e){console.log("[ERROR] ", e);}
function sendViaServer(data){socket.emit("data", data);}
socket.on("data", (msg)=>{
switch(msg["type"])
{
case "offer":
handleOfferMsg(msg);
break;
case "answer":
handleAnswerMsg(msg);
break;
case "new-ice-candidate":
handleNewICECandidateMsg(msg);
break;
}
});
function start_webrtc()
{
// send offer to all other members
for(let peer_id in _peer_list)
{
invite(peer_id);
}
}
function invite(peer_id)
{
if(_peer_list[peer_id]){console.log("[Not supposed to happen!] Attempting to start a connection that already exists!")}
else if(peer_id === myID){console.log("[Not supposed to happen!] Trying to connect to self!");}
else
{
console.log(`Creating peer connection for <${peer_id}> ...`);
createPeerConnection(peer_id);
let local_stream = myVideo.srcObject;
local_stream.getTracks().forEach((track)=>{_peer_list[peer_id].addTrack(track, local_stream);});
}
}
function createPeerConnection(peer_id)
{
_peer_list[peer_id] = new RTCPeerConnection(PC_CONFIG);
_peer_list[peer_id].onicecandidate = (event) => {handleICECandidateEvent(event, peer_id)};
_peer_list[peer_id].ontrack = (event) => {handleTrackEvent(event, peer_id)};
_peer_list[peer_id].onnegotiationneeded = () => {handleNegotiationNeededEvent(peer_id)};
}
function handleNegotiationNeededEvent(peer_id)
{
_peer_list[peer_id].createOffer()
.then((offer)=>{return _peer_list[peer_id].setLocalDescription(offer);})
.then(()=>{
console.log(`sending offer to <${peer_id}> ...`);
sendViaServer({
"sender_id": myID,
"target_id": peer_id,
"type": "offer",
"sdp": _peer_list[peer_id].localDescription
});
})
.catch(log_error);
}
function handleOfferMsg(msg)
{
peer_id = msg['sender_id'];
console.log(`offer recieved from <${peer_id}>`);
createPeerConnection(peer_id);
let desc = new RTCSessionDescription(msg['sdp']);
_peer_list[peer_id].setRemoteDescription(desc)
.then(()=>{
let local_stream = myVideo.srcObject;
local_stream.getTracks().forEach((track)=>{_peer_list[peer_id].addTrack(track, local_stream);});
})
.then(()=>{return _peer_list[peer_id].createAnswer();})
.then((answer)=>{return _peer_list[peer_id].setLocalDescription(answer);})
.then(()=>{
console.log(`sending answer to <${peer_id}> ...`);
sendViaServer({
"sender_id": myID,
"target_id": peer_id,
"type": "answer",
"sdp": _peer_list[peer_id].localDescription
});
})
.catch(log_error);
}
function handleAnswerMsg(msg)
{
peer_id = msg['sender_id'];
console.log(`answer recieved from <${peer_id}>`);
let desc = new RTCSessionDescription(msg['sdp']);
_peer_list[peer_id].setRemoteDescription(desc)
}
function handleICECandidateEvent(event, peer_id)
{
if(event.candidate){
sendViaServer({
"sender_id": myID,
"target_id": peer_id,
"type": "new-ice-candidate",
"candidate": event.candidate
});
}
}
function handleNewICECandidateMsg(msg)
{
console.log(`ICE candidate recieved from <${peer_id}>`);
var candidate = new RTCIceCandidate(msg.candidate);
_peer_list[msg["sender_id"]].addIceCandidate(candidate)
.catch(log_error);
}
function handleTrackEvent(event, peer_id)
{
console.log(`track event recieved from <${peer_id}>`);
if(event.streams)
{
getVideoObj(peer_id).srcObject = event.streams[0];
}
}
chatroom_ui.js
var myVideo;
document.addEventListener("DOMContentLoaded", (event)=>{
myVideo = document.getElementById("local_vid");
document.getElementById("room_link").innerHTML=`or the link: <span class="heading-mark">${window.location.href}</span>`;
});
function makeVideoElement(element_id, display_name)
{
let wrapper_div = document.createElement("div");
let vid_wrapper = document.createElement("div");
let vid = document.createElement("video");
let name_text = document.createElement("div");
wrapper_div.id = "div_"+element_id;
vid.id = "vid_"+element_id;
wrapper_div.className = "shadow video-item";
vid_wrapper.className = "vid-wrapper";
vid.autoplay = true;
vid_wrapper.appendChild(vid);
wrapper_div.appendChild(vid_wrapper);
console.log(wrapper_div)
return wrapper_div;
}
function addVideoElement(element_id)
{
document.getElementById("video_grid").appendChild(makeVideoElement(element_id));
}
function removeVideoElement(element_id)
{
let v = getVideoObj(element_id);
if(v.srcObject){
v.srcObject.getTracks().forEach(track => track.stop());
}
v.removeAttribute("srcObject");
v.removeAttribute("src");
document.getElementById("div_"+element_id).remove();
}
function getVideoObj(element_id)
{
return document.getElementById("vid_"+element_id);
}
I am working on the cs50 web development Network assignment. Essentially it is a barebones twitter copycat. I have an issue where a view from views.py is being called when I do not intend it to be called. I know below I am posting more than is needed of my code below, but I feel I need to since I don't know where the problem area is.
The views.py function follow_count() is being called eventually when I call the index view but cannot determine why. I.e. it is called every time the homepage is loaded. I do not want it to be called until it is specifically called by the clicked event listener in the js file. I cannot figure out what is causing follow_count() to run early, every time I load the index view. As I follow the path of different functions calling each other, it doesn't appear that anything is calling follow_count() yet it runs anyway.
views.py:
from django.contrib.auth import authenticate, login, logout
from django.db import IntegrityError
from django.http import HttpResponse, HttpResponseRedirect
from django.http.response import JsonResponse
from django.shortcuts import render
from django.urls import reverse
from .models import User, Post, Profile
def index(request):
print("index running in python")
if request.method == "POST":
post = request.POST["post-body"]
new_post = Post()
new_post.poster = request.user
new_post.body = post
new_post.save()
return render(request, "network/index.html")
def login_view(request):
if request.method == "POST":
# Attempt to sign user in
username = request.POST["username"]
password = request.POST["password"]
user = authenticate(request, username=username, password=password)
# Check if authentication successful
if user is not None:
login(request, user)
return HttpResponseRedirect(reverse("index"))
else:
return render(request, "network/login.html", {
"message": "Invalid username and/or password."
})
else:
return render(request, "network/login.html")
def logout_view(request):
logout(request)
return HttpResponseRedirect(reverse("index"))
def register(request):
if request.method == "POST":
username = request.POST["username"]
email = request.POST["email"]
# Ensure password matches confirmation
password = request.POST["password"]
confirmation = request.POST["confirmation"]
if password != confirmation:
return render(request, "network/register.html", {
"message": "Passwords must match."
})
# Attempt to create new user
try:
user = User.objects.create_user(username, email, password)
user.save()
except IntegrityError:
return render(request, "network/register.html", {
"message": "Username already taken."
})
login(request, user)
#auto-create a profile for new user
new_profile = Profile()
new_profile.user = user
new_profile.save()
return HttpResponseRedirect(reverse("index"))
else:
return render(request, "network/register.html")
def all_posts(request):
print("all_posts running in python")
posts = Post.objects.all()
posts = posts.order_by("-timestamp").all()
print(f"{posts}")
return JsonResponse([post.serialize() for post in posts], safe=False)
def follow_count(request, username_lookup):
print(f"follow_count running in python")
user = User.objects.get(username='dannl')
profiles = Profile.objects.get(user=user)
print(username_lookup)
try:
user = User.objects.get(username=username_lookup)
except User.DoesNotExist:
pass
try:
profiles = Profile.objects.get(user=user)
except Profile.DoesNotExist:
pass
return JsonResponse([profiles.serialize()], safe=False)
def follow(request, username_lookup):
print("follow runnning in python")
followed_user = User.objects.get(username=username_lookup)
print(f"followed_user is {followed_user.username}")
followed_profile = Profile.objects.get(user=followed_user)
following_user = request.user
print("step 3 done")
print(f"following_user is {following_user.username}")
following_profile = Profile.objects.get(user=following_user)
followed_profile.followers.add(following_user)
following_profile.following.add(followed_user)
return render(request, "network/index.html")
def unfollow(request, username_lookup):
print("unfollow runnning in python")
unfollowed_user = User.objects.get(username=username_lookup)
print(f"unfollowed_user is {unfollowed_user.username}")
unfollowed_profile = Profile.objects.get(user=unfollowed_user)
unfollowing_user = request.user
print("step 3 done")
print(f"unfollowing_user is {unfollowing_user.username}")
unfollowing_profile = Profile.objects.get(user=unfollowing_user)
unfollowed_profile.followers.remove(unfollowing_user)
unfollowing_profile.following.remove(unfollowed_user)
return render(request, "network/index.html")
def follow_button(request, username_lookup):
print("follow_button running in python")
current_logged_user = request.user
current_logged_profile = Profile.objects.get(user=current_logged_user)
print(f"current_logged_profile is {current_logged_profile.user.username}")
return JsonResponse([current_logged_profile.serialize()], safe=False)
urls.py:
from django.urls import path
from . import views
urlpatterns = [
path("", views.index, name="index"),
path("login", views.login_view, name="login"),
path("logout", views.logout_view, name="logout"),
path("register", views.register, name="register"),
path("all_posts", views.all_posts, name="all_posts"),
path("<str:username_lookup>", views.follow_count, name="follow_count"),
path("<str:username_lookup>/follow", views.follow, name="follow"),
path("<str:username_lookup>/unfollow", views.unfollow, name="unfollow"),
path("<str:username_lookup>/follow_button", views.follow_button, name="follow_button"),
path("profile_info", views.follow_button, name="profile_info")
]
index.html
{% extends "network/layout.html" %}
{% load static %}
{% block body %}
{% if user.is_authenticated %}
<div id="index-display">
<h3>All Posts</h3>
<br>
<div id="new-post">
<h5>New Post</h5>
<form action="{% url 'index' %}" method="post">
{% csrf_token %}
<textarea class="form-control" name="post-body" placeholder="Type post here"></textarea>
<input id="post-message" type="submit" class="btn btn-primary"/>
</form>
</div>
<div id="all-posts">
</div>
</div>
<div id="profile-display">
<h3 id="profile-name"></h3>
<br>
<b>Followers: </b><b id="followers"></b>
<b>Following: </b><b id="following"></b>
<div id="profile-posts">
</div>
</div>
<div id="following-display">
<h3>Following</h3>
<br>
<div id="following-posts">
</div>
</div>
{% else %}
<strong> Login To See Posts</strong>
{% endif %}
{% endblock %}
{% block script %}
<script src="{% static 'network/index.js' %}"></script>
{% endblock %}
index.js:
document.addEventListener('DOMContentLoaded', function() {
document.querySelector('#following-link').addEventListener('click', () => {
load_posts_following();
});
load_posts();
})
function load_posts() {
console.log("load_posts running");
document.querySelector('#index-display').style.display = 'block';
document.querySelector('#profile-display').style.display = 'none';
document.querySelector('#following-display').style.display = 'none';
fetch('/all_posts')
.then(response => response.json())
.then(posts => {
// Print posts
console.log(posts);
posts.forEach(post => show_posts(post));
});
}
function show_posts(post) {
console.log("show_posts running")
//create 'main' div (will add content to it below), and store it in a variable
const post_display = document.createElement('div');
post_display.id = 'post';
post_display.className = 'col-lg-10 col-md-20 col-sm-30 border';
console.log("step 1: div created")
//create new element for link to profiles, add it to the 'main' div
const post_poster = document.createElement('div');
post_poster.id = 'post-poster';
post_poster.innerHTML = post.poster;
post_poster.addEventListener('click', event => {
username_lookup = event.target.innerHTML;
load_posts_profile(username_lookup);
});
post_display.append(post_poster);
console.log("step 2 done")
//create new div to display post, add it to the 'main' div
const post_body = document.createElement('div');
post_body.id = 'post-body';
post_body.innerHTML = post.body;
post_display.append(post_body);
console.log("step 3 done")
//create new div to display timestamp, add it to the 'main' div
const post_timestamp = document.createElement('div');
post_timestamp.id = 'post-timestamp';
post_timestamp.innerHTML = post.timestamp;
post_display.append(post_timestamp);
console.log("step 4 done")
//create new div to display # of likes, add it to the 'main' div
const post_likes = document.createElement('div');
post_likes.id = 'post-likes';
post_likes.innerHTML = `Likes: ${post.likes}`;
post_display.append(post_likes);
console.log("step 5 done");
document.querySelector('#all-posts').append(post_display);
console.log("post appended");
}
function load_posts_following() {
console.log("load_posts_following running");
document.querySelector('#index-display').style.display = 'none';
document.querySelector('#profile-display').style.display = 'none';
document.querySelector('#following-display').style.display = 'block';
fetch('/profile_info')
.then(response => response.json())
.then(profiles_returned => {
console.log(profiles_returned);
profiles_returned.forEach(profile => {
fetch('/all_posts')
.then(response => response.json())
.then(posts => {
// Print posts
console.log(posts);
posts.forEach(post => show_posts_following(post, profile));
});
});
});
}
function show_posts_following(post, profile) {
console.log("show_posts_following running");
console.log(post.poster);
console.log(profile);
console.log(profile.following_usernames);
if (profile.following_usernames.includes(post.poster)) {
//create 'main' div (will add content to it below), and store it in a variable
const post_display = document.createElement('div');
post_display.id = 'post';
post_display.className = 'col-lg-10 col-md-20 col-sm-30 border';
//create new element for link to profiles, add it to the 'main' div
const post_poster = document.createElement('div');
post_poster.id = 'post-poster';
post_poster.innerHTML = post.poster;
post_display.append(post_poster);
//create new div to display post, add it to the 'main' div
const post_body = document.createElement('div');
post_body.id = 'post-body';
post_body.innerHTML = post.body;
post_display.append(post_body);
//create new div to display timestamp, add it to the 'main' div
const post_timestamp = document.createElement('div');
post_timestamp.id = 'post-timestamp';
post_timestamp.innerHTML = post.timestamp;
post_display.append(post_timestamp);
//create new div to display # of likes, add it to the 'main' div
const post_likes = document.createElement('div');
post_likes.id = 'post-likes';
post_likes.innerHTML = `Likes: ${post.likes}`;
post_display.append(post_likes);
document.querySelector('#following-posts').append(post_display);
}
}
function load_posts_profile(username_lookup) {
console.log("load_posts_profile running");
document.querySelector('#index-display').style.display = 'none';
document.querySelector('#profile-display').style.display = 'block';
document.querySelector('#following-display').style.display = 'none';
document.querySelector('#profile-name').innerHTML = username_lookup;
fetch(`/${username_lookup}`)
.then(response => response.json())
.then(profiles => {
console.log(profiles);
profiles.forEach(profile => show_follow_count(profile));
follow_button(username_lookup, profiles);
});
fetch('/all_posts')
.then(response => response.json())
.then(posts => {
// Print posts
console.log(posts);
posts.forEach(post => show_posts_profile(post, username_lookup));
});
}
function show_posts_profile(post, username_lookup) {
console.log("show_posts_profile running");
console.log(post.poster);
if (post.poster === username_lookup) {
//create 'main' div (will add content to it below), and store it in a variable
const post_display = document.createElement('div');
post_display.id = 'post';
post_display.className = 'col-lg-10 col-md-20 col-sm-30 border';
//create new element for link to profiles, add it to the 'main' div
const post_poster = document.createElement('div');
post_poster.id = 'post-poster';
post_poster.innerHTML = post.poster;
post_display.append(post_poster);
//create new div to display post, add it to the 'main' div
const post_body = document.createElement('div');
post_body.id = 'post-body';
post_body.innerHTML = post.body;
post_display.append(post_body);
//create new div to display timestamp, add it to the 'main' div
const post_timestamp = document.createElement('div');
post_timestamp.id = 'post-timestamp';
post_timestamp.innerHTML = post.timestamp;
post_display.append(post_timestamp);
//create new div to display # of likes, add it to the 'main' div
const post_likes = document.createElement('div');
post_likes.id = 'post-likes';
post_likes.innerHTML = `Likes: ${post.likes}`;
post_display.append(post_likes);
document.querySelector('#profile-posts').append(post_display);
}
}
function show_follow_count(profile) {
document.querySelector('#followers').innerHTML = `${profile.followers}`;
document.querySelector('#following').innerHTML = `${profile.following}`;
}
function follow(username_lookup) {
console.log("follow running")
fetch(`/${username_lookup}/follow`)
.then(response => null)
}
function unfollow(username_lookup) {
console.log("unfollow running")
fetch(`/${username_lookup}/unfollow`)
.then(response => null)
}
function update_followers() {
const before_followers = document.querySelector('#followers').innerHTML;
console.log(before_followers);
var after_followers = parseInt(before_followers) + 1;
after_followers = parseInt(after_followers);
console.log(after_followers);
document.querySelector('#followers').innerHTML = `${after_followers}`;
}
function update_followers_unfollow() {
const before_followers = document.querySelector('#followers').innerHTML;
console.log(before_followers);
var after_followers = parseInt(before_followers) - 1;
after_followers = parseInt(after_followers);
console.log(after_followers);
document.querySelector('#followers').innerHTML = `${after_followers}`;
}
function follow_button(username_lookup) {
console.log("follow_button running")
fetch(`/${username_lookup}/follow_button`)
.then(response => response.json())
.then(current_logged_profile => {
console.log(current_logged_profile);
current_logged_profile.forEach(profile => {
if (username_lookup === profile.username) {
console.log("own profile found - no follow button");
}
else if (profile.following_usernames.includes(username_lookup)) {
console.log("unfollow button");
const unfollow_button = document.createElement('button');
unfollow_button.innerHTML = "Unfollow";
unfollow_button.style.width = '50px';
unfollow_button.style.height = '25px';
profile_header = document.querySelector('#profile-name');
profile_header.append(unfollow_button);
unfollow_button.addEventListener('click', () => {
unfollow(username_lookup);
update_followers_unfollow();
})
}
else {
console.log("not already follower - follow button");
const follow_button = document.createElement('button');
follow_button.innerHTML = "Follow";
follow_button.style.width = '50px';
follow_button.style.height = '25px';
profile_header = document.querySelector('#profile-name');
profile_header.append(follow_button);
follow_button.addEventListener('click', () => {
follow(username_lookup);
update_followers();
});
}
});
});
}
You need to put profile_info before the <str:username>, otherwise that will be the first match, and thus fire the follow_countinstead of thefollow_button`:
urlpatterns = [
path('', views.index, name='index'),
path('login', views.login_view, name='login'),
path('logout', views.logout_view, name='logout'),
path('register', views.register, name='register'),
path('all_posts', views.all_posts, name='all_posts'),
# ↓ first profile_info before <str:username_lookup>
path('profile_info', views.follow_button, name='profile_info'),
path('<str:username_lookup>', views.follow_count, name='follow_count'),
path('<str:username_lookup>/follow', views.follow, name='follow'),
path('<str:username_lookup>/unfollow', views.unfollow, name='unfollow'),
path('<str:username_lookup>/follow_button', views.follow_button, name='follow_button'),
]
I have run into a 500 error that I cannot resolve while practicing with making a To Do app with various lists & to do items that all have full CRUD options.
To Do List code:
class TodoList (db.Model):
__tablename__ = 'todolists'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(), nullable=False)
todos = db.relationship('Todo', backref='list', lazy=True)
const todo_list_input = document.getElementById('todo_list_id');
document.getElementById('create_list_box_button').onsubmit = function(e) {
e.preventDefault();
const list_title = todo_list_input.value;
todo_list_input.value = '';
fetch('/todolists/create', {
method: 'POST',
body: JSON.stringify({
'todo_list_id': list_title,
}),
headers: {
'Contet-Type': 'application/json'
}
})
.then(response => response.json())
.then(jsonResponse => {
const li = document.createElement('li');
const checkbox = document.createElement('input');
checkbox.className = 'check-completed';
checkbox.type = 'checkbox';
checkbox.setAttribute('data-id', jsonResponse.id);
li.appendChild(checkbox);
const text = document.createTextNode(' ' + jsonResponse.description);
li.appendChild(text);
const deleteButton = document.createElement('button');
deleteButton.className = 'delete-button';
deleteButton.setAttribute('data-id', jsonResponse.id);
deleteButton.innerHTML = '✗';
li.appendChild(deleteButton);
document.getElementById('todo_lists_buttons').appendChild(li);
document.getElementById('error').className = 'hidden';
})
.catch(function() {
console.error('Error occurred');
document.getElementById('error').className = '';
})
}
#app.route('/todolists/create', methods=['POST'])
def create_todoList():
error = False
body = {}
try:
list_name = request.json()['list_name']
todoList = List(list_name=list_name)
db.session.add(todoList)
db.session.commit()
body['list_name'] = todoList.list_name
except:
error = True
db.session.rollback()
print(sys.exc_info())
finally:
db.session.close()
if not error:
return jsonify(body)
else:
abort(500)
I've tried changing variable names around throughout, no joy there, as well as a few other things to try to pinpoint the issue and am just out of ideas (still new at this) on what might be going on.
This only occurs when attempting to 'Create' a new To Do List. I can swap between lists and create/delete To Do Items no problem, it's just the Create List that isn't working.
To Do item code:
class Todo(db.Model):
__tablename__ = 'todos'
id = db.Column(db.Integer, primary_key=True)
description = db.Column(db.String(), nullable=False)
completed = db.Column(db.Boolean, default=False)
list_id = db.Column(db.Integer, db.ForeignKey('todolists.id'), nullable=False)
const todo_item_input = document.getElementById('description');
document.getElementById('create_todo_box_button').onsubmit = function(e) {
e.preventDefault();
const desc = todo_item_input.value;
todo_item_input.value = '';
fetch('/todos/create', {
method: 'POST',
body: JSON.stringify({
'description': desc,
'list_id': {{ active_list.id }}
}),
headers: {
'Content-Type': 'application/json'
}
})
.then(response => response.json())
.then(jsonResponse => {
const li = document.createElement('li');
const checkbox = document.createElement('input');
checkbox.className = 'check-completed';
checkbox.type = 'checkbox';
checkbox.setAttribute('data-id', jsonResponse.id);
li.appendChild(checkbox);
const text = document.createTextNode(' ' + jsonResponse.description);
li.appendChild(text);
const deleteButton = document.createElement('button');
deleteButton.className = 'delete-button';
deleteButton.setAttribute('data-id', jsonResponse.id);
deleteButton.innerHTML = '✗';
li.appendChild(deleteButton);
document.getElementById('todos').appendChild(li);
document.getElementById('error').className = 'hidden';
})
.catch(function() {
console.error('Error occured');
document.getElementById('error').className = '';
})
}
#app.route('/todos/create', methods=['POST'])
def create_todo():
error = False
body = {}
try:
description = request.get_json()['description']
list_id = request.get_json()['list_id']
todo = Todo(description=description)
active_list = TodoList.query.get(list_id)
todo.list = active_list
db.session.add(todo)
db.session.commit()
body['description'] = todo.description
except:
error = True
db.session.rollback()
print(sys.exc_info())
finally:
db.session.close()
if not error:
return jsonify(body)
else:
abort(500)
Web app view
Error
I would try to put a more verbose exception in your code. Also, I think you can have the error check inside your try...accept
#app.route('/todos/create', methods=['POST'])
def create_todo():
body = {}
try:
description = request.get_json()['description']
list_id = request.get_json()['list_id']
todo = Todo(description=description)
active_list = TodoList.query.get(list_id)
todo.list = active_list
db.session.add(todo)
db.session.commit()
body['description'] = todo.description
return jsonify(body)
except Exception as e:
print(e) # ------- tracing
db.session.rollback()
print(sys.exc_info())
finally:
db.session.close()
abort(500)