1

im very new to Javascript, Django & web development in general. Im following a cs50 web dev course by harvard and I have to design a front-end for an email client that makes API calls to send and receive emails.

Ill get mail, send mail, and update emails by using an API that is written specifically for us.

I need to send a GET request to /emails/ where is either inbox, sent, or archive, and it will return back (in JSON form) a list of all emails in that mailbox, in reverse chronological order.

How to fetch, as instructed by the course:

fetch('/emails/sent')
.then(response => response.json())
.then(emails => {
    // Print emails
    console.log(emails);

    // ... do something else with emails ...
});

I put this exact code in my .js file and it gives me these two errors:

        GET http://127.0.0.1:8000/emails/sent 500 (Internal Server Error)
        load_mailbox @ inbox.js:85
        (anonymous) @ inbox.js:24
        
        127.0.0.1/:1 Uncaught (in promise) SyntaxError: Unexpected token < in
JSON at position 0
Promise.then (async)        
    load_mailbox    @   inbox.js:87
    (anonymous) @   inbox.js:6

What shows at the cmd: Is the issue at the timestamp of the model in django? I dont understand why.

Internal Server Error: /emails/sent
Traceback (most recent call last):
  File "C:\Python\Python38\lib\site-packages\django\core\handlers\exception.py", line 34, in inner
    response = get_response(request)
  File "C:\Python\Python38\lib\site-packages\django\core\handlers\base.py", line 115, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "C:\Python\Python38\lib\site-packages\django\core\handlers\base.py", line 113, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "C:\Python\Python38\lib\site-packages\django\contrib\auth\decorators.py", line 21, in _wrapped_view
    return view_func(request, *args, **kwargs)
  File "C:\Users\AG\Desktop\cs50\mail\mail\views.py", line 96, in mailbox
    return JsonResponse([email.serialize() for email in emails], safe=False)
  File "C:\Users\AG\Desktop\cs50\mail\mail\views.py", line 96, in <listcomp>
    return JsonResponse([email.serialize() for email in emails], safe=False)
  File "C:\Users\AG\Desktop\cs50\mail\mail\models.py", line 26, in serialize
    "timestamp": self.timestamp.strftime("%b %-d %Y, %-I:%M %p"),
ValueError: Invalid format string

Code given by the course:

models.py:

from django.contrib.auth.models import AbstractUser
from django.db import models


class User(AbstractUser):
    pass


class Email(models.Model):
    user = models.ForeignKey("User", on_delete=models.CASCADE, related_name="emails")
    sender = models.ForeignKey("User", on_delete=models.PROTECT, related_name="emails_sent")
    recipients = models.ManyToManyField("User", related_name="emails_received")
    subject = models.CharField(max_length=255)
    body = models.TextField(blank=True)
    timestamp = models.DateTimeField(auto_now_add=True)
    read = models.BooleanField(default=False)
    archived = models.BooleanField(default=False)

    def serialize(self):
        return {
            "id": self.id,
            "sender": self.sender.email,
            "recipients": [user.email for user in self.recipients.all()],
            "subject": self.subject,
            "body": self.body,
            "timestamp": self.timestamp.strftime("%b %-d %Y, %-I:%M %p"),
            "read": self.read,
            "archived": self.archived
        }

views.py, this function i believe it returns the emails from my request:

@login_required
def mailbox(request, mailbox):

    # Filter emails returned based on mailbox
    if mailbox == "inbox":
        emails = Email.objects.filter(
            user=request.user, recipients=request.user, archived=False
        )
    elif mailbox == "sent":
        emails = Email.objects.filter(
            user=request.user, sender=request.user
        )
    elif mailbox == "archive":
        emails = Email.objects.filter(
            user=request.user, recipients=request.user, archived=True
        )
    else:
        return JsonResponse({"error": "Invalid mailbox."}, status=400)

    # Return emails in reverse chronologial order
    emails = emails.order_by("-timestamp").all()
    return JsonResponse([email.serialize() for email in emails], 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"),

    # API Routes
    path("emails", views.compose, name="compose"),
    path("emails/<int:email_id>", views.email, name="email"),
    path("emails/<str:mailbox>", views.mailbox, name="mailbox"),
]

My.js code where i use fetch:

document.addEventListener('DOMContentLoaded', function () {

    // Use buttons to toggle between views
    document.querySelector('#inbox').addEventListener('click', () => load_mailbox('inbox'));
    document.querySelector('#sent').addEventListener('click', () => load_mailbox('sent'));
    document.querySelector('#archived').addEventListener('click', () => load_mailbox('archive'));
    document.querySelector('#compose').addEventListener('click', compose_email);
    
    //code..
  
  });
  
  
  function compose_email() {
  //code..
  }
  
  function load_mailbox(mailbox) {
  
    // Show the mailbox and hide other views
    document.querySelector('#emails-view').style.display = 'block';
    document.querySelector('#compose-view').style.display = 'none';
  
    // Show the mailbox name
    document.querySelector('#emails-view').innerHTML = `<h3>${mailbox.charAt(0).toUpperCase() + mailbox.slice(1)}</h3>`;

    //problem:
//i will change the 'sent' string in the future

    fetch('/emails/sent')
    .then(response => response.json())
    .then(emails => {
      console.log(emails);
  });
  }
3
  • 2
    What exactly did you try to achieve with %-d and %-I? Commented Jul 26, 2020 at 19:42
  • @DeepSpace like i said, its not my code. I downloaded it from the course's website & im told i dont need to touch it. I only have to deal with js & html. The course is taught by harvard. Im currently trying your solution, will report back Commented Jul 26, 2020 at 19:46
  • 1
    Turns out -d and -I were a thing in Python 2. See my answer for details Commented Jul 26, 2020 at 20:05

1 Answer 1

4

self.timestamp.strftime("%b %-d %Y, %-I:%M %p")

You are using Python 3, but the code you were given was written for Python 2 (or by someone who didn't know all the difference with Python 3 so you might expect other hurdles down the road). They are used for non zero-padded versions of d and I.

In Python 3, -d and -I do not make sense to the parsing engine, and I don't think there are non zero-padded versions.

You can safely remove the -.

Sign up to request clarification or add additional context in comments.

3 Comments

i removed both of the '-' and the console prints the emails. Thanks! I dont know why they put them there, people at harvard wrote it so uhh. I only hope it wont cause errors in the future, their removal i mean
@Bryar Turns out -d and -I were valid identifiers in Python 2 (non zero-padded versions of d and I. Seeing that the codebase you are working with was probably written for Python 2 (or by someone who did know they were invalid in Python 3), expect other hurdles down the road
Thank you!!!! It took me 3 days to find this answer!!!! Bless you

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.