How to access extended User attributes in django template - django

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.

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

Django model store information for each user

I am building a competition website where challenges will be released weekly. For each user I want to track if they have completed a challenge but cannot see how this would be done. Currently the challenges are stored as a model and am using the ListView and DetailView to display them.
from django.db import models
from django.contrib.auth.models import User
STATUS = (
(0, 'Draft'),
(1, 'Publish'),
)
class Challenge(models.Model):
title = models.CharField(max_length=200, unique=True)
slug = models.SlugField(max_length=200, unique=True)
release_date = models.DateTimeField()
preamble = models.TextField()
ciphertext = models.TextField()
plaintext = models.TextField()
status = models.IntegerField(choices=STATUS, default=0)
class Meta:
ordering = ['-release_date']
def __str__(self):
return self.title
Thank you in advance to anyone who helps me with this. Oh and a solution will be submitted and then checked with this form.
<div class='form'>
{% if user.is_authenticated %}
<textarea rows="10" name="plaintext" form="submitAnswer" wrap="soft" placeholder="Plaintext.."></textarea>
<form method="post" id="submitAnswer">
{% csrf_token %}
<input type="submit" value="Submit">
</form>
{% else %}
<p>Must be logged in to submit answer.</p>
{% endif %}
</div>
A really basic implementation is to add a ManyToManyField between your Challenge model and your the User model :
from django.conf import settings
class Challenge(models.Model):
users = models.ManyToManyField(settings.AUTH_USER_MODEL)
# Other fields...
In the above example, you can just activate the relationship if the user has passed the test.
Now, maybe, you want to add informations about this relationship. You can do it with 'through' argument. This model tells if a user has passed the challenge or not and how many tentatives has been done. Modify it as you wish.
from django.conf import settings
class Challenge(models.Model):
users = models.ManyToManyField(settings.AUTH_USER_MODEL,
through='ChallengeUsers')
# Other fields...
class ChallengeUsers(models.Model):
challenge = models.ForeignKey(Challenge, on_delete=models.CASCADE)
users = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
hasPassed = models.BooleanField(default=False)
tentatives = models.IntegerField()

first_name in django model

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

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

can't use a field of the database in django template

I have a database like this:
from django.db import models
class User(models.Model):
firstName = models.CharField(max_length=30, blank=False, default=None)
lastName = models.CharField(max_length=30, blank=False, default=None)
email = models.EmailField(max_length=100, blank=False, default=None)
password = models.CharField(max_length=100, blank=False, default=None)
score = models.IntegerField(default=0)
in views.py I want to send a user that currently logged in and show its informations from DB at template.
my views.py:
user = User.objects.filter(email=request.POST['email'])
#some code ....
context = RequestContext(request, {
'user': user[0]
})
return HttpResponse(template.render(context))
my template :
{% if user %}
Wellcome {{ user.firstName }}
{% endif %}
but I don't see anything after welcome.also when I use this:
{% if user %}
Wellcome {{ user }}
{% endif %}
I see welcome anonymousUser where I am wrong ?
You cannot use user as the context variable, as it conflicts with the user object that is injected into the context by the processor
django.contrib.auth.context_processors.auth
Now, to fix your issue, rename user to user_obj or something which makes more sense.
Read more here
Based on the behavior you are describing you are likely not getting any objects returned from the call to filter:
user = User.objects.filter(email=request.POST['email'])
I would look at the value that is returned from request.POST['email'] and making sure that value is in your datbase as the starting point.
Also, you should be aware that the filter function returns a QuerySet and not a User object. If you want to retrieve a unique User object you can use the get function instead.