Django Check for user in list - python

I'm creating a django blog app where users can add comments to articles.
I want to remove the post button when the user has already commented.
I have a model named article and another one named comment (with ForeignKey to article)
I tried {% if any request.user in article.comment_set.all} but that doesn't work. I tried to loop over article.comment_set.all but that didn't work either.
Is there a method to do this in the template?

Rather than doing that in template, why don't you do that in view and send it via context. For example:
def view(request):
...
user_exists = article.comment_set.filter(user=request.user).exists()
context = {}
context['user_exists'] = user_exists
return render(request, 'template.html', context)
in template:
{% if user_exists %}
// do something
{% else %}
// do something else
{% endif %}

Related

ManyToMany fields are not showing in if statement in template

I am building a BlogApp and I am stuck on a Problem.
What i am trying to do :-
I am trying to use if statement in template of two many fields BUT if statement is not working correctly.
models.py
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE,default='',unique=True)
friends = models.ManyToManyField("Profile",blank=True)
class Post(models.Model):
post_owner = models.ForeignKey(User,default='',null=True,on_delete = models.CASCADE)
viewers = models.ManyToManyField(settings.AUTH_USER_MODEL,related_name='viewed_posts',editable=False)
views.py
def detail_view(request,pk,slug):
post = get_object_or_404(Post,pk=pk)
friend = request.user.profile.friends.all()
saw = post.viewers.all()
context = {'friend':friend,'saw':saw}
template.html
{% if request.user.profile.friends.all in post.viewers.all %}
"SHOWING SOME TEXT"
{% endif %}
I am trying to show if request.user friends are in post viewers then show some text.
When i print {{ request.user.profile.friends.all }} it show friends of request.user, It works correctly.
AND when i print {{ post.viewers.all }} then it correctly shows the post viewers (users).
When i try to print some text after combine both in if statement then it doesn't showing anything.
I have no idea where is the Mistake.
Any help would be Appreciated.
Thank You in Advance.
You can filter in the view:
def detail_view(request,pk,slug):
post = get_object_or_404(Post,pk=pk)
friend = request.user.profile.friends.all()
saw = post.viewers.all()
seen_friends = post.viewers.filter(
id__in=friend.values_list("user_id")
).exists()
context = {
'friend':friend,'saw':saw,
'seen_friends':seen_friends
}
in template.html:
{% if seen_friends %}
"SHOWING SOME TEXT"
{% endif %}
The problem is in this line
{% if request.user.profile.friends.all in post.viewers.all %}
Update:
The template has an access to request.user object, but not to the profile object. You are trying to apply Django ORM methods in the template, it is not going to work.
def detail_view(request,pk,slug):
# some code
profile = Profile.objects.get(user=request.user)
context = {'profile':profile}
# more code
return render(request, template_file, context)

How to pass list of Django form field names to template?

I have a very basic form:
class NavigationForm(forms.Form):
NavSelection1 = forms.TextInput()
In my view I want to pass a list to the template:
form = NavigationForm()
context['formfields'] = [i for i in form.fields]
return render(request, "page.html", context)
I am hoping to be able to use:
{% for i in formfields %}
{{i}}
{% endfor %}
But it returns nothing.
{{formfields}}
Alone returns an empty list
[]
I feel like I'm missing something simple but I'm stumped at the moment. Any help would be appreciated!
I've been doing forms like this
form = NavigationForm()
context['form'] = form
return render(request, "page.html", context)
Then in your template
{{form}}
Or maybe you want to do this
{% for field in form %}
{{field}}
{% endfor %}
Hope this answers your question
For some reason the form didn't like TextInput()
I changed it to CharField() and it passes all the form information I was expecting.

how to use django model object in django templates?

I am not able to use the Django model object in Django templates. I want to iterate using the model user in the template and then play with the ActivityPeriod(model) of that user. Please check my code for the clarity:
Here is my code:
views.py
from .models import User,ActivityPeriod
def call_response(request):
user = User.objects.all()
return render(request, "Test/list.html", {"users":user ,"activityperiod":ActivityPeriod})
Test/list.html
{% for user in users %}
'real_name': {{ user.real_name}}},
'activity_periods': {% with activity=activityperiod.objects.get(id =user) %}
{{ activity.start_time }}
{% endwith %}
{% endfor %}
But i am getting an error:
Could not parse the remainder: '(id' from 'activityperiod.objects.get(id'
What is the correct way? Can anyone please share it with me.
Django template don't understand the filter action of Model. This part shoud be in view.
activity=activityperiod.objects.get(id =user)
You should prepare your data and manipulate them before sending to template (a dictionary may help you). And remember that result of action "User.objects.all()" is a list.
views.py
def call_response(request):
user = User.objects.filter(user=request.user)
activityperiod = activityperiod.objects.get(user=user)
context={'user':user,'activityperiod':activityperiod}
return render(request, "Test/list.html",context})
Test/list.html
'real_name': {{ user.real_name}}
'activity_periods':{{ activityperiod.start_time }}
Your question suggests that you think you can a function in the templates like a normal function (ie activityperiod.objects.get(...)).
You can't, the templating system is not made like this (for security reasons amongst others).
You should do something like, in your models:
def call_response(request):
# ! first() not "all()" (if > 1 user, you'll have problem)!
user = User.objects.first()
activityperiod = activityperiod.objects.get(user=user)
return render(request, "Test/list.html",
{"users":user ,"activityperiod":activityperiod})

