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
Related
Homefeed is the page where i query all the blogposts
In this project, any user that sees a blogpost that they are interest in can submit their interest to the post. 1 user can only submit 1 interest to that blogpost, but they can submit as many interest as they want to different blogposts.
Right now in my home.html, I am trying to make it such that if YOU have submitted interest,(aka your interest status is at pending or accept or decline) for that particular blog post, you will see the view interest button instead of the submit interest button.
But I am facing a problem because in my views, I am querying for blog_posts = BlogPost.objects.all() and not blog_post = get_object_or_404(BlogPost, slug=slug). As such, how am I able to query whether or not for the particular blogpost, the user has already submitted an interest in my template to determine which button should show in my home.html? Thanks, and also I dont want to change the url at all :)
views.py
def home_feed_view(request, *args, **kwargs):
context = {}
blog_posts = BlogPost.objects.all()
context['blog_posts'] = blog_posts
page = pageFilter(request.GET, queryset=BlogPost.objects.exclude(author_id=request.user.id).order_by('date_updated'))
context['page'] = page
paginated_page = Paginator(page.qs, 4)
page = request.GET.get('page')
page_obj = paginated_page.get_page(page)
context['page_obj'] = page_obj
return render(request, "HomeFeed/snippets/home.html", context)
home.html
{% for post in page_obj %}
{% if post.interest_set.exists and request.user.is_authenticated %}
<a class="btn btn-info btn-sm" href="{% url 'HomeFeed:submitinterest' post.slug %}">View Interest</a>
{% else %}
<a class="btn btn-warning btn-sm" href="{% url 'HomeFeed:submitinterest' post.slug %}">Submit Interest</a>
{% endif %}
{% endfor %}
urls.py
path('', home_feed_view , name= "main"),
models.py
class Account(AbstractBaseUser):
email = models.EmailField(verbose_name="email", max_length=60, unique=True)
username = models.CharField(max_length=30, unique=True)
class BlogPost(models.Model):
title = models.CharField(max_length=50, null=False, blank=False, unique=True)
author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
slug = models.SlugField(blank=True, unique=True)
class Interest(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
blog_post = models.ForeignKey(BlogPost, on_delete=models.CASCADE)
class InterestInvite(models.Model):
ACCEPT = "ACCEPT"
DECLINE = "DECLINE"
PENDING = "PENDING"
STATUS_CHOICES = [
(ACCEPT, "accept"),
(DECLINE, "decline"),
(PENDING, "pending"),
]
interest = models.OneToOneField(Interest, on_delete=models.CASCADE, related_name="interest_invite")
status = models.CharField(max_length=25, choices=STATUS_CHOICES, default=PENDING)
objects= models.Manager
views.py
type = TypeFilter(request.GET, queryset=BlogPost.objects.exclude((Q(author_id__in=request.user.blocked_users.all()) | Q(author = request.user))).order_by('date_updated')).annotate(user_has_interest=Case(When(interest__user=request.user, then=Value(True)), default=False, output_field=BooleanField()))
Using Django filters:
filters.py
class TypeofIdeaFilter(django_filters.FilterSet):
title = django_filters.CharFilter(field_name="title", lookup_expr='icontains')
class Meta:
model = BlogPost
You can annotate a field on your query:
from django.db.models import Case, When, Value, BooleanField
blog_posts = BlogPost.objects.all().annotate(
user_has_interest=Case(When(interest__user=request.user, then=Value(True)), default=False, output_field=BooleanField())
)
Now you can check in your template using if-else:
{% if post.user_has_interest %}
Something
{% else %}
Something else
{% endif %}
As Pierre mentioned template tags also achieve this (alternate for annotate answerd by Abdul).
Firstly create the file structure. Go into the app directory where the tag is needed, and add these files:
templatetags
templatetags/__init__.py
templatetags/blog_tags.py
The templatetags/blog_tags.py file:
from django import template
register = template.Library()
#register.simple_tag
def interest_submitted(blog_id, user_id):
if Interest.objects.filter(blog_post__id=blog_id, user_id=user_id).exists():
return True
else:
return False
In the template:
{% load blog_tags %} <!--don't forget to load the blog_tags.py file in the template. -->
{% for post in page_obj %}
{% interest_submitted post.id request.user.id as result %}
{% if result and request.user.is_authenticated %}
<a class="btn btn-info btn-sm" href="{% url 'HomeFeed:submitinterest' post.slug %}">View Interest</a>
{% else %}
<a class="btn btn-warning btn-sm" href="{% url 'HomeFeed:submitinterest' post.slug %}">Submit Interest</a>
{% endif %}
{% endfor %}
You can use a try instead of get_object_or_404(). That way you can use different logic and return different contexts if the object does not exist
pseudocode:
context = {}
try:
blog_posts = BlogPost.objects.all()
...
context = "Something"
return render(request, "HomeFeed/snippets/home.html", context)
except BlogPost.DoesNotExist:
context = "Something else"
return render(request, "HomeFeed/snippets/home.html", context)
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'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'),
I am trying to create a simple CRUD with ModelForm. It works fine except that every time I edit, saving creates a new instance of the data. So i edit and get an extra row in DB instead of an updated one. I am at a loss as to how it knows to save an existing charity as it does not store the PK (id) as a hidden field in the form. That is how I always did it before trying to use the 'fabulous' ModelForm!
It's driving me nuts, I have read everything and as far as I can tell I am doing everything right.
Here is my code..
Model:
from django.db import models
from django.conf import settings
COUNTRY_CHOICES = settings.COUNTRIES
class Charities(models.Model):
charity_name = models.CharField(max_length=100)
country = models.CharField(max_length=4, choices=COUNTRY_CHOICES)
registration_number = models.CharField(max_length=100)
address1 = models.CharField(max_length=100)
address2 = models.CharField(max_length=100)
city = models.CharField(max_length=30)
zip = models.CharField(max_length=10)
phone = models.CharField(max_length=20)
email = models.EmailField()
charity_logo_image = models.CharField(max_length=100)
charity_banner_image = models.CharField(max_length=100)
charity_accepted = models.IntegerField()
def __str__(self):
return self.charity_name
def __unicode__(self):
self.charity_name
View:
def list(request):
charities = Charities.objects.all()
return render_to_response('charities_charity_list.html', {'charities': charities})
def add(request):
return add_or_edit(request)
def edit(request, charity_id):
return add_or_edit(request, charity_id)
def add_or_edit(request, charity_id=None):
print "ID = " + str(charity_id)
form = CharityForm(request.POST or None,
instance=charity_id and Charities.objects.get(pk=charity_id))
# Save new/edited student
if request.method == 'POST' and form.is_valid():
print form
form.save()
return HttpResponseRedirect('/charities/list/')
return render_to_response('charities_charity_edit.html', {'form': form})
Form:
class CharityForm(ModelForm):
class Meta:
model = Charities
Template:
{% extends "base.html" %}
{% block title %}Charities Add{% endblock %}
{% block content %}
<form method="post" action="/charities/add/" id="save"><table cellpadding="0">{{ form.as_table}}</table><input type="submit" value="Save"></form>
{% endblock %}
It doesn`t work because your template is always POSTing to the view that adds a new Charity. When you manually type a URL like /charities/edit/5, it creates the ModelForm with the right initial data, but then POSTs to /charities/add, thus creating a new instance. You need to POST to /charities/edit/5, for example. Take a look at the url template tag.
I suggest you use 2 templates, one for adding, another for editing. I know it may not be very DRY, but I believe it's clearer this way.
Add template:
{% extends "base.html" %}
{% block title %}Charities Add{% endblock %}
{% block content %}
<form method="post" action="{% url charities_app.views.add %}"><table cellpadding="0">{{ form.as_table}}</table><input type="submit" value="Save"></form>
{% endblock %}
Edit template:
{% extends "base.html" %}
{% block title %}Edit Charity{% endblock %}
{% block content %}
<form method="post" action="{% url charities_app.views.edit charity.id %}"><table cellpadding="0">{{ form.as_table}}</table><input type="submit" value="Save"></form>
{% endblock %}
You may also want to check the create_object and update_object generic views, they are very useful in simple cases like yours.
Hello I have been recently working on Django search forms recently and have tired to edit one myself. Here is a search form that is supposed to find Clients. However When I type in a clients name, it does not display that client's name. So I am wondering What I am doing wrong.
#model.py
class Client(models.Model):
company = models.CharField(max_length=80)
first_name = models.CharField(max_length=80, blank=True, null=True)
last_name = models.CharField(max_length=80, blank=True, null=True)
address = models.CharField(max_length=250)
city = models.CharField(max_length=100)
country = models.CharField(max_length=120)
postcode = models.CharField(max_length=7)
telephone = models.CharField(max_length=20)
email = models.EmailField()
additional_info = models.TextField(blank=True, null=True)
def __unicode__(self):
return self.company
#views.py
#login_required
def search_client(request):
query = request.GET.get('q', '')
if query:
qset = (
Q(company__icontains=query) |
Q(address__icontains=query) |
Q(postcode__icontains=query)
)
results = Client.objects.filter(qset).distinct()
else:
results = []
return render_to_response("search_clients.html", {
"results": results,
"query": query
}, context_instance=RequestContext(request))
#search_clients
{% extends "base.html" %}
{% block content %}
<h1>Search</h1>
<form action="." method="GET">
<label for="q">Search: </label>
<input type="text" name="q" value="{{ query|escape }}">
<input type="submit" value="Search">
</form>
{% if query %}
<h2>Results for "{{ query|escape }}":</h2>
{% if results %}
<ul>
{% for clients in results %}
<li>{{ clients|escape }}</l1>
{% endfor %}
</ul>
{% else %}
<p>No clients found</p>
{% endif %}
{% endif %}
{% endblock %}
Could it be because you are searching by company, address and postcode, and not by client name?
Ok looks like somehow it know works properly. The odd thing is I don't know how it started to working properly. I may have restarted the server again while making changes or may have been my urls.py file. I really don't know but seems ok now.