How to restrict admin link/button in Django? - python

This is what I expect: if a user has position "1" (Admin) the nav menu in home.html must show "Admin" link to an admin page. If a user has position "2" (User) it won't show the link.
But when I run server this code generate as many Admin links as there are registered users. I want only one link for currently logged-in user to be shown. How can I do that? I know that there's something wrong with "for user in position", but how to fix it for currently logged-in user?
models.py
class Profile(models.Model):
positions = (
('1', 'Admin'),
('2', 'User'),
)
user = models.OneToOneField(User, on_delete=models.CASCADE, unique=True)
image = models.ImageField(default='default.jpg', upload_to='profile_pics')
position = models.CharField(max_length=50, default='Position', choices=positions)
views.py
def home(request):
user_position = Profile.objects.all()
return render(request, 'home.html', {
'position': user_position,
})
home.html
{% for user in position %}
{% if user.position == '1' %}
<a class="nav-link" aria-current="page" href="/admin">Admin</a>
{% endif %}
{% endfor %}

You can also use the is_superuser attribute in your template to achieve this:
{% if user.is_superuser %}
admin
{% endif %}
if you want to check it based on the username only you can use:
{% if user.username == "Admin" %}
admin
{% endif %}
Another thing you can do is to create 2 groups inside your admin panel; admins & users.
Then you have to create a custom template tag(has_group for example) to show the nav items based on these groups which is a better solution i think. Then you can use something like this in your template:
{% if user|has_group:"admin" %}
<p>User belongs to the admin group
{% else %}
<p>belongs to users group</p>
{% endif %}

Related

How do i access the username of user logged in with google in Django from user model

