Tech With Tim Logo
Go back

User Specific Pages & Data

##User Specific Pages Up until this point everyone has been able to access every page of our website and users share a common list of to do lists. This is obviously not ideal and in many instances you want each user to have their own set of information that is specific to them. In this tutorial I will be showing how we can save information specific to each user and how to restrict users to only see certain pages.

Updating Models

What we will start by doing is updating our models so that each To Do List is assigned to a specific user. This way each user can only access their To Do Lists.

We will modify the models.py from within our main app to be the following:

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

# Create your models here.
class ToDoList(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="todolist", null=True) # <--- added
    name = models.CharField(max_length=200)

    def __str__(self):
	return self.name


class Item(models.Model):
    todolist = models.ForeignKey(ToDoList, on_delete=models.CASCADE)
    text = models.CharField(max_length=300)
    complete = models.BooleanField()

    def __str__(self):
	return self.text

Because we’ve made changes to our Database we need to execute the following commands:

python manage.py makemigrations python manage.py migrate

If either of these commands case you any trouble watch the video for a solution.

Modifying View.py

Since we’ve added a foreign key to ToDoList this means whenever we create one we need to add it to a user. So we will modify the create function inside views.py to do this.

# inside views.py
def create(response):
    if response.method == "POST":
	form = CreateNewList(response.POST)

	if form.is_valid():
	    n = form.cleaned_data["name"]
	    t = ToDoList(name=n)
	    t.save()
	    response.user.todolist.add(t)  # adds the to do list to the current logged in user

	    return HttpResponseRedirect("/%i" %t.id)

    else:
        form = CreateNewList()

    return render(response, "main/create.html", {"form":form})

Viewing All of A Users Lists

Now we are going to add a new page that will allow us to view all of the current users To Do Lists. We will create another template called view.html inside of templates > main.

# view.html
{% extends "main/base.html" %}

{% block title %}
View
{% endblock %}

{% block content %}
    {% for td in user.todolist.all %}
	<p><a href="/{{td.id}}">{{td.name}}</a></p>
    {% endfor %}
{% endblock %}

Now we will add a url to link to this page:

# urls.py
from django.urls import path

from . import views

urlpatterns = [
path("<int:id>", views.index, name="index"),
path("", views.home, name="home"),
path("home/", views.home, name="home"),
path("create/", views.create, name="create"),
path("view/", views.view, name="view"),  # <-- added
]

And create a function to render the view:

# inside views.py
def view(response):
    return render(response, "main/view.html", {})

And now when we visit /view we can see a list of all of our To Do Lists. Try logging out (/logout) and logging back in (/login) with a different user and seeing how the view page changes.

Restricting Pages

Now time to restrict access to users that are not logged in. For this example we will only restrict access to viewing a To Do List that is not yours but you can do this anywhere.

If a user tries to access a To Do List that they did not create we will simply redirect them to the home page. We will need to modify our index function to accomplish this:

# inside views.py
def index(response, id):
    ls = ToDoList.objects.get(id=id)

    if ls in response.user.todolist.all():

	if response.method == "POST":
	    if response.POST.get("save"):
		for item in ls.item_set.all():
		    if response.POST.get("c" + str(item.id)) == "clicked":
		        item.complete = True
		    else:
		        item.complete = False

		    item.save()

	    elif response.POST.get("newItem"):
		txt = response.POST.get("new")

		if len(txt) > 2:
		    ls.item_set.create(text=txt, complete=False)
		else:
		    print("invalid")


	return render(response, "main/list.html", {"ls":ls})

    return render(response, "main/home.html", {})
Design & Development by Ibezio Logo