first_name in django model - django

how can I access to first_name of a user in django template?. for example my writer in django model is like this below :
writer = models.ForeignKey(User, on_delete=models.CASCADE)

If User is the Django default user model, it's simply
writer.first_name
-- e.g. if your example is in a post model you're rendering,
{{ post.writer.first_name }}
in a template.

I have somewhat of a similar setup and this works for me:
models.py
class Customers(models.Model):
name = models.CharField(("Customer name"), max_length=200)
class Licenses(models.Model):
customer = models.ForeignKey(Customers, on_delete=models.CASCADE)
views.py
def licenses (request):
lic = Licenses.objects.all()
return render(request, 'licenses.html',{'lic': lic})
licenses.html
{% for license in lic %}
{{ license.customer.name }}
{% endfor %}

Related

How to access 'related_name' of a model via intermediate model's Foreign key inside template tag?

models.py
class Book(models.Model):
title = models.CharField(max_length=100)
author = models.ForeignKey(User, on_delete=models.CASCADE)
active = models.BooleanField(default=True)
...
class Review(models.Model):
paper = models.ForeignKey(Book, null=True, on_delete=models.CASCADE, related_name='book_class_related_name')
user = models.ForeignKey(User, on_delete=models.CASCADE)
comment = RichTextField()
status = models.CharField(max_length=10, choices=options, default='draft')
...
class TrackReviewRequests(models.Model):
paperid = models.ForeignKey(Book, null=True, on_delete=models.CASCADE, related_name='book_track')
numberOfTimesReviewRequestSent = models.PositiveSmallIntegerField(default=0)
...
views.py
reviews_in_draft = Review.objects.filter(paper__active=True).filter(status='draft')
return render(request,
'accounts/profile.html',
{
'reviews_in_draft': reviews_in_draft,
})
profile.html
Here I tried accessing the 'numberOfTimesReviewRequestSent' using the following code:
{% for review in reviews_in_draft %}
{{ review.paper.book_track.numberOfTimesReviewRequestSent }}
{% endfor %}
But I am getting empty string.
Then I wrote a method inside the Book model
def get_TrackReviewRequests_numberOfTimesReviewRequestSent(self):
return self.book_track.numberOfTimesReviewRequestSent
and tried accessing the numberOfTimesReviewRequestSent in the profile.html using the following code:
{{ review.paper.get_TrackReviewRequests_numberOfTimesReviewRequestSent }}
But this time I got the error stating
'RelatedManager' object has no attribute 'numberOfTimesReviewRequestSent'
Ultimately, I want to access the numberOfTimesReviewRequestSent in the template using the context variable.
A Bookcan have multiple TrackReviewRequests (Since TrackReviewRequests has a foreign key to Book, if in reality there can only be one then you should use a OneToOneField [Django docs] instead) hence review.paper.book_track is not an instance of TrackReviewRequests but as the error says a RelatedManager.
Hence when you write review.paper.book_track.numberOfTimesReviewRequestSent it doesn't make much sense. You can instead loop over the related instances if you want in the template like so:
{% for review in reviews_in_draft %}
{% for review_request in review.paper.book_track.all %}
{{ review_request.numberOfTimesReviewRequestSent }}
{% endfor %}
{% endfor %}

How to display A only a users entered data related in a foreignkey on detailview in django

I am building this simple quiz app. This app allows all users to submit an answer to an assignment in Docx format. I what that any time a user views the question on the DetailView page, if the user has already submitted a solution for that assignment, that solution should be shown on the DetailView page as well. Current I get is all that answers submitted by all users. I only want a user's answer to that assignment on the detailpage
this is my model.
class Assignment(models.Model):
title = models.CharField(max_length=120)
slug = models.SlugField(max_length=500)
course = models.ForeignKey(Course, on_delete=models.CASCADE)
class_or_level = models.ForeignKey(StudentClass, on_delete=models.CASCADE)
teacher = models.ForeignKey(Teacher, on_delete=models.CASCADE)
Text = models.TextField()
date_added = models.DateTimeField(auto_now_add=True)
date_expire = models.DateTimeField()
def __str__(self):
return self.title
class Answer(models.Model):
slug = models.SlugField(max_length=500)
assignment = models.ForeignKey(Assignment, on_delete=models.CASCADE)
student = models.ForeignKey(User, on_delete=models.CASCADE)
file = models.FileField(upload_to='assignment')
date_added = models.DateTimeField(auto_now_add=True)
def __str__(self):
return '{} - {} '.format(self.assignment, self.student)
Below is my view
class AssignmentSubmitView(DetailView):
model = Assignment
template_name = 'assignment_submit.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['student_answer'] = self.object.answer_set.all()
return context
Below is my filter on detailview template.
{% for answer in student_answer %}
{{ answer.file }}
{% endfor %}
You will need to first of all know the user that is accessing that page, so i presume you have a user model and an authentication system in place.
in the views
class AssignmentSubmitView(DetailView):
model = Assignment
template_name = 'assignment_submit.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['student_answer'] = self.object.answer_set.filter()#then filter and get the answer specific to that user here (depending on your user and Assignment models)
return context
and in your templates
{% if user.is_authenticated %}
{% if student_answer %}
{% for answer in student_answer %}
{{ answer.file }}
{% endfor %}
{% endif %}
{% endif %}

