Making with Code

Views #

Views are the key link between the Model and HTML files. Django has two main types of views:


[1] Class Base Views #

πŸ‘€ Let’s start by looking at our existing class based views in ridde_app/views.py Each view inherits a Django view. For now we are going to ignore NewRiddleForm(FormView). We will go in-depth in forms in a later lab.

  • IndexView(TemplateView)
  • RiddleListView(ListView)
  • RiddleDetailView(DetailView)

πŸ“– Take a look at documentation for each Class View

There are a TON of different ways to achieve the same outcome in Django. We will just explore a few of them in this lab.


[TemplateView] #

TemplateView is a view that simply directs the a url path to a HTML file.

πŸ‘€ Let’s look at IndexView(TemplateView). You can view it HERE.

class IndexView(TemplateView):
    template_name = "index.html"

The only attribute TemplateView NEEDS is a template_name.

β˜‘οΈ Let’s add complexity to our IndexView by having a random riddle appear on our index page.

πŸ’» In IndexView(TemplateView) add the get_context_data() function. This is a powerful function that allows you to send data to a template.

def get_context_data(self, **kwargs):
    context = super().get_context_data(**kwargs)
    context['riddle'] = Riddle.objects.order_by("?").first()
    return context

order_by("?") can be slow with larger databases, you can read more about it here if interested

πŸ’» To see the random riddle appear, you will need to use the context['riddle'] in templates/index.html. Add the line below to line 8.

{{riddle}}

🧐 You may be wondering, why does it show the question? That is because the __str__() method is overridden in ridde_app/models.py.

def __str__(self):
    return f"{self.question}"

πŸ’» Add another Riddle property to the __str() method.

🌐 Refresh http://127.0.0.1:8000/ to see your changes!

πŸ’» Now, return to the index.html page and try just showing the riddle answer, by using the fields.

{{riddle.answer}}

There are multiple ways to have control over what appears in the template!


Context Data is a very powerful dictionary that allows you to send data to your template! You can add as many key, value pairs the context as you need.

context = {
    'riddle': Riddle.objects.order_by("?").first()
}

πŸ’» Try, adding a new key,value pair and see if you can access it in index.html


[ListView] #

ListView is a view that sends an entire Queryset of a model. You can think of a Queryset as a list of models.

πŸ‘€ Let’s look at RiddleList(TemplateView).

class RiddleListView(ListView):
    model = Riddle
    template_name = "riddle_list.html"

    queryset = Riddle.objects.all()
  • it requires you to specify a model and a template_name
  • by defining a queryset you can have more control over what data gets sent

πŸ’» Use .order_by() to change the sort order of riddles. Up to you to decide how to sort.

>>> Riddle.objects.order_by('likes')
<QuerySet [<Riddle: Where does today come before yesterday?>, <Riddle: I speak without a mouth and hear without ears. I have no body, but I come alive with wind. What am I?>, <Riddle: who am i?>, <Riddle: What is black when it’s clean and white when it’s dirty?>, <Riddle: I’m the rare case when today comes before yesterday. What am I?>]>
>>>  Riddle.objects.order_by('question')
<QuerySet [<Riddle: I speak without a mouth and hear without ears. I have no body, but I come alive with wind. What am I?>, <Riddle: I’m the rare case when today comes before yesterday. What am I?>, <Riddle: What is black when it’s clean and white when it’s dirty?>, <Riddle: Where does today come before yesterday?>, <Riddle: who am i?>]>
>>>   Riddle.objects.order_by('-question')
<QuerySet [<Riddle: who am i?>, <Riddle: Where does today come before yesterday?>, <Riddle: What is black when it’s clean and white when it’s dirty?>, <Riddle: I’m the rare case when today comes before yesterday. What am I?>, <Riddle: I speak without a mouth and hear without ears. I have no body, but I come alive with wind. What am I?>]>
  • what is the difference between ('question') and ('-question')?

🌐 Refresh and visit 127.0.0.1:8000/riddle/list to see your changes!


You can also add the get_context_data() method into a ListView.

πŸ’» Add the get_context_data() method to RiddleList(TemplateView)

  • Send data to communicate what how the riddles are sorted
  • Display the data on the riddle_list.html page.

[DetailView] #

DetailView is a view that sends one instance of a model. In this app, it will send one Riddle object.

πŸ‘€ Let’s look at RiddleDetailView(DetailView).

class RiddleDetailView(DetailView):
    model = Riddle
    template_name = "riddle_detail.html"
  • it requires you to specify a model and a template_name

πŸ‘€ Now, let’s take a look at line 9 in riddle_app/urls.py.

path('riddle/detail/<int:pk>/', RiddleDetailView.as_view(), name='riddle-detail'),

<int:pk> - this tells the DetailView which Riddle to send based on the id

🌐 Try it out by visiting the path http://127.0.0.1:8000/riddle/detail/1. You can change 1 to any id that is in the database.


You can also add the get_context_data() method into a DetailView.

πŸ’» Add the get_context_data() method to RiddleDetailView(DetailView) to send the current datetime the page is accessed. You will need to reference the resources to figure out how to do this.

🌐 Test your changes by visiting the path 127.0.0.1:8000/riddle/detail/1.


[2] Function Views #

Function based views are great for when a class based view does not fit your needs or if you want more specific over the GET and POST request cycle. In this app we function based views for:

  • liking a riddle
  • guessing a riddle

πŸ’» Add a dislike feature to your app that simply the likes. You will need to edit:

  • riddle_app/models.py
  • riddle_app/views.py
  • riddle_app/urls.py
  • riddle_app/templates/riddle_detail.html

🌐 Test your changes by visiting the path 127.0.0.1:8000/riddle/detail/1.


[3] Deliverables #

⚑✨

πŸ’» Push your work to Github:

  • git status
  • git add -A
  • git status
  • git commit -m "your message goes here"
    • be sure to customize this message, do not copy and paste this line
  • git push


[Extension] #

Try implementing any of these features:

  • a new ListView to only see easy, medium, or hard riddles
  • a UpdateView - to allow a user to change an existing Riddle
  • a non-destructive way to ‘delete’ riddles by ‘archiving’ them