sessions with js

Hello again :slight_smile:

I have a problem, I have a video field and I want to save in the session if the user finished watching a video. I am planing on saving the video id (video is in my django db).

my code:

        {% if True %} <!-- if user has acsses to this video/course-->
            <div class="video_container">
                <div>
                    <h2>{{lecture.name}}</h2>
                </div>
                <div>
                    <div>
                        <video id="video" controls controlsList="nodownload" poster="">
                            <source type="video/mp4" src="{{lecture.video.url}}"></source>
                        </video>
                    </div>
                </div>
            
            </div>
        {% else %}
            <p>אין לך גישה לפה יא מניאק</p>
        {% endif %}
        
        

    </div>



<script>
    document.getElementById('video').addEventListener('ended', function(e) {
        sessionStorage.setItem("watched_videos", "SessionValue");
    });
</script>

and in a diffrent view i have this statment

                        {% if str(lecture.id) in request.session.watched_videos %} <!--if user watched the video-->
                            <i class="fas fa-play-circle"></i>                
                        {% else %}
                            <i class="far fa-play-circle"></i>
                        {% endif %}

                        <i class="{{lecture.L_type.icon}}"></i>
                        <h2 class="lecture_name">{{lecture.name}}</h2>

my problems are -

a) watched_videos needs to be a list containing a lot the videos ids, not just one, for example [1,2,3,4,5…] and I want to insert into it not update it.

b) I don’t know if its possible but I want to keep the session information about watched_videos for 4 months but the user login for 2 weeks. is it possible?

another question:
my db is structure like so:
User → purchses → bundles → items
user - purchses is one to many. purchses - bundles is many to many and bundles - items is many to many
I want to get all the Items the user bough,
is there a better way than this

# get all bundles a user bought
a=[x.bundles.all()  for x in user.purchses .all()]
b = []
#combine all the bundles to one list of bundles
for bundles in a:
	for bundle in bundles
		b.append bundle
#get the items from the bundles
items = []
for bundle in b:
	for item in bundle.items.all()
		items.append(item)

return item

.

Note: The ended event does not mean that the person watched the video. You have no way to know if they watched the video or just advanced the video to the end.

This generally implies a table related to your user table, where each row is a video id. (Possibly a many-to-many relationship between videos and users through a “watched video” model.)

There’s nothing within Django to automatically delete data after some period of time, but this can be done by identifying when you need to check this, and delete the old data at that time.

You can cross multiple relationships using the __ notation.

my_items = Items.objects.filter(bundles__purchases__user=some_user)

“This generally implies a table related to your user table, where each row is a video id. (Possibly a many-to-many relationship between videos and users through a “watched video” model.)”

isn’t it smarter to save the information locally on the session?

thanks for the help!

Sessions aren’t permanent. They’re disposed of when they expire.

Session storage should be reserved for short-term, per-session data.

(It’s also not “local”.)

He could use localstorage…

sorry for not responding, thanks for the suggestion I’ll look into both of the options.

hey, im trying to save if a user finshed watching a video on my website, I wrote the following code and I dont understand why it doesnt work.
my idea is, on the page run a js lister, when the end of the video is triggered send a form to a url which updates db.
in the db the user class has a"watched videos" var in a many to many relasionship with lecture (each lecture contains a video).

my code:

the html -

  {% if True %} <!-- if user has acsses to this video/course-->
            <div class="video_container">
                <div>
                    <h2>{{lecture.name}}</h2>
                </div>
                <div>
                    <div>
                        <video id="video" controls controlsList="nodownload" poster="">
                            <source type="video/mp4" src="{{lecture.video.url}}"></source>
                        </video>
                    </div>
                </div>
            
            </div>
        {% else %}
            <p>אין לך גישה לפה יא מניאק</p>
        {% endif %}
    </div>


     <form id="post-form"> 
        {% csrf_token %}
        <input type="hidden" name="user_id" id="user_id" value="{{user.id}}"/>
    </form>


