So I just learned Python/Django last weekend. What I'm trying to do is have url routes available with different content depending on who's logged in. So my usecase is I create 5 usernames/passwords and then those 5 users can login to read specific content/routes catered to them that no other user should be able to see.
Right now I have these routes with correlating views.
urlpatterns = [
url(r'^$', accounts.views.loginview),
url(r'^accounts/', include('accounts.urls')),
url(r'^sitepages/', include('sitepages.urls')),
]
I get the auth thing, I'm filtering content to only logged in users using @login_required, it looks like this :
from django.shortcuts import render
from django.contrib.auth.decorators import login_required
@login_required
def attributes(request):
return render(request, 'sitepages/something.html')
I've researched how to have a different menu bar depending on the user, etc. But I haven't been able to find how to have entirely different routes and content pages depending on the user.
I think I'll need to do this using groups in Django and I think that I'll need to use the user's foreign key in order to cater the content. I created one group using admin, but I'm having a hard time consolidating my next step.
These are the resources I've checked out:
Django Database routing based on current user logged in
Django restrict pages to certain users
https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/Authentication
https://docs.djangoproject.com/en/1.10/topics/auth/default/
I'm on Python version 3.6.0; Django version 1.10.6
My answer is based on assumption. But these are also some general pointers, that should help you understand your options and more about django's way of model/url/view concept.
To store different content for users I would recommend creating a simple model in your models.py
to save everything in your database, with fields for title, content and a reference to the user it belongs too:
class Page(models.Model):
title = models.CharField(max_length=50)
slug = models.SlugField(max_length=50)
content = models.TextField(...)
user = models.ForeignKey(settings.AUTH_USER_MODEL)
The slug field holds the title in a url-friendly format that you can look for in an url pattern as variable in your urls.py
:
urlpatterns = [
url(r'^(?P<user>\w+)/(?P<slug>\w+)/$', views.PageView.as_view(), name='page'),
...
]
It defines two placeholders so you can have urls like:
- /sarah/apples
- /jim/bananas
- /anna/apples
They will all be 'caught' by the same url pattern.
Check how to create a simple Class-based TemplateView
in your views.py
. And use the collected url parameters (e.g. user sarah
and title apples
) to query the database for the corresponding page, then populate the template context with those values to fill your html template placeholders.
If different urls are not a requirement for you, you can also have different content served based on the current user with a url that does not need variables:
url(r'^/profile/$', views.ProfileView.as_view(), name='profile'),
In your view you can pick the right page record like this then:
content = Page.objects.get(user=request.user).content
Another possibility is using GET parameters: e.g /?page=intro
.
Then use Page.objects.get(title=request.GET.get("intro"))
to get the content from the database. You can combine the last two as well.
Update:
To ensure that only the right user can access the page you can use a django shortcut:
get_object_or_404(Page, slug=slug, user=request.user)
If will show a "Page not found" if the current user does not have a page named like this. E.g. if user jim
tries to access /anna/apple
he will get a 404 response while anna
can see her apple page.