Python - Check if user is in team or not - python

I have a model that stores teams and members. I want to check if a requested user is in this team or not. How do i do that?
Model
class TeamPlayer(models.Model):
team = models.ForeignKey(Team, related_name='players', on_delete=models.CASCADE)
player = models.OneToOneField(User, related_name='player', on_delete=models.CASCADE)
approved = models.BooleanField(default=False)
Template
{% if request.user in object.players.all %}
Leave
{% else %}
Join
{% endif %}
View is just simple DetailView.

If you want to do that in the template, just use the teamplayer_set like this:
{% if request.user in object.teamplayer_set.all %}

You have it 1-on-1, so it should be
players = TeamPlayer.object.all()
if request.user.player in players
# Do what you need to
or in template
{% if request.user.player in players %}
provided players is sent to the template
When it's one-on-one, it's always user.player to get related player and player.user for the related user.

Related

For Loop in Django Template

I am working on a Django project. It has two Apps, one for explaining the topic, which has its own model, and views, and the second app is a quiz app, which has its own model and view, which will test the ability / learning of the students on each topics.
The main idea is that for each topic of each book, there will be a quiz to test the ability of the students.
my book explanation model is as follows:
class book_explination(models.Model):
title = models.CharField (max_length = 255)
slug = models.SlugField(max_length= 250, null = True, blank = True, unique= True)
lesson_no = models.CharField (max_length = 255)
book_text = models.TextField (blank=False, null=False)
book_text_explination = models.TextField (blank=False, null=False)
quiz = models.ForeignKey(Quiz, on_delete=models.CASCADE, null= True, blank=True)
timestamp = models.DateField(auto_now=False, auto_now_add=True)
def __str__(self):
return self.title
my view for the course model is as follows:
def maths_topics(request):
content_list = book_explination.objects.filter(title = "maths")
return render(request, 'blog/maths_topics.html', {'content_list': content_list})
my url on url.py file is as under:
path('nahwa_meer_topics/', maths_topics, name = 'maths_topics'),
my quiz model is as follows:
class Quiz(models.Model):
title = models.CharField(max_length=255)
book_name = models.CharField(max_length=255)
slug = models.SlugField(blank = True)
topic = models.CharField(max_length=255)
number_of_questions = models.IntegerField()
class Meta:
verbose_name_plural = 'Quizes'
def __str__(self):
return self.title
my view for the quiz app is as follows:
def maths_quiz(request):
maths_quiz = Quiz.objects.filter(book__name = "maths")
return render(request, 'blog/maths_topics.html', {'maths_quiz': maths_quiz})
my django HTML template is as under:
{% for c in content_list %}
<ul class="list-group list-group-horizontal">
{% if c.title == "maths" %}
<li> {{ c.title }}</li>
<li> {{ c.lesson_no }}</li>
<li> {{ c.book_text }}</li>
{% endif %}
</ul>
{%endfor%}
{% for c in maths_quiz %}
<ul class="list-group list-group-horizontal">
{% if c.name == "maths" %}
<li> {{ c.topic }}</li>
<li> {{ c.title }}</li>
{% endif %}
</ul>
{% endfor %}
the HTML template is reflecting the maths book explanation, however, it is not showing the quiz part of the data.
My aim is to show the topics of a book in an html page, and in front of each topic there should be the quiz, related to that topic, bearing in mind that each topic will have it own separate quiz.
Thanks for your support and help. Looking forward for a positive response from your end.
Regards
If I understand this correctly, the maths_quiz variable holds a queryset of Quiz instances. In your template logic, you display a list item, if an instance's name attribute is "maths". However your Quiz model has no name field at all. Could it be that you meant to check the book_name attribute instead?
{% for c in maths_quiz %}
<ul class="list-group list-group-horizontal">
{% if c.book_name == "maths" %}
...
{% endif %}
</ul>
{% endfor %}
Additionally, I think you made an error in your query to begin with:
...
maths_quiz = Quiz.objects.filter(book__name = "maths")
There are two underscores in book__name, but your field has only one:
class Quiz(models.Model):
...
book_name = models.CharField(max_length=255)
Moreover, I just noticed that your whole if condition in the template seems to be redundant since you are doing that exact filtering in your query in the view function before passing the results to the template. So there is really no need to check the book_name again in the template. Every instance in that queryset will have book_name == "maths".
Same goes for the maths_topics view.
Finally, I assume that either the HTML is actually two separate templates or if not, that you are aware that only one of the two sections will ever be displayed depending on the view that is called, maths_topics or maths_quiz, not both.
As a side note: I would suggest using more descriptive variable names, if possible. Seeing as you are working with multiple Quiz instances, I would name the variable something like maths_quizzes and for the iteration I would use a name like quiz instead of c:
def maths_quiz(request):
maths_quizzes = Quiz.objects.filter(book__name = "maths")
return render(request, 'blog/maths_topics.html', {'maths_quizzes': maths_quizzes})
{% for quiz in maths_quizzes %}
...
{% endfor %}
EDIT
OK, now that you explained a bit more, it seems you do think that both querysets should appear somehow. You have two separate views. They render separate responses. If you want both querysets passed to your template data, then you should do that in one view:
def maths_view(request):
content_list = book_explination.objects.filter(title = "maths")
maths_quiz = Quiz.objects.filter(book_name = "maths")
return render(
request,
'blog/maths_topics.html',
{'content_list': content_list, 'maths_quiz': maths_quiz}
)
Then obviously you need to adjust your URL route to point to that view, something like this (for example):
path('yoururlpath/', maths_view, name = 'maths_view')
Also, it seems to me that if your two models are so intimately connected, you may want to consider creating some sort of a relationship between them. Namely, if a quiz is always related to exactly one book, this seems to call for a foreign key relationship from quiz to book.
I mean something like this:
class Quiz(models.Model):
book = ForeignKey(to=book_explination, ...)
...
This would allow you to get all the related objects in the same query.
You can read up on relationships in the Django documentation.

