I am creating a modular menu in Django that has the following structure;
class Pagina(models.Model):
nome = models.CharField(max_length=250, blank=True)
url = models.CharField(max_length=250)
def __str__(self):
return self.nome
class Voce(models.Model):
nome = models.CharField(max_length=250, blank=True)
Pagine = models.ManyToManyField(Pagina)
Permesso = models.ForeignKey(Permesso, on_delete=models.CASCADE)
def __str__(self):
return self.nome
class Menu(models.Model):
Voci = models.ManyToManyField(Voce)
I need to check if the user has the required permission to see the submenu(permission that is in a group).
The menu is rendered the following way;
{% for voce in menu.Voci.all %}
<li class="m-menu__item m-menu__item--submenu m-menu__item--rel {% ifequal parent voce.nome %}m-menu__item--active{% endifequal %}" m-menu-submenu-toggle="click" aria-haspopup="true">
<a href="javascript:;" class="m-menu__link m-menu__toggle">
<span class="m-menu__item-here"></span><span class="m-menu__link-text">{{voce}}</span><i class="m-menu__hor-arrow la la-angle-down"></i><i class="m-menu__ver-arrow la la-angle-right"></i>
</a>
<div class="m-menu__submenu m-menu__submenu--classic m-menu__submenu--left"><span class="m-menu__arrow m-menu__arrow--adjust"></span>
<ul class="m-menu__subnav">
{% for pagina in voce.Pagine.all %}
<li class="m-menu__item {% ifequal request.path pagina.url %}m-menu__item--active{% endifequal %}" aria-haspopup="true">
<a href="{{pagina.url}}" class="m-menu__link ">
<i class="m-menu__link-bullet m-menu__link-bullet--line"><span></span></i>
<span class="m-menu__link-title"><span class="m-menu__link-wrap"><span class="m-menu__link-text">{{pagina.nome}}</span></span></span>
</a>
</li>
{% endfor %}
</ul>
</div>
</li>
{% endfor %}
The check would need to happen just after the first for loop starts in order to determine whether or not to display that particular submenu.
The "gruppo" object of the user is a foreignkey relation to a personalized Group object, which has a ManyToMany relation with different permissions, each having a name. I need to check if a user has the same permission as the "Voce" model currently being looped through.
Thank you for your time,
Matteo
Related
I'm building an app in Django, using Bulma for styling. I have a Polishes model that has a favorites field, which references the User (users can save polishes to their list of favorites):
models.py:
class Polish(models.Model):
name = models.CharField(max_length=100)
image = models.CharField(max_length=400, default="https://www.dictionary.com/e/wp-content/uploads/2018/02/nail-polish-light-skin-tone.png")
brand = models.ForeignKey(Brand, on_delete=models.CASCADE, related_name='polishes')
favorites = models.ManyToManyField(User, related_name='favorite', default=None, blank=True)
def __str__(self):
return self.name
The add_favorites function checks to see if the polish has been added to the user's favorites already, and if it has, it removes the polish from the list. If it hasn't, it adds it:
views.py:
# login_required
def add_favorite(request, id):
polish = get_object_or_404(Polish, id=id)
if polish.favorites.filter(id=request.user.id).exists():
polish.favorites.remove(request.user.pk)
else:
polish.favorites.add(request.user.pk)
return redirect('favorites_list')
When I render the list of polishes, I'm using Bulma cards, displaying one polish per card. In the footer of the card, I want it to say 'Save to Favorites' if the polish is not in the user's list of favoties and 'Remove from Favorites' if it is. I'm struggling to get this piece to work. It will currently show either Save to Favorites or Remove from Favorites on all of the cards.
Does anyone have any insight on how to render a different message only on those that are already on the favorites list?
polish_list.html:
...
<div class="gallery">
{% for polish in polishes %}
<a href="{% url 'polish_reviews' polish.pk %}">
<div class="card">
<div class="card-header">
<p class="card-header-title">{{polish.name}} by {{polish.brand}}</p>
</div>
<div class="card-image">
<figure class="image is-square">
<img src="{{polish.image}}" alt="{{polish.name}}" />
</figure>
</div>
<footer class="card-footer">
{% if polish.favorites %}
Remove from Favorites
{% elif user.is_authenticated %}
Save to Favorites
{% else %}
Save to Favorites
{%endif%}
</footer>
</div>
</a>
{% empty %}
<article class="message">
<div class="message-header">
<p>No Polishes Available</p>
</div>
</article>
{% endfor %}
</div>
...
I have tried using a conditional in my polish_list.html - {% if polish.favorites %} - but this will make the change on all of the cards rather than just on those that are saved to favorites.
I am asking this question again because I did not receive a satisfactory answer in my previous attempt. It may be difficult for me to fully convey the issue I am trying to resolve, but I will do my best to provide a clear and concise explanation.
.
I am trying to run a query that retrieves a list of followers, as well as the list of followers and followings for each follower. I have included an image that illustrates this structure. I am currently using the following code to attempt this, but it is not producing the expected results. Can you help me understand what I am doing wrong and how I can correctly run this query?
views.py
def get_context_data(self, *args, **kwargs):
context = super(FollowerView,self).get_context_data(*args, **kwargs)
user = context['user']
user_com = User.objects.get(username=user)
myfollowers = user_com.is_following.all()
followers_Array =[]
followerings_Array =[]
for target_list in myfollowers:
user_obj = User.objects.get(username=target_list)
followers_obj = user_obj.is_following.all()
print(followers_obj,'name o ki line')
followerings_Array.append(followerings_Array)
print(followers_obj,user_obj)
followerings_obj = user_obj.userprofile.follower.all()
followerings_Array.append(followerings_obj)
print(followerings_obj,user_obj)
print(followerings_Array,'arry one one one ')
context['myfollowers_data']= followers_Array
context['myfollowerings_data']= followerings_Array
return context
I am currently using two arrays in my code, but I would prefer to avoid doing so if possible. My current implementation is not producing the desired output when I return the arrays in the context. Can you suggest an alternative approach that allows me to display the data in the manner illustrated in the image, and can you review the followers template to see if I am making any mistakes there?
{% for follower in user.is_following.all %}
<div class="followers-body">
<img class="img-responsive img-circle" src="{{follower.avatar.url}}" alt="">
<div class="name-box">
<h4>{{follower}}</h4>
<span>#{{follower}}</span>
<div class="followers-base">
<ul class="list-group">
<li class="list-group-item full-width">
<div class="pull-left" style="margin-right: 20px;">
{% if myfollowers_data %}
{% for user in myfollowers_data %}
<img src="{{user.userprofile.avatar.url}}" alt="" class="img-circle max-w-40 ">
{% endfor %}
{% endif %}
<span> {{myfollowers_data.count}} Followers </span>
</div><!--/ pull-left -->
</li>
<li class="list-group-item full-width">
<div class="pull-left">
{% for usr in myfollowerings_data %}
<img src="{{usr.userprofile.avatar.url}}" alt="" class="img-circle max-w-40 ">
{% endfor %}
<span> {{myfollowerings_data|length}} Following </span>
</div><!--/ pull-right -->
</li><!--/ list-group-item -->
</ul>
</div><!--/ followers-base -->
</div><!--/ name-box -->
<span> Follow</span>
</div><!--/ followers-body -->
{% endfor %}
models.py
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
follower = models.ManyToManyField(User, related_name ='is_following',blank=True,)
close_friends = models.ManyToManyField(User,related_name='my_close_friends', blank=True)
rank = models.ManyToManyField(Rank, related_name='rank', default='Newbie', blank=True)
avatar = models.ImageField(("Avatar"), upload_to='displays', default = '1.jpg',height_field=None, width_field=None, max_length=None,blank = True)
create_date = models.DateField(auto_now_add=True,null=True)
#property
def email_address(self):
return self.user.email
objects = ProfileManager()
def __str__(self):
return f'{self.user.username}'
def get_absolute_url(self):
return reverse("profiles:final_detail", kwargs={"username": self.user.username})
If more code in require than tell me in a comment session. I will update my question with that information.
Okay, this should all be achievable from the template:
template.html:
<!-- users followers -->
{% for follower1 in user.is_following.all %}
<img src="{{ follower1.avatar.url }}"/>
<!-- followers followers -->
{% for follower2 in follower1.is_following.all %}
<img src="{{ follower2.avatar.url }}"/>
...
{% endfor %}
{% endfor %}
am new to Django and am trying to create a blog site where users can sign up and post articles, but my problem is how can I display a user's post on the user's profile page so that when other users reading the post clicks on the author's name it takes them to the post.author's profile page with the post.author's recent post listed and not the request.user's post. here is my code.
here is accounts/views.py
views.py
#login_required()
def user_profile_view(request, username):
post = User.objects.filter(courses__author=username)
context = {'courses': courses}
return render(request, 'accounts/user_profile_view.html', context)
and here is post/models.py
models.py
class Posts(models.Model):
author = models.ForeignKey(User, on_delete=models.CASCADE)
cover = ProcessedImageField(upload_to='post_featured_image',
processors=[ResizeToFill(600, 300)],
format='png',
options={'quality': 80},
blank=True)
slug = models.SlugField()
title = models.CharField(max_length=200)
body = models.TextField()
summary = models.TextField(max_length=200)
here is the template
post_list.html
{% extends 'base.html' %}
{% load static %}
{% block content %}
<div class="col-lg-6">
{% for course in courses_list %}
<div class="central-meta item">
<div class="user-post">
<div class="friend-info">
{% if post.author.profile.avatar %}
<figure>
<img src="{{ post.author.profile.avatar.url }}" alt="">
</figure>
{% else %}
<img src="{% static 'default.ico' %}" alt="">
{% endif %}
<div class="friend-name">
<ins>{{ course.author.get_full_name|title }}</ins>
<span>published: {{ post.published }}</span>
</div>
<div class="post-meta">
{% if course.cover %}
<img src="{{ post.cover.url }}" alt="">
{% endif %}
<div class="friend-name">
<ins>{{ course.title|title }}</ins>
</div>
<div class="description">
<p><span>{{ post.summary|capfirst }}</span></p>
</div>
</div>
</div>
</div>
</div>
{% endfor %}
</div>
{% endblock content %}
here is my accounts/urls.py
urls.py
app_name = 'accounts'
urlpatterns = [
path('accounts/profile/<str:username>/', user_profile_view, name='user_profile'),
]
you should be able do that, easy and via lots of ways.
make a post model like this:
class Post(models.Model):
author = foreign_key(User, related_name="posts", on_delete=models.CASCADE)
title = char_field()
content ........
so with that related name you will be able to reverse from user to its posts too!.
in your template do this:
{{ post.author }}
this link will redirect user to the posts author dashboard if you arrange the urls pattern correctly.
then for sorting authors posts, you have to pass the dashboard_owner to the template and use this name instead of user which normally will refer to the request.user -> user who are visiting the page
{% for post in dash_owner.posts.all %}
<li> <a href="{{ post.get_abslute_url }}" target="_blink">
{{ post.title }} </a> </li>
{% endfor %}
in views.py
def dashboard(request, owner_id=None)
if owner_id:
dash_owner = get_or_404(User, id=owner_id)
elif request.user.is_authenticated:
dash_owner = User.objectd.get(id=request.user.id)
return render(request, 'dashboard.html', {'dash_owner': dash_owner})
in urls.py -> urlpatterns:
path('dashboard/<int:owner_id>/', views.dashboard, name="dashboard")
this is the idea behind that, but for get the better result, you may need to clearly define the get_absolute_url of User model, to give you the url which machts to
'dashboard/<int:id/'
or another way is instead of that, do this:
{{ post.author }}
I have two model called organization and staff.Staff model have onetoone relation with user and Foreignkey relation to the organization.The problem what i got is to filter the staffs by their related organization.I have tried liked this but didn't worked out.
models.py
class Staff(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='user')
name = models.CharField(max_length=255, blank=True, null=True)
organization = models.ForeignKey(Organization, on_delete=models.SET_NULL, blank=True, null=True,
related_name='organization')
.....other fields.....
views.py
def view_staff_users(request):
staff_users = User.objects.filter(is_staff=True)
organizations = Organization.objects.all()
staffs_by_org = Staff.objects.select_related('organization')
# tried this also:
# staffs_by_org = []
# print('staffff',staffs_by_org)
# for organization in organizations:
# staffs = Staff.objects.filter(organization=organization)
# staffs_by_org.extend(staffs)
# print('staaa',staffs_by_org)
Edited views:
def view_staff_users(request):
staff_users = User.objects.filter(is_staff=True)
organizations = Organization.objects.all()
staffs_by_org = []
for organization in organizations:
staffs_by_org = Staff.objects.filter(organization__name=organization).select_related('organization')
template
{% for user in staffs_by_org %}
# tried this also: {% for u in user.organization_set.all %}
{{user.user.name}}
{{user.username}}
{{user.email}}
{{user.user.organization}}
{% endfor %}
Edit: My template looks like this.
<ul class="nav nav-tabs customtab" role="tablist">
<li class="nav-item"> <a class="nav-link active" data-toggle="tab" href="#all" role="tab"><span class="hidden-sm-up"></span> <span class="hidden-xs-down">All Staffs</span></a> </li>
{% for organization in organizations %}
<li class="nav-item"> <a class="nav-link" data-toggle="tab" href="#{{organization.name}}" role="tab"><span class="hidden-sm-up"></span> <span class="hidden-xs-down">{{organization.name}}</span></a> </li>
{% endfor %}
</ul>
<div class="tab-content">
<div class="tab-pane active" id="all" role="tabpanel">
{% for user in staff_users %}
{{user.user.name}}
{{user.username}}
{{user.email}}
{{user.user.organization}}
{% endfor %}
</div>
{% for organization in organizations %}
<div class="tab-pane tab" id="{{organization.name}}" role="tabpanel">
{% endfor %}
{% for user in staffs_by_org %}
# tried this also: {% for u in user.organization_set.all %}
{{user.user.name}}
{{user.username}}
{{user.email}}
{{user.user.organization}}
{% endfor %}
</div>
You can filter for example with:
staffs_by_org = Staff.objects.filter(
organization__name='My organization'
).select_related('organization')
The staffs_by_org is a QuerySet of Staffs. I therefore stronly advice to use staff in the iterator. You can access the organization with staff.organization:
{% for staff in staffs_by_org %}
{{ staff.name }}
{{ staff.user.username }}
{{ staff.user.email }}
{{ staff.organization }}
{% endfor %}
If the organization has for example a name, you can render it with:
{% for staff in staffs_by_org %}
{{ staff.name }}
{{ staff.user.username }}
{{ staff.user.email }}
{{ staff.organization.name }}
{% endfor %}
Note that the related_name of a ForeignKey is the name of the relation in reverse. A better name is probably 'staff'. If you refer to the user model, it is better to use get_user_model() [Django-doc], since if you later change your mind, you can easily use another user model.
from django.contrib.auth import get_user_model
class Staff(models.Model):
user = models.OneToOneField(
get_user_model(),
on_delete=models.CASCADE,
related_name='staff'
)
name = models.CharField(max_length=255, blank=True, null=True)
organization = models.ForeignKey(
Organization,
on_delete=models.SET_NULL,
blank=True,
null=True,
related_name='staff'
)
I think one problem is that you created a loop that is rewriting itself instead of appending each batch of staff users to your queryset.
One way to do what you want (return all staff that belong to a set of organizations) is to use the in filter operator.
So, in your views.py:
organizations = Organization.objects.all()
staffs_by_org = Staff.objects.filter(
organization__in=organizations).select_related('organization')
This will return all staff from whatever organizations is.
If you want a dynamic filter for the organization name, then what you have to do is:
Pass the organization name to the request. This is usually done via
URL parameters or query strings.
Change the organizations variable
from objects.all() to objects.filter(URL_PARAMETER)
Then staffs_by_org will only return the staff from that organization.
{% if user.resume %}
<div class="empty-state-box">
<img src="{% static 'resumes/images/resume-empty-icon.png' %}" class="centered">
<p class="empty-state-text"><b>You currently don't have any resumes.</b><br>Create one and
start building your very first resume</p>
</div>
{% else %}
<p>More information here</p>
{% endif %}
models.py
from django.db import models
from users.models import User
class Resume(models.Model):
name = models.CharField(max_length=255, blank=True)
created_at = models.DateTimeField(auto_now_add=True, editable=False)
updated_at = models.DateTimeField(auto_now=True)
user = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
return self.name
views.py
from django.contrib.auth.decorators import login_required
from django.shortcuts import render
#login_required()
def my_resumes(request):
return render(request, 'resumes/myresumes.html')
I'm trying to place an empty state if a user does not have a resume. Else, I want to show other information. I can't seem to get it to work. I think I am using the if conditional statement wrong in the template.
First, your condition seems turned the wrong way. You code handling the case when the resume is not present is in the if user.resume statement. So it should rather be if not user.resume.
Second, the reverse relation is not named user.resume but user.resume_set. You can change this name using related_name if you want. For instance: user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='resumes') would enable to access it via user.resumes instead of user.resume_set.
Yet, if user.resume_set will always be evaluated to if True because it is a related manager, not a queryset. So you could do something like this:
{% if not user.resume_set.exists %}
<div class="empty-state-box">
<img src="{% static 'resumes/images/resume-empty-icon.png' %}" class="centered">
<p class="empty-state-text"><b>You currently don't have any resumes.</b><br>Create one and
start building your very first resume</p>
</div>
{% else %}
<p>More information here</p>
{% endif %}
However, in your else statement, you will likely iterate over resumes with something like this {% for resume in user.resume_set.all %}. In such, case you will hit twice the database. Once for user.resume_set.exists and once for user.resume_set.all, which is not needed because you can know the result of user.resume_set.exists from the result of user.resume_set.all. Django templates allows you to do something like this to handle empty case when iterating an object:
{% for resume in user.resume_set.all %}
Your code to display a resume item here
{% empty %}
<div class="empty-state-box">
<img src="{% static 'resumes/images/resume-empty-icon.png' %}" class="centered">
<p class="empty-state-text"><b>You currently don't have any resumes.</b><br>Create one and
start building your very first resume</p>
</div>
{% endif %}
But still, it is not very good practice to execute querysets in a template. To avoid this, you can pass it in your view:
#login_required()
def my_resumes(request):
context = {'resumes': request.user.resume_set.all()}
return render(request, 'resumes/myresumes.html', context)
Now you can do:
{% for resume in resumes %}
Your code to display a resume item here
{% empty %}
<div class="empty-state-box">
<img src="{% static 'resumes/images/resume-empty-icon.png' %}" class="centered">
<p class="empty-state-text"><b>You currently don't have any resumes.</b><br>Create one and
start building your very first resume</p>
</div>
{% endif %}
Note that you can also use the previous syntax, it will only hit the database once:
{% if not resumes %}
<div class="empty-state-box">
<img src="{% static 'resumes/images/resume-empty-icon.png' %}" class="centered">
<p class="empty-state-text"><b>You currently don't have any resumes.</b><br>Create one and
start building your very first resume</p>
</div>
{% else %}
<p>More information here</p>
{% for resume in resumes %}
Your code to display a resume item
{% endfor %}
{% endif %}
You need to rename the backwards relationship on your resume class so you can access it using {{ user.resume }}.
By default the ForeignKey relationship you've defined from the resume to the user is accessible using user.resume_set. See the docs for more detail.
I'm guessing that you only want to have a single resume per user, so you'll probably want to use a OneToOneField instead of a ForeignKey.
class Resume(models.Model):
name = models.CharField(max_length=255, blank=True)
created_at = models.DateTimeField(auto_now_add=True, editable=False)
updated_at = models.DateTimeField(auto_now=True)
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name="resume")
def __str__(self):
return self.name
Additionally, your if appears to be round the wrong way, given you probably want the form to appear when a resume doesn't exist.
{% if user.resume.exists %}
<p>More information here</p>
{% else %}
<div class="empty-state-box">
<img src="{% static 'resumes/images/resume-empty-icon.png' %}" class="centered">
<p class="empty-state-text"><b>You currently don't have any resumes.</b><br>Create one and
start building your very first resume</p>
</div>
{% endif %}