How to access extended User attributes in django template

I am trying to access extended field of User model in Django template but it doesn't work, there are my files:
models.py:
class Author(models.Model):
user = models.OneToOneField(User, related_name='user', on_delete=models.SET_NULL, null=True)
bio = models.TextField(
max_length=1400, help_text="Enter author biography.")
def __str__(self):
return self.user.username
def create_profile(sender, **kwargs):
user = kwargs["instance"]
if kwargs["created"]:
user_profile = Author(user=user, bio='my bio')
user_profile.save()
post_save.connect(create_profile, sender=User)
template:
{% extends "base_generic.html" %}
{% block title %}
<title>Author {{user}}</title>
{% endblock %}
{% block content %}
<h1>{{user}}</h1>
<h2>Bio:</h2>
<p>{{user.author.bio}}</p>
<div>
{%for item in user.author.blogs_set.all%}
<p>{{item.title}}</p>
<hr>
{%endfor%}
</div>
{% endblock %}
views:
class UserDetailView(generic.DetailView):
model = User
template_name = 'blogapp/user_detail.html'
I want to get access to the bio field through user.author.bio but nothing displays I have also tried user.bio is there any tricky way to get access to this field?
You set the related_name to:
class Author(models.Model):
user = models.OneToOneField(
User,
related_name='user',
on_delete=models.SET_NULL, null=True
)
But the related_name is the name to access the related Author from a User object (so the name of the relation in reverse). You thus should set it to author (or leave it blank), like:
class Author(models.Model):
user = models.OneToOneField(
User,
related_name='author',
on_delete=models.SET_NULL, null=True
)
By setting it to user, you could have accessed the Author object with user.user, but I strongly advise not to do this, since in the end, it will only result in code that is hard to understand. For Django it of course does not matter (given no two relations originating from User have the same name), but for programmers, it gives a wrong impression.

django: How can i get multiple instances of model Userinfo when each instance of Userinfo has multiple instances in Education model

