Reputation: 911
it's been a few hours since I tried to retrieve a list of users with the information of an intermediate table.
So I have a workspace model that is a manytomanyfield with users
There is also an intermediary table to differentiate the classic users and the workspace manager
I would like to display the list of users and add a small icon symbolizing the managers in the list.
But unfortunately it seems difficult for Django, to display both the list of users of the workspace with the information of the intermediate table.
In any case I look at the documentation of Django I have not managed to find how to do.
models.py
class Workspace(models.Model):
name = models.CharField(max_length=250, verbose_name="Nom du workspace")
members = models.ManyToManyField(User, through='Membership', verbose_name="Membres du workspace")
token = models.CharField(max_length=500) # token statique
join_token = models.CharField(max_length=500) # token dynamique
join_token_date = models.DateTimeField(auto_now_add=False, null=True, blank=True)
payday = models.DateField(max_length=10, verbose_name="Jour de paye", null=True, blank=True)
planning_image = ProcessedImageField(upload_to='planning',
null=True,
blank=True,
processors=[ResizeToFill(1299, 937)],
format='JPEG',
options={'quality': 100})
planning_thumbnail = ImageSpecField(source='planning_image',
processors=[ResizeToFill(280, 202)],
format='JPEG',
options={'quality': 100})
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('create-workspace')
class Membership(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
workspace = models.ForeignKey(Workspace, on_delete=models.CASCADE)
is_manager = models.BooleanField(default=False)
date_joined = models.DateTimeField(auto_now_add=True)
views.py
@login_required
def workspace_detail(request, token):
ins_workspace = get_object_or_404(Workspace, token=token)
list_members = ins_workspace.members.all()
for member in list_members:
if member == request.user:
current_user = Membership.objects.get(workspace=ins_workspace, user=request.user)
context = {
'name': ins_workspace.name,
'token': ins_workspace.token,
'list_members': list_members,
'payday': ins_workspace.payday,
'is_manager': current_user.is_manager,
}
return render(request, 'workspace/workspace_detail.html', context)
else:
return HttpResponseForbidden()
template.html
{% for item in list_members %}
{{ item.username }}
{% endfor %}
This is what I want:
template.html
{% for item in list_members %}
{% item.is_manager %}
{{ item.username }} (♔)
{% else %}
{{ item.username }}
{% endfor %}
Upvotes: 1
Views: 51
Reputation: 51988
You can do it like this:
Update Membership model with related name:
class Membership(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="membership")
workspace = models.ForeignKey(Workspace, on_delete=models.CASCADE)
is_manager = models.BooleanField(default=False)
date_joined = models.DateTimeField(auto_now_add=True)
Then you can update your view like following:
from django.db.models import F
@login_required
def workspace_detail(request, token):
ins_workspace = get_object_or_404(Workspace, token=token)
list_members = ins_workspace.members.all().annotate(is_manager=F('membership__is_manager'))
context = {
'name': ins_workspace.name,
'token': ins_workspace.token,
'list_members': list_members,
'payday': ins_workspace.payday,
'is_manager': request.user.membership.get(workspace=ins_workspace).is_manager,
}
return render(request, 'workspace/workspace_detail.html', context)
That should do the trick.
Here what I have done is that, I am using a reverse relation to get is_manager
value from membership model. I am annotating that value in the queryset using F.
Upvotes: 1