Skip to content

Commit

Permalink
Add django tutorial up to part 5
Browse files Browse the repository at this point in the history
  • Loading branch information
evinjaff committed May 27, 2024
1 parent 269a98e commit 0be5d23
Show file tree
Hide file tree
Showing 12 changed files with 225 additions and 8 deletions.
Binary file modified server/egglocke/db.sqlite3
Binary file not shown.
3 changes: 3 additions & 0 deletions server/egglocke/pokepoll/admin.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
from django.contrib import admin

# Register your models here.
from .models import Question

admin.site.register(Question)
8 changes: 6 additions & 2 deletions server/egglocke/pokepoll/models.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
from django.db import models

import datetime
# Create your models here.
from django.db import models
from django.utils import timezone


class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField("date published")

def was_published_recently(self):
now = timezone.now()
return now - datetime.timedelta(days=1) <= self.pub_date <= now


class Choice(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE)
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 7 additions & 0 deletions server/egglocke/pokepoll/static/pokepoll/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
li a {
color: green;
}

body {
background: white url("img/astarion.png") no-repeat;
}
21 changes: 21 additions & 0 deletions server/egglocke/pokepoll/templates/pokepoll/detail.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<h1>{{ question.question_text }}</h1>
<ul>
{% for choice in question.choice_set.all %}
<li>{{ choice.choice_text }}</li>
{% endfor %}
</ul>

<h2>Submissime owo</h2>

<form action="{% url 'pokepoll:vote' question.id %}" method="post">
{% csrf_token %}
<fieldset>
<legend><h1>{{ question.question_text }}</h1></legend>
{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}
{% for choice in question.choice_set.all %}
<input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}">
<label for="choice{{ forloop.counter }}">{{ choice.choice_text }}</label><br>
{% endfor %}
</fieldset>
<input type="submit" value="Vote">
</form>
11 changes: 11 additions & 0 deletions server/egglocke/pokepoll/templates/pokepoll/home.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{% load static %}

<h2>Eviii's Egglocke Maker uwu :3</h2>

<img src="{% static 'pokepoll/img/strawberi.png' %}" width=400>


<h3>X Eggs Submitted so far!</h3>


<a href="">Submit an Egg!</a>
14 changes: 14 additions & 0 deletions server/egglocke/pokepoll/templates/pokepoll/submissions.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{% load static %}

<link rel="stylesheet" href="{% static 'pokepoll/style.css' %}">


{% if latest_question_list %}
<ul>
{% for question in latest_question_list %}
<li><a href="{% url 'pokepoll:detail' question.id %}">{{ question.question_text }}</a></li>
{% endfor %}
</ul>
{% else %}
<p>No polls are available.</p>
{% endif %}
103 changes: 102 additions & 1 deletion server/egglocke/pokepoll/tests.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,104 @@
# Create your tests here.
import datetime

from django.test import TestCase
from django.utils import timezone
from django.urls import reverse
from .models import Question

# Create your tests here.

class QuestionModelTests(TestCase):
def test_was_published_recently_with_future_question(self):
"""
was_published_recently() returns False for questions whose pub_date
is in the future.
"""
time = timezone.now() + datetime.timedelta(days=30)
future_question = Question(pub_date=time)
self.assertIs(future_question.was_published_recently(), False)

def test_was_published_recently_with_old_question(self):
"""
was_published_recently() returns False for questions whose pub_date
is older than 1 day.
"""
time = timezone.now() - datetime.timedelta(days=1, seconds=1)
old_question = Question(pub_date=time)
self.assertIs(old_question.was_published_recently(), False)


def test_was_published_recently_with_recent_question(self):
"""
was_published_recently() returns True for questions whose pub_date
is within the last day.
"""
time = timezone.now() - datetime.timedelta(hours=23, minutes=59, seconds=59)
recent_question = Question(pub_date=time)
self.assertIs(recent_question.was_published_recently(), True)

def create_question(question_text, days):
"""
Create a question with the given `question_text` and published the
given number of `days` offset to now (negative for questions published
in the past, positive for questions that have yet to be published).
"""
time = timezone.now() + datetime.timedelta(days=days)
return Question.objects.create(question_text=question_text, pub_date=time)