I have two models that I am working with. First one is a education model in which one user can enter multiple educational qualifications instances:
class Education(models.Model):
user = models.ForeignKey(User,on_delete=models.CASCADE)
degree_name = models.CharField(max_length=150,null=True,blank=True)
institute_name = models.CharField(max_length=150, null=True, blank=True)
date_start = models.CharField(null=True,blank=True,max_length=25)
date_end = models.CharField(null=True,blank=True,max_length=25)
description = models.TextField(null=True,blank=True,max_length=1000)
Second Model is the 'User info' model in which one user can have maximum one instance:
class Userinfo(models.Model):
user = models.ForeignKey(User,on_delete=models.CASCADE)
user_info = models.ForeignKey(User_info,related_name='user_info',on_delete=models.CASCADE,null=True)
profile_pic = models.FileField(null=True,blank=True)
dob = models.CharField(max_length=25,null=True,blank=True)
nationality = models.CharField(max_length=100, null=True, blank=True)
headline = models.CharField(max_length=160, null=True,blank=True)
summary = models.TextField(max_length=1000, null=True, blank=True)
current_salary = models.FloatField(null=True,blank=True)
japanese_level = models.CharField(max_length=50, null=True, blank=True)
english_level = models.CharField(max_length=50, null=True, blank=True)
career_level = models.CharField(max_length=50,null=True,blank=True)
availability = models.CharField(max_length=50, null=True, blank=True)
expected_salary = models.FloatField(null=True, blank=True)
job_role = models.CharField(max_length=50,null=True)
When I use any query to get any instance of 'User info' like:
Userinfo.objects.filter(user=request.user)
How can i related both models so that when looping through Userinfo, I should be able to get multiple instances of it in Education model. How should I change my models and query them ?
I see that you already have a foreign key to the User model inside your Education model. There is no need for a foreign key in the UserInfo Model. You can fetch all the Education instances for a given user just by making an extra call:
Education.objects.filter(user=request.user)
or you can change request.user to the actual user that you need to get.
EDIT:
without making any changes to your code, you can get the multiple instances in the following way:
example views.py
def myView(request):
user_info = Userinfo.objects.get(user=request.user) #using get since only 1 instance always
educations = Education.objects.filter(user=request.user) #fetching all the instances for the education
context_dict = {"user_info": user_info}
educations_list = []
for e in educations:
educations_list.append(e)
# do whatever you need with the educations
# you can access user_info fields just by `user_info.field_name`
# and you can access the current education fields by `e.field_name`
context_dict["educations"] = educations_list
return render(request, "template.html", context_dict)
example usage in template.html
{% if user_info %}
<p>{{ user_info.field_name }}</p>
{% if educations %}
{% for e in educations %}
<div>{{ e.field_name }}</div>
{% endfor %}
{% endif %}
{% endif %}
EDIT 2 (including multiple userinfo instances)
views.py
def myView(request):
user_infos = Userinfo.objects.filter() # fetch all instances
context_dict = {}
result = []
for u in user_infos:
temp = []
educations_list = []
educations = Education.objects.filter(user=u.user) # fetch educations for the currently iterated user from user_infos
for e in educations:
educations_list.append(e)
temp.append(u) # append the current user_info
temp.append(educations_list) # append the corresponding educations
result.append(temp)
context_dict["result"] = result
return render(request, "template.html", context)
template.html
{% if result %}
{% for r in result %}
<div>{{ r.0 }}</div> <!-- r.0 is your currently iterated user_info can be used like: r.0.profile_pic for example -->
{% if r.1 %}
{% for e in r.1 %}
<div>e.degree_name</div> <!-- e is the current education on the current user_info -->
{% endfor %}
{% endif %}
{% endfor %}
{% endif %}
the code in the views.py is not perfect and might be worth to refactor a bit (how to build the final dictionary), but i believe this will give you an idea of how to do it.
Hope this helps!
ui = Userinfo.objects.filter(user=request.user)
this query will give you all the instances of Userinfo for request.user. you can access the value of Education attributes with looping like this:
for u in ui:
ui.education.degree_name
# and so on for other fields.
I think maybe your UserInfo model can have a OneToOne relationsship with user and then do something like
UserInfo.objects.filter(user=request.user).education_set.all()
Hope this helps.
Good luck!

How to check if a relationship exists in a Django template?

I have a Django project where a user can re post other users posts by creating a relationship between the user and the post itself. But when I display this on my template, I want the tweets that have been re posted to have a different link next to them in order to un repost but instead with my current set up it still has the re post link, so I was just wondering how I could see if a relationship exists in a Django template as part of my conditional.
template
{% for tweets in combined_tweets %}
<p>{{ tweets.userprofile.user}} | {{ tweets }} | {{ tweets.date }} |
{% if tweets.userprofile.user == request.user %}
<a href='{% url "delete_tweet" request.user.id tweets.id %}'>DELETE</a>
{% elif ###Something to check if realtionship exists### %}
UN REPOST LINK
{% else %}
<a href='{% url "retweet" tweets.id %}'>RETWEET</a>
{% endif %}</p>
{% endfor %}
models.py
class UserProfile(models.Model):
user = models.OneToOneField(User)
bio = models.CharField(max_length=120, blank=True, verbose_name='Biography')
follows = models.ManyToManyField('self', related_name='followers', symmetrical=False, blank=True)
theme = models.ImageField(upload_to=get_image_path, blank=True)
profile_picture = models.ImageField(upload_to=get_image_path, blank=True)
def __str__(self):
return self.bio
class Tweet(models.Model):
userprofile = models.ForeignKey(UserProfile)
retweet = models.ManyToManyField(UserProfile, related_name='retweet_people', symmetrical=False, blank=True)
tweets = models.TextField(max_length=120)
date = models.DateTimeField()
You can check that a relationship exists between the current user and other user tweets using a custom template filter.
We will write a custom template filter check_relationship_exists which will take the current user as the argument. This will check if the current tweet object is related to the user passed by performing a filter on its retweet attribute using user.id. If there exists a relationship, then the UN REPOST link will be displayed otherwise a RETWEET link will be shown.
from django import template
register = template.Library()
#register.filter(name='check_relationship_exists')
def check_relationship_exists(tweet_object, user):
user_id = int(user.id) # get the user id
return tweet_object.retweet.filter(id=user_id).exists() # check if relationship exists
Then in your template, you can do the following:
{% elif tweets|check_relationship_exists:request.user %}