I have a list of users and want to display their tasks only if the selected user belongs to the same department. My Models have a department field that I want to compare.
This is my template code.
{% extends 'view_users.html' %}
{% block view_user_tasks %}
Back
<p> todo lists for {{ user }}</p>
{% for todo in view_user_tasks %}
<a id="{{todo.id}}" class="todo_remove"></a>
{% endfor %}
{% endblock view_user_tasks %}
What i want to do is evaluate this condition:
if request.user.Department == user.Department:
show user tasks
This are my respective views.
class ViewUsers(ListView):
model = CustomUser
template_name = 'view_users.html'
class ViewUserTasks(ListView):
model = Todo
template_name = 'view_user_tasks.html'
context_object_name = 'view_user_tasks'
My models.py
class Todo(models.Model):
title = models.CharField(max_length=30)
body = models.CharField(max_length=255)
created_at = models.DateTimeField(auto_now_add=True, blank=True)
checked = models.BooleanField(default=False)
owner = models.ManyToManyField(CustomUser)
id = HashidAutoField(primary_key=True)
def __str__(self):
return "%s: %s" % (self.title, self.body)
class CustomUser(AbstractUser):
Department = models.CharField(max_length=30, blank=True)
How can I be able to accomplish this?
Do your filtering logic in the view. You can override the default get_queryset method and return only the Todos that you want.
class ViewUserTasks(ListView):
template_name = 'view_user_tasks.html'
context_object_name = 'view_user_tasks'
def get_queryset(self):
return Todo.objects.filter(user__Department=self.request.user.Department)
And then just loop through the returned data like you are already doing.
If I clearly understand your question, you can compare it like this:
{% if todo.user.id == user.id %}
Related
First of all, I'm new to Django or MVC frameworks in general and I've got quite little experience in Python.
I've read stackoverflow threads with similar title, but yet I'm missing some puzzle piece.
After trying for some time, this is what I ended up with... which renders empty list. I think it's due to the fact, that the referred table has no database entries. I can't seem to figure out how to evaluate values based on FK from another table:
models.py
class Employees(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
def __str__(self):
return self.last_name
def get_absolute_url(self):
return reverse('employees')
class Tasks(models.Model):
type = models.CharField(max_length=30)
duration = models.IntegerField()
def __str__(self):
return self.type
def get_absolute_url(self):
return reverse('tasks')
class Records(models.Model):
employee_id = models.ForeignKey(Employees)
task_id = models.ForeignKey(Tasks)
date_from = models.DateTimeField()
date_to = models.DateTimeField()
def __str__(self):
return self.id
def get_absolute_url(self):
return reverse('records')
forms.py
class CreateRecordForm(forms.ModelForm):
employee_id = forms.ModelChoiceField(queryset=Records.objects.all().values('employee_id'))
task_id = forms.ModelChoiceField(queryset=Records.objects.all().values('task_id'))
date_from = forms.DateTimeField() #doesnt matter at the moment
class Meta:
model = Records
fields = ('employee_id', 'task_id', 'date_from')
views.py
class RecordCreateView(CreateView):
form_class = CreateRecordForm
template_name = 'record_new.html'
model = Records
#fields = ['employee_id', 'task_id', 'date_from']
Generic view below renders the drop-down selection correctly, so it is doable.
class RecordCreateView(CreateView):
template_name = 'record_new.html'
model = Records
fields = ['employee_id', 'task_id', 'date_from']
record_new.html
{% extends 'base.html' %}
{% block content %}
<h1>New record</h1>
<form action="" method="post">{% csrf_token %}
{{ form }}
<button class="btn btn-success ml-2" type="submit">save</button>
</form>
{% endblock content %}
Any help is greatly appreciated!
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 %}
Apologies for the unclear title, I'm not sure how to articulate my question in a few words.
Basically, within my view I have a variable containing a list of objects (photos):
photos = Photo.objects.all()
In my template I have a for loop for these objects where I display the attributes (e.g. photo.author ). I would like to have some logic to be run on individual photo instances:
all_likes = Like.objects.all()
for photo in photos:
pic_likes = all_likes.filter(photo_id=id)
like_count = len(pic_likes)
liker = pic_likes.filter(liker_id=request.user.id)
if len(liker) != 0:
liked=True
but using a for loop inside the view causes the error
int() argument must be a string, a bytes-like object or a number, not 'builtin_function_or_method'
How should I go about having logic for the photo instances but not the object list as a whole?
My Photo model is as follows:
class Photo(models.Model):
image = models.ImageField(upload_to='uploaded_images', blank=True)
title = models.CharField(max_length=128)
author = models.ForeignKey(settings.AUTH_USER_MODEL, default = 1)
slug = models.SlugField()
likes = models.ManyToManyField(User, related_name='likes')
description = models.CharField(max_length=1000, blank=True)
and my like model is:
class Like(models.Model):
liker = models.ForeignKey(User, related_name='liker')
photo = models.ForeignKey(Photo, related_name='photo')
liked = models.BooleanField()
I suggest you change the related_name attributes in you Like model, maybe even remove it to use the default names:
class Like(models.Model):
liker = models.ForeignKey(User)
photo = models.ForeignKey(Photo)
liked = models.BooleanField()
Now you can use it like this:
all_likes_of_a_user = user_instance.like_set.all()
all_likes_of_a_photo = photo_instance.like_set.all()
Now, to iterate over the photos in the view, you can use:
for photo in Photo.objects.all():
like_count = photo.like_set.count()
has_liked = photo.like_set.filter(liker=request.user).exists()
And for using that in your templates, you could add a nested loop:
{% for photo in Photo.objects.all %}
Like count: {{ photo.like_set.count }}
Has this user liked this photo:
{% for like in photo.like_set.all %}
{% if like.liker == user %}
yes
{% endif %}
{% endfor %}
{% endfor %}
Or add a method to your Photo model:
class Photo(models.Model):
...
def users_that_liked_it(self):
return [
e.liker.pk
for e in self.like_set.all()]
{% for photo in Photo.objects.all %}
Like count: {{ photo.like_set.count }}
Has this user liked this photo:
{% if user.pk in photo.users_that_liked_it %}
yes
{% else %}
no
{% endif %}
{% endfor %}
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!
Here is the code I've written:
models.py:
class Name_overall(models.Model):
rank = models.IntegerField()
name = models.CharField(max_length=50)
frequency = models.IntegerField()
def __unicode__(self):
return self.name
class Name_state(models.Model):
gender = models.CharField(max_length=1, choices=GENDER_CHOICES)
name_overall = models.ForeignKey(Name_overall, db_column='name')
frequency = models.IntegerField()
rank = models.IntegerField()
state = models.CharField(max_length=2, choices=STATE_CHOICES)
def __unicode__(self):
return self.state
views.py:
def single_name(request, baby_name):
baby_list = get_list_or_404(Name_overall, name=baby_name)
return render_to_response('names/single_name.html', {'baby_list': baby_list})
single_name.html:
{{ baby_list.name_state_set.all }}
Nothing shows up in the single_name.html template. If I change it to {{ baby_list }}, there is an object there, but I am not able to access the Name_state class. I thought I should be able to have access to Name_state because of the foreign key. What am I missing?
The baby_list context variable is a QuerySet. You need to iterate it and access the ForeignKey in the loop.
{% for item in baby_list %}
{{item.name_state_set.all}}
#iterate the name_state_set
{% for obj in item.name_state_set.all %}
{{obj}}
{% endfor %}
{% endfor %}