class QuestionIndexViewTests(TestCase):
def test_no_questions(self):
"""
If no questions exist, an appropriate message is displayed.
"""
response = self.client.get(reverse("pokepoll:index"))
self.assertEqual(response.status_code, 200)
self.assertContains(response, "No polls are available.")
self.assertQuerySetEqual(response.context["latest_question_list"], [])

def test_past_question(self):
"""
Questions with a pub_date in the past are displayed on the
index page.
"""
question = create_question(question_text="Past question.", days=-30)
response = self.client.get(reverse("pokepoll:index"))
self.assertQuerySetEqual(
response.context["latest_question_list"],
[question],
)

def test_future_question(self):
"""
Questions with a pub_date in the future aren't displayed on
the index page.
"""
create_question(question_text="Future question.", days=30)
response = self.client.get(reverse("pokepoll:index"))
self.assertContains(response, "No polls are available.")
self.assertQuerySetEqual(response.context["latest_question_list"], [])

def test_future_question_and_past_question(self):
"""
Even if both past and future questions exist, only past questions
are displayed.
"""
question = create_question(question_text="Past question.", days=-30)
create_question(question_text="Future question.", days=30)
response = self.client.get(reverse("pokepoll:index"))
self.assertQuerySetEqual(
response.context["latest_question_list"],
[question],
)

def test_two_past_questions(self):
"""
The questions index page may display multiple questions.
"""
question1 = create_question(question_text="Past question 1.", days=-30)
question2 = create_question(question_text="Past question 2.", days=-5)
response = self.client.get(reverse("pokepoll:index"))
self.assertQuerySetEqual(
response.context["latest_question_list"],
[question2, question1],
)
7 changes: 6 additions & 1 deletion server/egglocke/pokepoll/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

from . import views

app_name = "pokepoll"
urlpatterns = [
path("", views.index, name="index"),
path("", views.HomeView.as_view(), name="home"),
path("submissions/", views.IndexView.as_view(), name="submissions"),
path("<int:pk>/", views.DetailView.as_view(), name="detail"),
path("<int:pk>/results/", views.ResultsView.as_view(), name="results"),
path("<int:question_id>/vote/", views.vote, name="vote"),
]
59 changes: 55 additions & 4 deletions server/egglocke/pokepoll/views.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,59 @@
from django.shortcuts import render
from django.shortcuts import render, get_object_or_404
from django.template import loader
from django.http import Http404, HttpResponse, HttpResponseRedirect
from django.db.models import F
from django.views import generic
from django.utils import timezone

# Create your views here.
from django.http import HttpResponse
from django.urls import reverse
from .models import Question, Choice

class HomeView(generic.TemplateView):
template_name = "pokepoll/home.html"

def index(request):
return HttpResponse("Hello, world. You're at the polls index.")
class IndexView(generic.ListView):
template_name = "pokepoll/submissions.html"
context_object_name = "latest_question_list"

def get_queryset(self):
"""
Return the last five published questions (not including those set to be
published in the future).
"""
return Question.objects.filter(pub_date__lte=timezone.now()).order_by("-pub_date")[
:5
]


class DetailView(generic.DetailView):
model = Question
template_name = "pokepoll/detail.html"


class ResultsView(generic.DetailView):
model = Question
template_name = "pokepoll/results.html"


def vote(request, question_id):
question = get_object_or_404(Question, pk=question_id)
try:
selected_choice = question.choice_set.get(pk=request.POST["choice"])
except (KeyError, Choice.DoesNotExist):
# Redisplay the question voting form.
return render(
request,
"pokepoll/detail.html",
{
"question": question,
"error_message": "You didn't select a choice.",
},
)
else:
selected_choice.votes = F("votes") + 1
selected_choice.save()
# Always return an HttpResponseRedirect after successfully dealing
# with POST data. This prevents data from being posted twice if a
# user hits the Back button.
return HttpResponseRedirect(reverse("pokepoll:results", args=(question.id,)))

0 comments on commit 0be5d23

Please sign in to comment.