Return usernames mentioned in post as profile links to those users inside the post

Hey guys I'm trying to get my code to check for a user mentioned in a post with #username that is in the database and return that users profile link as the #username. I am currently able to get the users in the backend with the tagged_users variable in my views. It store the users mentioned but how do I access that in the template so that it gives me the link to those users profiles? so far my code is this in the template
{% if post.post|slice:":1" == '#' %}
<a href="{% url 'profile_with_pk' pk=user.username %}">
{{ post.post }}
</a>
{% else %}
{{ post.post }}
{% endif %}
this returns the entire post as a link but does not return the actual user mentioned in the post instead it makes a link to the current user logged in
This is my code that brings back the users mentioned in the tagged_users list correctly I want to access this in the template as a link to those users profiles in the post.
def post(self, request, pk=None):
if pk:
user = User.objects.get(pk=pk)
else:
user = request.user
form = HomeForm(request.POST)
users = User.objects.all()
if form.is_valid():
post = form.save(commit=False)
post.user = request.user
post.save()
tagUsers = re.findall(r"#+(\w+)", post.post)
tagged_users = list()
for username in tagUsers:
user = User.objects.get(username=username)
tagged_users.append(user)
print(tagged_users)
text = form.cleaned_data['post']
form = HomeForm()
tag = tagged_users
return redirect('home')
context = {'form': form, 'text': text, 'users':users, 'user': user, 'tag':tag, 'tagUsers':tagUsers }
return render(request, self.template_name, context)
There are multiple problems. Let's start from this one:
<a href="{% url 'profile_with_pk' pk=user.username %}">
{{ post.post }}
</a>
The whole post is wrapped in the link. I think you want to make a link to the post author, right? Then (with only guessing your model schema that you didn't posted), you need something like this:
# iteration through posts somewhere here
user.username
{{ post.post }}
Next, is that if you have tagged users, you need to somehow put them into the template in your posts. Depending on how you wish to put a link to mentionned users this may be something like:
# iteration through posts somewhere here
user.username
{{ post.post }}
Mentions: {% for tagged_user in tagUsers %} {{ tagged_user.username }} {% endfor %}
Or maybe you want to insert links directly inside post text? Then you need to construct a post structure before passing it to template (example snipped; will rather need improvements):
from django.utils.html import mark_safe
def post(self, request, pk=None):
...
post_text = post.post
tagUsers = re.findall(r"#+(\w+)", post.post)
tagged_users = list()
for username in tagUsers:
user = User.objects.get(username=username)
for match in re.finditer(username, post_text):
start = match.start()
end = match.end()
profile_link = reverse('profile_with_pk', kwargs={'pk': user.id})
post_text[start:end] = mark_safe(f'username')
...
# return post_text to template context and use in the same way as used post

Django - Show/hide urls in base html dependant on user group?

I want to try and show or hide urls in my navigation page based on user group.
currently i am adding to the top of every view and sending through a value to the template and checking against that, but this doesnt seem too efficient, also if a view does not require auth and that value is not set, will that break the template?
is there a better way to do this?
like a global.py where i could check and set then use it in any template? or something completely different altogether?
view.py
Authorised_user = ''
if request.user.is_authenticated():
Authorised_user = 'IT'
#login_required
def index(request):
return render(request, 'service/index.html', {
'Authorised': Authorised_user,
})
template.html
{% if Authorised == 'IT' or Authorised =='Netwworks' %}
Link
{% endif %}
i do have the user groups in django admin
Based on Get user group in a template
Create user_tags.py / group_tags.py at an appropriate place. e.g. auth_extra/templatetags/user_tags.py
from django import template
register = template.Library()
#register.filter('in_group')
def in_group(user, group_name):
return user.groups.filter(name=group_name).exists()
Then in your template:
{% load user_tags %}
{% if request.user|in_group:"IT"%}
IT only link
{% endif %}
{% if request.user|in_group:"Netwworks"%}
Netwworks only link
{% endif %}
Easiest way around this for me was https://stackoverflow.com/a/17087532/8326187.
Here you don't have to create a custom template tag.
{% if request.user.groups.all.0.name == "groupname" %}
...
{% endif %}
You need to create context_processors.py and create a function say
def foo():
Authorised_user = ''
if request.user.is_authenticated():
Authorised_user = 'IT'
Then in setttings
TEMPLATE_CONTEXT_PROCESSORS = ("path_to_context_processor.foo")
this way you can use foo variable in all the templates without explicitly defining in all the views.
You can also have a look here:https://rubayeet.wordpress.com/2009/10/31/django-how-to-make-a-variable-available-in-all-templates/

Categories