How can i write this if statement on my template Django

I would like to write something in the form of an entry to a particular tournament where the user after clicking on the "join" button is moved to a sheet where the user is asked to enter their name and choose which tournament they want to join. Is it possible to write a conditional instruction that checks if the name of a given tournament is equal to the name of the tournament that the user has chosen and using it to list the users assigned to the given tournament.
my views.py file
def content(request, pk):
tournament = Tournament.objects.get(id=pk)
users = TournamentUsers.objects.all()
return render(request, 'ksm_app2/content.html', {'tournament': tournament, 'users': users})
my models.py file
class Tournament(models.Model):
data = models.DateField(null=True)
tournament_name = models.CharField(max_length=256, null=True)
tournament_creator = models.ForeignKey(Judges, on_delete=models.SET_NULL, null=True)
tournament_info = models.TextField(max_length=10000)
def __str__(self):
return self.tournament_name
class TournamentUsers(models.Model):
user_first_name = models.CharField(max_length=256)
user_last_name = models.CharField(max_length=256)
user_tournament = models.ForeignKey(Tournament, on_delete=models.SET_NULL, null=True)
def __str__(self):
return self.user_last_name + ' ' + self.user_first_name
{% for user in users %}
{% if user.user_tournament == tournament.tournament_name %}
<p>{{ user.user_first_name }} {{ user.user_last_name }}</p>
{% else %}
<p>no one takes part in this tournament </p>
{% endif %}
{% endfor %}
if u have any idea what i can do i will appreciate that.
.user_tournament is a Torunament, so you check this with:
{% if user.user_tournament == tournament %}
…
{% endif %}
but filtering in the template is not a good idea. It will make the server unresponsive if the number of users keeps growing. You filter in the view with:
from django.shortcuts import get_object_or_404
def content(request, pk):
tournament = get_object_or_404(Tournament, pk=pk)
users = TournamentUsers.objects.filter(user_tournament=tournament)
return render(request, 'ksm_app2/content.html', {'tournament': tournament, 'users': users})
This will perform the filter on the database, which has index structures to do this efficiently. In that case you no longer filter in the template.
Note: It is often better to use get_object_or_404(…) [Django-doc],
then to use .get(…) [Django-doc] directly. In case the object does not exists,
for example because the user altered the URL themselves, the get_object_or_404(…) will result in returning a HTTP 404 Not Found response, whereas using
.get(…) will result in a HTTP 500 Server Error.

Check if a record from one model exists in a list with records from another model in Django

I have two simple models defined in Django... one contains album names, and another one that links albums and users.
class Album(models.Model):
name = models.CharField(max_length=255)
class UserAlbum
category = models.ForeignKey(Album, on_delete=models.CASCADE)
author = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
)
In my view I get the list of all albums, and I check which albums the user owns:
albums = Album.objects.order_by('name')
my_albums = UserAlbum.objects.filter(user_id=request.user.id)
This all works well. However, I now need to display the list with albums online, and a little icon should appear if a user owns an album. I'm not sure how to do this. This is what I have:
<ul>
{% for info in albums %}
<li>{{ info.name %} {% if SOME_CONDITION %} <span class="owner"></span>{% endif %}</li>
{% endif %}
I am not sure how to formulate SOME_CONDITION. It should basically say: if this album id is also in the my_albums list. But how can I do this?
You don't really need the UserAlbum model, unless you want to attach extra fields to the m2m relation. Instead just use a ManyToManyField.
from django.contrib.auth import get_user_model
User = get_user_model()
class Album(models.Model):
name = models.CharField(max_length=255)
users = models.ManyToManyField(User)
Then you can test for membership in Album().users.all() in your template.
{% for album in albums %}
<li>{{ album.name }}
{% if request.user in album.users.all %}
<span class="owner"></span>
{% endif %}
</li>
{% endfor %}
If you have some plan with the UserAlbum model, you can use it as a intermediate model.
class Album(models.Model):
name = models.CharField(max_length=255)
users = models.ManyToManyField(User, through='UserAlbum')

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 %}

Django Regroup User ForeignKey

I have the following model:
class JobView(models.Model):
job = models.ForeignKey(Job)
user = models.ForeignKey('auth.User')
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
class Meta:
ordering = ['-created']
And in a view i'm grabbing the job info:
model = Job.objects.get(pk=id)
In a template I'm doing the following:
{% regroup model.jobview_set.all by user as user_list %}
{% for u in user_list %}
{{ u.grouper.email }}
{% endfor %}
The problem I'm having is that is not really grouping by the user, or more to the point, randomly grouping them by the user.. Sometimes it display the user twice, sometimes 3 times..Is there something I'm missing?
Cheers!
This is because {% regroup %} does not order its inputs. You're trying to group by user, but model.jobview_set.all is not ordered by user, so you get random groups depending on how user is ordered.
The easiest solution is sort model.jobview_set.all before passing it to the template.
Taken directly from django doc's:
Note that {% regroup %} does not order its input!
https://docs.djangoproject.com/en/1.4/ref/templates/builtins/#regroup

Categories

Resources