How to access the username of user logged in with google in django all-auth from the user model
how can i access the user name of the logged in user with google from user model
for example
{% for i in user %}
{{i.socialaccount_set.all.0.extra_data.name}}//is there a way to acces the user name in this way
{% endfor %}
My views.py
def leaderBoard(request):
points= Points.objects.all().order_by("-score")
context = {"user": result}
return render(request, "Main/lb.html", context)
My model.py
class Points(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
score = models.BigIntegerField()
my htmlfile
<div class="leaderboard-table">
{% for i in user %}
<div class="board-item">
<div>1</div>
<div>
{% if i.socialaccount_set.all.0.get_avatar_url %}
<img src="{{i.socialaccount_set.all.0.get_avatar_url}}" />
{{i}}//how to access the user name of the googleuser
</div>
<div>Test's Taken - 30</div>
<div>{{i.score}} Points</div>
</div>
{% endfor %}
</div>
With the username, I assume you want to access Django's default username field for that particular user.
You can access it like this.
{% for i in user %}
{{i.username}}
{% endfor %}
Also, one more thing I noticed is that your view is missing result data which you are appending to your context dictionary.

How to show in template current users role in project?

Can someone say where I did mistake?
I have Project model. Every project has members. I have project_detail page where I want to show current user's username and his role in project. Right know in template it shows me only current user's username but not his role in project.
models.py:
class Project(models.Model):
members = models.ManyToManyField(User, through='Member', help_text=_('Members'))
ROLE_CHOICES = (
('manager', _('Manager')),
('developer', _('Developer')),
('business_analyst', _('Business Analyst')),
('system_analyst', _('System Analyst')),
)
class Member(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
project = models.ForeignKey(Project, on_delete=models.CASCADE)
role = models.CharField(max_length=20, choices=ROLE_CHOICES)
views.py:
def project_detail(request, project_code):
project = get_object_or_404(Project, pk=project_code, status='open')
context = {'project': project,}
return render(request, 'project/project_detail.html', context)
project_detail.html:
<span class="nav-link active navbar-text">
{{ user.get_username }}:
{% for member in project.member_set.all %}
{% if member.user == user.get_username %}
{{ member.get_role_display }}
{% endif %}
{% endfor %}
</span>
Why are you comparing the user against the result of get_username? That presumably returns a username string, but the user is, well, a user. This would work:
{% if member.user == user %}
{{ member.get_role_display }}
{% endif %}
But don't do this. It's very inefficient to loop over all project members and get the user for each one. Instead, do a single query in the view:
member = project.member_set.get(user=request.user)
context = {'project': project, 'role': member.get_role_display()}

To determine the user's role in the project

In my django website I have pages like 'project_list' and 'project_detail'. Every project has members with different roles (developer, manager, e.t.c.). I want to show different buttons depending on the current user's role in the project in template. I need ideas how to realise it. Lets say something like that in template:
{% if request.user.role_in_the_current_project = 'manager' %}
SOW SOMETHING
{% endif %}
models.py
class Project(models.Model):
name = models.CharField(max_length=250,)
slug = models.SlugField(max_length=250, unique_for_date='publication_date',)
*Other fields*
def get_absolute_url(self):
return reverse('project:project_detail', args=[self.slug])
class Membership (models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
project = models.ForeignKey(Project, on_delete=models.CASCADE)
ROLE_CHOICES = (
('manager', 'Manager'),
('developer', 'Developer'),
('business_analyst', 'Business analyst'),
('system_analysts', 'System analysts'),
)
role = models.CharField(max_length=20, choices=ROLE_CHOICES,)
view.py
def project_detail(request, slug):
project = get_object_or_404(Project, slug=slug, status='public')
return render(request, 'project/project_detail.html', {'project': project,})
project_detail.html
{% block content %}
<h1>{{ project.name }}</h1>
<p>{{ project.description|linebreaks }}</p>
{%endblock %}
urls.py
urlpatterns = [
url(r'^project/(?P<slug>[-\w]+)/$', project_detail, name='project_detail'),
]
You can use the concept of choices inside a model field and then by using these you can make decisions inside your templates (or to your views) to show appropriate content.
Let me know if you need more info on this.
[EDIT]: So, what you want is to check each time the value of role. Right?
In your views.py write:
project = get_object_or_404(Project, slug=slug, status='public')
memberships = project.membership_set.all()
Then because one project can have many Membership records you should iterate over the memberships to get each time the role.
So, in your template:
{% for membership in memberships %}
{% if membership.role == 'Manager' %} Do stuff here {% endif %}
{% endfor %}
Note that .role will give you back the second value of the ROLE_CHOICES sub-tuple which is capitalized, while the first one is that will be shown in the user if you use the function get_role_display()
Well, after all I found solusion. In view I add:
is_manager = project.membership_set.filter(user=request.user, role='Manager').exists()
Then in template I add:
{% if is_manager %}
<button>Create</button>
{% endif %}

Filter on many-to-one model

I want to be able assign users vehicle registrations, and when the user logs into the website their home page should have a list of vehicle regs they own.
However I cannot get the model class to filter on the foreign key.
views.py
#login_required
def home(request):
# This is the basic user landing Page
veh_list = Vehicle.objects.filter(UserProfile.user)
return render(request, 'portal/home.html', {"veh_list": veh_list})
model.py
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class UserProfile(models.Model):
# This line is required. Links UserProfile to a User model instance.
user = models.OneToOneField(User)
# The additional attributes we wish to include.
compName = models.CharField(max_length = 20)
milkco = models.IntegerField()
# Override the __unicode__() method to return out something meaningful!
def __unicode__(self):
return self.user.username
class Vehicle(models.Model):
vehid = models.CharField(max_length = 10)
company = models.ForeignKey(UserProfile, default = 1)
class Meta:
db_table = "vehicle"
def __unicode__(self):
return self.vehid
home.html
<!DOCTYPE html>
{% extends 'portal/base.html' %}
{% block title %}{{user.first_name }} {{ user.last_name }} Portal{% endblock %}
{% block content %}
<p>This is the home Page</p>
{% if user.is_authenticated %}
<h4>Optiload says... hello {{ user.first_name }} {{ user.last_name }}!</h4>
{% endif %}
{% for veh in veh_list %}
{{ veh}}
{% endfor %}
{% if user.is_authenticated %}
Logout<br/>
{% endif %}
{% endblock %}
Could someone help me with where I'm going wrong?
Thanks
Django offers a powerful and intuitive way to “follow” relationships in lookups, taking care of the SQL JOINs for you automatically, behind the scenes. To span a relationship, just use the field name of related fields across models, separated by double underscores, until you get to the field you want.
So your query should look like
veh_list = Vehicle.objects.filter(company__user=request.user)
Reference
You cannot make queries with unnamed arguments:
Vehicle.objects.filter(UserProfile.user)
In this case you want:
Vehicle.objects.filter(company=[your user])

Django: How to display author of query of posts?

I'm trying to make individual pages for each author showing their name and posts. I can't seem to get the username displayed.
views.py
class UserProfileView(generic.ListView):
template_name = 'howl/user-profile.html'
context_object_name = 'user_howls'
def get_queryset(self):
author = self.request.user
u = User.objects.get(username=author)
return Howl.objects.filter(author=u)
models.py
class Howl(models.Model):
author = models.ForeignKey(User, null=True)
content = models.CharField(max_length=150)
Here is where I'm stuck.
user-profile.html
{% extends 'howl/base.html' %}
{% block content %}
<h1>User: {{user_howl.author}}</h1>
{% for user_howl in user_howls %}
<ul>
<li>{{user_howl.content}}</li>
</ul>
{% endfor %}
{% endblock %}
The content is displayed just fine, but the heading just says "User: ", how do I give it a context without using a for loop?
I've tried:
{% for author in user_howls.author %}
<h1>User: {{author}}</h1>
{% endfor %}
and
{% if user_howls.author %}
<h1>User: {{user_howl.author}}</h1>
{% endif %}
Still the same outcome, displaying "User: "
user_howls is a queryset so it won't have an author attribute, you need to get the author of the iterated object
{% for howl in user_howls %}
<h1>User: {{ howl.author}}</h1>
{% endfor %}
More to the point though, it doesn't make sense to start from a Howl list, when you are just returning the results for the user_profile, nor does it make sense to use a ListView. so instead, start from the user and then look up its howls
user_obj.howl_set.all()
Since your queryset is based on the posts belonging to the current user, you can shortcut all of this and just show the user directly:
User: {{ user }}

Categories

Resources