show different content based on logged in user dja

2020-08-01 05:16发布

问题:

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

回答1:

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.