I'm a beginner and trying to make a to-do list app. I want the app to display only the tasks that have not yet been marked completed (by the user).
models.py:
class Task(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
title = models.CharField(max_length=50)
description = models.TextField(blank=True, null=True)
start_date = models.DateTimeField()
end_date = models.DateTimeField()
priority = models.BooleanField(default=True)
completed = models.BooleanField(default=False)
def __str__(self):
return self.title
View:
def task(request):
task = Task.objects.filter(user=request.user, completed=False)
queryset = task.order_by('-start_date')
context = {
'task': queryset,
}
return render(request, 'task-list.html', context)
template:
{% if request.user.is_authenticated %}
<h2>Here is the list of tasks you gotta get done:</h2>
{% if task %}
<ul>
{% for obj in task %}
<li><strong>{{ obj.title }}</strong></li>
<p>{{ obj.description }}</p>
<p>
Start at: {{ obj.start_date }}
</p>
<p>
end at: {{ obj.end_date }}
</p>
{% endfor %}
</ul>
{% else %}
<p>You dont have anything on this list yet!</p>
{% endif %}
{% else %}
<p>Hey! Please login to check your to-do list! click here!</p>
{% endif %}
I want to display an option (a link/button) for the user, which upon clicking would update the instance 'completed' to True (and so the task will no longer be displayed). I would like to use an achor tag as the button. something like
completed
I have created this view:
def task_completed(request, id):
get_task = Task.objects.filter(id=id)
get_task.instance.completed = True
return redirect('task:task-page')
The urls.py:
urlpatterns = [
path('', home, name='home-page'),
path('task', task, name='task-page'),
path('complete', task_completed, name='complete'),
]
upon loading the task-list page, it shows
Reverse for 'complete' not found. 'complete' is not a valid view function or pattern name.
any help would be appreciated!
Please try to set your url as below...
completed
And your url should be...
path('complete/<int:id>', task_completed, name='complete'),
Related
I'm a newbie to Django, trying to build site to allow people to register for football matches.
At the moment, a user can register multiple times for the same match, which is obviously not ideal! Is there a way that I can identify if the currently logged in user has already registered, and then replace the register button with a message telling them that they have already registered? I guess I need some kind of Boolean value in my EventDetail view, and then I can make a conditional statement in the template, but I'm unsure as to how to implement this. I hope this question is clear, it's my very first post!
views.py:
class EventDetail(View):
def get(self, request, id, *args, **kwargs):
event = get_object_or_404(Event, pk=id)
registrations = Registration.objects.filter(event=event)
total_participants = 0
for person in registrations:
total_participants += 1
if person.guest:
total_participants += 1
remaining_spaces = event.max_participants - total_participants
template = "event_detail.html"
context = {
"event": event,
"total_participants": total_participants,
"registrations": registrations,
"remaining_spaces": remaining_spaces,
}
return render(request, template, context)
template
{% extends "base.html" %}
{% block content %}
<p>{{ event.title }}</p>
<p>{{ total_participants }} / {{ event.max_participants }} ({{ remaining_spaces }} spot{{ remaining_spaces|pluralize }}
remaining!)</p>
{% if total_participants < event.max_participants %}
Register
{% else %}
<p>This event has filled up.</p>
{% endif %}
<h2>Current Participants</h2>
<ul>
{% for person in registrations %}
<li>
{{ person.name }}
{% if person.guest %}
+1
{% endif %}
</li>
{% endfor %}
</ul>
{% endblock %}
models.py
from django.db import models
from django.contrib.auth.models import User
class Event(models.Model):
title = models.CharField(max_length=100)
created_by = models.ForeignKey(User, on_delete=models.CASCADE, related_name="event_posts")
event_date_and_time = models.DateTimeField()
venue = models.CharField(max_length=100)
max_participants = models.IntegerField()
extra_info = models.TextField(blank=True)
updated_on = models.DateTimeField(auto_now=True)
class Meta:
ordering = ['event_date_and_time']
def __str__(self):
return self.title
class Registration(models.Model):
event = models.ForeignKey(Event, on_delete=models.CASCADE, related_name="event_registration")
name = models.ForeignKey(User, on_delete=models.CASCADE)
ball = models.BooleanField(default=False)
bibs = models.BooleanField(default=False)
guest = models.BooleanField(default=False)
def __str__(self):
return str(self.name)
I'm a newbie at extracting values from the DB via views and templates but all of my attempts have failed so far. I've been looking at this for several hours now.
I have the below model in my users app at models.py. This is an additional model to the "main one" with the regular name, email and password for my users.
class WorkEmail(models.Model):
user = models.ForeignKey(CustomUser, on_delete=models.CASCADE, null=True)
work_email = models.EmailField(unique=False, null=True, blank=True)
work_email_verified = models.BooleanField(default=False)
work_email_active = models.BooleanField(default=False)
verified_company_name = models.CharField(max_length=100, null=True, blank=True)
company_url = models.URLField(max_length=100, null=True, blank=True)
request_datetime = models.DateTimeField(blank=True, null=True, auto_now_add=True, auto_now=False)
def __str__(self):
return self.work_email
I have this UpdateView in views.py that works perfectly (with the exception of being able to see whether the work email has been verified or not, i.e. from the line with work_is_verified, till the end.
class UpdateProfileView(UpdateView):
form_class = CustomUserChangeForm
success_url = reverse_lazy('home')
template_name = 'update_profile.html'
def get_object(self, queryset=None):
return self.request.user
def work_is_verified(self, request):
if request.work_email_verified==True and request.work_email_active==True:
return True
else:
return False
And I have the below, in my update profile template at update_profile.html
{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% block title %}Home{% endblock title %}
{% block content %}
{% if user.is_authenticated %}
<h2>Profile</h2>
<form method="post">
{% csrf_token %}
{{ form|crispy }}
<button class="btn btn-success" type="submit">Update</button>
</form>
<h2>Verification </h2>
<p> {{user.work_is_verified}} </p>
{% if user.work_is_verified == True %}
Delete Work Email and Verified Company Name
{% else %}
Verify Company Name via Work Email
{% endif %}
<p></p>
{% else %}
<p>You are not logged in</p>
Log In |
Sign Up
{% endif %}
{% endblock content %}
Template works and I'm able to change the values of my main form (customuserchangeform) BUT that method that I created in my view to check if the email is verified and active for a user is not doing anything... (not even showing up).
I want to be able to make a logic that gives either a True or a False whenever we're checking that a user's records in that table show the email being both, verified and active. I should say that this model/table could have many rows for the same user, but the way we can identify the most up-to-date work email is by filtering by both, work_email_active and work_email_verified.
{{user.work_is_verified}}
{% if user.work_is_verified == True %}
Thanks so much in advance.
Try this
For email in request.user.workmail_set:
if email.workmail.work_email_verified and email.workmail.work_email_active:
return True
else:
return False
I have multiple users in my project
my models.py file is
class User(AbstractUser):
is_student = models.BooleanField(default=False)
is_teacher = models.BooleanField(default=False)
class Teacher(models.Model):
user = models.OneToOneField(User,on_delete=models.CASCADE,primary_key=True,related_name='Teacher')
name = models.CharField(max_length=250)
subject_name = models.CharField(max_length=250)
email = models.EmailField(max_length=254)
phone = models.IntegerField()
teacher_profile_pic = models.ImageField(upload_to="classroom/teacher_profile_pic",blank=True)
def __str__(self):
return self.name
class Announcement(models.Model):
title = models.CharField(max_length=30)
content = models.TextField()
date_posted = models.DateTimeField(default=timezone.now)
teacher = models.ForeignKey(Teacher, on_delete=models.CASCADE)
def __str__(self):
return self.title
If the logged in user is a teacher it is allowed to create an announcement
Now i want that only the teacher who posted the announcement should be able to see the delete button
My html file is
{% extends "classroom/base.html" %}
{% block content %}
<h1>Announcements</h1>
{% for announcement in announcements %}
<!-- starting loop (posts is keyword from view) -->
<div style="border-style: solid;">
{% if object.teacher.id == request.teacher %}
<div>
Delete
</div>
{% endif %}
<a class="mr-2">Posted by: {{ announcement.teacher }}</a>
<h2><a class="article-title">{{ announcement.title }}</a></h2>
<p class="article-content">{{ announcement.content}}</p>
</div>
{% endfor %}
{% endblock content %}
the if statement is supposed to be true if logged in teacher is the teacher who originally posted it. However the delete button is visible for every announcement
my views.py has
class AnnouncementListView(ListView):
context = {
'announcements' : Announcement.objects.all()
}
model = Announcement
template_name = 'classroom/all_announcements.html'
context_object_name = 'announcements'
Try using this.
{% if announcement.teacher.user == request.user %}
<div>
Delete
</div>
{% endif %}
Your models are a bit "unconventional".
However, this should work:
{% if announcement.teacher.user == request.user %}
...
{% endif %}
I have in my models Projects and Tasks. I'd like to display on the template:
Project 1
Task 1:1
Task 1:2
Task 1:n
Project 2
Task 2:1
Task 2:n
Project n
Here's the model
class Projects(models.Model):
slug_project = models.CharField(max_length=200)
project_name = models.CharField(max_length=200)
project_due_date = models.DateTimeField()
project_lead_time = models.IntegerField()
project_assignee = models.CharField(max_length=200)
project_status = models.CharField(max_length=200)
def __str__(self):
return self.project_name
class Tasks(models.Model):
slug_task = models.CharField(max_length=200)
task_name = models.CharField(max_length=200)
task_desc = models.TextField(null=True)
task_channel = models.CharField(max_length=200)
task_id = models.ForeignKey(Projects, on_delete=models.CASCADE)
task_due_date = models.DateTimeField('Due Date')
task_lead_time = models.IntegerField()
task_assignee = models.CharField(max_length=200)
def __str__(self):
return self.task_name
I'm not sure how to construct the view properly but here's my code:
class somePage(generic.ListView):
template_name = 'dashboard/index.html'
context_object_name = 'project_object'
def get_queryset(self):
"""Return the last five published Coupons."""
return Projects.objects.order_by('project_name')
def get_context_data(self, **kwargs):
context = super(somePage, self).get_context_data(**kwargs)
# context['tasks'] = Tasks.objects.order_by('task_name') #this would display ALL tasks
context.update({
'all_project': Projects.objects.all(),
'all_tasks': Tasks.objects.filter(task__id=self.object),
})
return context
And I'm also not confident how construct the template:
{% if project_object %}
{% for project_name in project_object %}
<div class="card_row_h1">
<a href="{% url 'dashboard:task_list' project_name.id %}">
{{ project_name }}
</a>
</div>
{% if all_tasks %}
{% for task_name in tasks %}
<div class="card_row_h2" style="width: 100%; padding-left: 30px;">
<small>{{ task_name }}</small>
</div>
{% endfor %}
{% else %}
<div class="card_row_h2" style="width: 100%;">
No Tasks for This Project
</div>
{% endif %}
{% endfor %}
The result is that the Projects display correctly, but under each project I get nothing for 'all_tasks' and it displays 'No tasks for this project' or if I use 'tasks' (see commented line in view), it displays all tasks for all the projects over and over.
So there are two questions here:
how do I construct the view, and
how do I construct the template?
I'm a newbie but I've been stuck on this for over a day. Thanks in advance.
Good start! I think you can simplify this a little. You can get the set of tasks for a project using the reverse look up for foreign keys. Without setting the related_name argument in the task models ForeignKey, you can access the tasks associated to a project using some_project.task_set.all(). You can even do this in the template so you dont need to worry about overriding the context data for the view:
views.py
class MainPage(ListView):
template_name = 'dashboard/index.html'
context_object_name = 'projects'
def get_queryset(self):
return Projects.objects.order_by('project_name')
index.html
{% for project in projects %}
<div class="card_row_h1">
<a href="{% url 'dashboard:task_list' project.id %}">
{{ project.project_name }}
</a>
</div>
{% if project.task_set.all %}
{% for task in project.task_set.all %}
<div class="card_row_h2" style="width: 100%; padding-left: 30px;">
<small>{{ task.task_name }}</small>
{% endfor %}
{% else %}
<div class="card_row_h2" style="width: 100%;">
No Tasks for This Project
</div>
{% endif %}
{% endfor %}
If you wanted, in your Tasks model, you could change
task_id = models.ForeignKey(Projects, on_delete=models.CASCADE)
to project = models.ForeignKey(Projects, on_delete=models.CASCADE, related_name="tasks"
This would make the field name a little more intuitive, and also let you access the Tasks for a project just by doing:
my_project_instance.tasks.all()
EDIT: I fixed the views.py with Av4t4r's code but it still shows no content. When I type something in voodoo.html it actually shows content, but all of the content inside the {% block content %} are not showing. Why is that?
Hello I am trying to make a simply gallery app where the first view (listview) is a list of all the persons (which are the objects), and when a user clicks on one it proceeds to the next page with a given pk/id key. But when it comes to that page... the content is blank. Here is what I have:
urls.py:
urlpatterns = [
url(r'^$', ListView.as_view(queryset=Images.objects.all(), template_name='imgboard/home.html')),
url(r'^imgboard/(?P<id>\d+)/$', views.voodoofunction, name='voodoofunction'),
]
views.py (I feel like this is where the problem is):
def voodoofunction(request, id=None):
instance = get_object_or_404(Moreimages, id=id)
context = { "object_list": instance, }
return render(request, "imgboard/voodoo.html", context)
models.py
class Images(models.Model):
name_person = models.CharField(max_length=70)
instagram = models.CharField(max_length=200)
img_url = models.CharField(max_length=500)
def __unicode__(self):
return self.name_person
class Meta:
verbose_name_plural = 'Images'
class Moreimages(models.Model):
key = models.ForeignKey(Images, on_delete=models.CASCADE)
img_url = models.CharField(max_length=500)
def __unicode__(self):
return str(self.key)
class Meta:
verbose_name_plural = "More Images"
listview_code.html
{% block content %}
{% for object in object_list %}
<p>{{object.name_person}}</p>
{% endfor %}
{% endblock %}
voodoo.html:
{% block content %}
<h2>{{ object.name_person}}<br></h2>
<h4>{{object.instagram}}</p></h4>
<br>
{% for object in object_list %}
<p><img src="{{object.img_url}}", width=350, height="360></img>"</p>
{% endfor %}
{% endblock %}
Your context has no "object" in it. And your "object_list" is an instance, not a list (so your for loop is doing nothing).