<script>
    document.getElementById('video').addEventListener('ended', function(e) {
    $(document).on('submit','#post-form',function(e){
    e.preventDefault();
    
    $.ajax({
      type:'POST',
      url:'/courses/{{the_course.id}}/lecture/{{lecture.id}}/done_watching',
      data:{
          user_id:$  {{request.user.id}}

        csrfmiddlewaretoken:$('input[name=csrfmiddlewaretoken]').val(),
      },
      success: function(data){

      }
    });
    document.getElementById('message').value = ''
  });


    });
</script>

url -

    path("courses/<int:course_id>/lecture/<int:lecture_id>/done_watching",
          views.fully_watched_lecture, name="fully_watched_lecture"),

the views


def fully_watched_lecture(request,lecture_id):
    user_id = request.POST['user_id']
    user=NewUser.objects.get(id=user_id)
    user.wafully_watched_lectures.add(lecture.objects.get(id=lecture_id))

after trying to debug it seems like the browser dosent understand that the video has finshed. Do you have any idea how to fix his? thanks

The request.POST is used for HTML form-formatted data. You are not posting an HTML form, you’re posting a JSON object.

See Request and response objects | Django documentation | Django for how to retrieve and process non-form data.

What information are you seeing that is giving you this idea? Are you not seeing the POST being issued to the server?

i added this line of code

<script>
    document.getElementById('video').addEventListener('ended', function(e) {
consoel.log("made it here") ---- thats what i added
    $(document).on('submit','#post-form',function(e){
    e.preventDefault();
    
    $.ajax({
      type:'POST',
      url:'/courses/{{the_course.id}}/lecture/{{lecture.id}}/done_watching',
      data:{
          user_id:$  {{request.user.id}}

        csrfmiddlewaretoken:$('input[name=csrfmiddlewaretoken]').val(),
      },
      success: function(data){

      }
    });
    document.getElementById('message').value = ''
  });


    });

and after looking at the cosoel it dosent even get there when the video is finshed

Is your console log showing any errors before that?

Just a 404 about an unloaded image. Nothing relevent. (Sorry for the late respond)
managed to fix this, now getting this error

image
image

Quite frankly, it doesn’t make sense to me to embed the registration of an event listener in an event listener.

First thing I’d try would be to verify that the event listener works as expected and not try to do anything else with it.

<script>
document.getElementById('video').addEventListener('ended', function(e) {
  console.log("made it here");
});
</script>

to see if it triggers.

ive dont it and it seems to work, how would you suggest to send a post request to update the db ?

Issue the AJAX request.

You don’t need to associate it with an event, because you’ve already received the event.

(Note, it looks like you’re trying to do the AJAX using jQuery. I’m guessing that from the $.ajax(... call. Is jQuery loaded?)

hey,
after doing some research I’ve made a url

     path("courses/done_watching",
          views.fully_watched_lecture, name="fully_watched_lecture"),

and added this js code:

<script type='text/javascript'>
    document.getElementById('video').addEventListener('ended',myHandler,false);
    function myHandler(e) {
        $.ajax({
        type: "POST",

        url: "{% url 'fully_watched_lecture'%}",
        data: {
            csrfmiddlewaretoken:
            course_id = {{the_course.id}},
            lecture_id = {{lecture.id}},
            user_id = {{user.id}}


        },
        success: function() {
            alert('success');
        }
        });    


    }
</script>

when I ran it i got a 403 error, which is probably caused due to not having a csrf token, I tried some suggested stuff on stackoverflow but most of the suggestions are for form submissions, how can I add csrf token without a form?

See the docs on CSRF Forgery protection for information on how to get / use the csrf token in an AJAX call.

thanks it finally works!

hey, I have another question.

every course have many sections, and every section has many lectures. I made a many to many relation ship.

when I present the data, I qurry the data, for example course.sections.all() and get back all the sections in a specific course.
when I present them I just make a for, the problem is the order of the sections, some needs to be before others.
my question:
what is the order that the items from back from the db? the order they were added to the many to many relation or ordered by id?
if the second one is the correct, is there any way to order them like I want? (not by adding a number to the section because the same section might be the first section in one course and the last one in another). thanks !

Neither.

SQL query result sets are by definition, unordered. If you want the data returned in some specific order, you need to use an order_by clause to specify the sequence. It is wrong to rely upon the database to return data in order.