Problem Description:
I’m working on a Django project where I want to auto-play videos when they are at least 70% visible in the viewport and pause them when they fall below 70%. I’ve written the JavaScript using IntersectionObserver
, and the logic works well on its own. However, I’m facing some issues when integrating it into my Django template.
What I Have Tried:
I have a Video
model in Django where each video file is stored. In the template, I loop through the videos and apply the IntersectionObserver
logic for auto-play and pause. The videos load and display correctly, but the auto-play behavior isn’t consistent.
Here’s my setup:
models.py:
class Video(models.Model):
vidid=ShortUUIDField(length=10,max_length=100,prefix="video",alphabet="abcdefgh")
title = models.CharField(max_length=100)
description = models.TextField(blank=True)
video_file = models.FileField(upload_to='videos/')
uploaded_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
views.py:
def shorts_view(request,vidid):
shorts1 = Video.objects.filter(vidid=vidid)
shorts2 = Video.objects.all()
context = {
"shorts1":shorts1,
"shorts2":shorts2,
}
return render(request,"videoshareing/shorts.html")
shorts.html
{%load static%}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Lazy Load Shorts</title>
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css" rel="stylesheet">
<style>
/* Global Styles */
body, html {
margin: 0;
padding: 0;
background-color: #181818;
color: #fff;
font-family: Arial, sans-serif;
height: 100%;
overflow-y: scroll;
}
.shorts-container {
display: flex;
flex-direction: column;
}
.video-container {
position: relative;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
video {
width: 500px;
height: 100%;
object-fit: cover;
}
.follow-button {
position: absolute;
top: 10px;
left: 10px;
padding: 8px 12px;
background-color: #ff0000;
color: white;
border: none;
border-radius: 20px;
cursor: pointer;
font-size: 14px;
}
.actions {
position: absolute;
right: 10px;
top: 50%;
transform: translateY(-50%);
display: flex;
flex-direction: column;
align-items: center;
}
.action-button {
margin: 10px 0;
color: white;
text-align: center;
cursor: pointer;
padding: 10px;
background-color: rgba(0, 0, 0, 0.5);
border-radius: 50%;
width: 50px;
height: 50px;
opacity: 0.8;
}
.action-button span {
display: block;
font-size: 12px;
margin-top: 4px;
}
.fa-heart, .fa-thumbs-down, .fa-comment, .fa-share {
font-size: 20px;
}
</style>
</head>
<body>
<div class="shorts-container">
<!-- Video 1 -->
<div class="video-container">
{%for s in shorts2%}
<video class="video-player" src="{% static './assets/videos/video-1.mp4' %}" muted></video>
<button class="follow-button">Follow</button>
<div class="actions">
<div class="action-button like">
<span><i class="fa-regular fa-heart"></i></span>
<span>161K</span>
</div>
<div class="action-button dislike">
<span><i class="fa-regular fa-thumbs-down"></i></span>
<span>Dislike</span>
</div>
<div class="action-button comment">
<span><i class="fa-regular fa-comment"></i></span>
<span>378</span>
</div>
<div class="action-button share">
<span><i class="fa-solid fa-share"></i></span>
<span>Share</span>
</div>
</div>
{%endfor%}
</div>
<!-- Video 2 -->
<!-- <div class="video-container">
<video class="video-player" src="{% static './assets/videos/video-2.mp4' %}" muted></video>
<button class="follow-button">Follow</button>
<div class="actions">
<div class="action-button like">
<span><i class="fa-regular fa-heart"></i></span>
<span>200K</span>
</div>
<div class="action-button dislike">
<span><i class="fa-regular fa-thumbs-down"></i></span>
<span>Dislike</span>
</div>
<div class="action-button comment">
<span><i class="fa-regular fa-comment"></i></span>
<span>450</span>
</div>
<div class="action-button share">
<span><i class="fa-solid fa-share"></i></span>
<span>Share</span>
</div>
</div>
</div> -->
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const videos = document.querySelectorAll('.video-player');
// Create an intersection observer
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
const video = entry.target;
// If the video is in view
if (entry.isIntersecting) {
video.play(); // Play the video when it enters the viewport
} else {
video.pause(); // Pause the video when it leaves the viewport
}
});
}, {
threshold: 0.7 // Play the video when 70% is visible
});
// Observe each video element
videos.forEach(video => {
observer.observe(video);
});
});
</script>
</body>
</html>
The Problem:
Even though the videos load, the auto-play and pause functionality sometimes doesn’t work properly. It works fine when I test the plain HTML + JavaScript, but something seems off when I integrate it with Django.
What I Need Help With:
- Is my approach correct for integrating JavaScript with Django templates in this scenario?
- Are there any best practices I should follow when using
IntersectionObserver
with Django’s templating system? - Any suggestions on how I can debug or fix the issue would be greatly appreciated.