How to prevent a supplier from upvoting and downvoting himself - python

I am working on a Supplier Management System. I have a page where users could view all suppliers on the application. on the same page, users can upvote and downvote suppliers, is there a way that i could make the supplier not able to upvote or downvote his self.
I am thinking if there is a way i can pass the supplier.user into the context which identifies the supplier, perhaps doing something like this but it doesn't seem to work. I could then pass this into the template {% if supplier.user == request.user %}content...{% endif %}
Presently, supplier.user return nothing.
views.py
def Viewsupplier(request):
title = "All Suppliers"
suppliers = User.objects.filter(user_type__is_supplier=True)
# Get the updated count:
suppliers_votes_count = {}
for supplier in suppliers:
upvote_count = supplier.upvotes
downvote_count = supplier.downvotes
supplier_count = {supplier: {'upvote': upvote_count, 'downvote': downvote_count } }
suppliers_votes_count.update(supplier_count)
context = {"suppliers":suppliers, "title":title, "suppliers_votes_count": suppliers_votes_count}
return render(request, 'core/view-suppliers.html', context)
view-supplier.html
<thead>
<tr>
<th>No</th>
<th>Email</th>
<th>Votes</th>
</tr>
</thead>
<tbody>
{% for supplier in suppliers %}
<tr>
<td>{{forloop.counter}}</td>
<td>{{supplier.email}}</td>
<td>
<div class="table-data-feature">
{% if supplier.user == request.user %}<a href="{% url 'upvote' supplier.id %}">{% endif %}
<button class="item" data-toggle="tooltip" data-placement="top" title="Like">
<i class="zmdi zmdi-thumb-up"></i></button>
{% if supplier.user == request.user %}</a>{% endif %}
<button>{{supplier.upvotes}}</button>
{% if supplier.user == request.user %}<a href="{% url 'downvote' supplier.id %}">{% endif %}
<button class="item" data-toggle="tooltip" data-placement="top" title="Dislike">
<i class="zmdi zmdi-thumb-down"></i></button>
{% if supplier.user == request.user %}</a>{% endif %}
<button>{{supplier.downvotes}}</button>
</div>
</td>
</tr>
{% empty %}
<tr><td class="text-center p-5" colspan="7"><h4>No supplier available</h4></td></tr>
{% endfor %}
</tbody>

I was able to solve the issue by using this templatetag in my templates:
{% if supplier.email != request.user.email %}content...{% endif %}
This worked easily because i already had the supplier info from the views already.

Related

My UpdateView does show errors on fly orm

I have an update view which displays a form (based on some criteria). I can update my model successfully, but if I enter bad data (like a bad time field), I do not get any errors back, I simply get a refresh of the update form.
My view looks like this:
class Cd_MixedView(UpdateView):
model = Track
template_name = 'cd_mixed_view.html'
form_class = TrackForm
context_object_name = 'cd_edit'
def get_context_data(self, **kwargs):
context = super(Cd_MixedView,self).get_context_data(**kwargs)
cur_track = Track.objects.get(id=self.kwargs['pk'])
context['form'] = TrackForm(instance=cur_track)
context['cd_info'] = Cd.objects.get(id=cur_track.cd_id.pk)
return context
def post(self, request, *args, **kwargs):
self.object = self.get_object()
form = self.get_form()
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
def form_valid(self,form):
form.save()
return super(Cd_MixedView, self).form_valid(form)
def form_invalid(self,form):
print("Form Invalid")
return super(Cd_MixedView,self).form_invalid(form)
My template is the following:
<!-- templates/cd_mixed_view.html -->
{% extends 'base.html' %}
{% load static %}
{% block title %} CD Details{% endblock title %}
{% block content %}
<h1>CD Update Track </h1>
{% if cd_info %}
<p>Artist Name: {{ cd_info.artist_name}}
<p>Cd Title: {{ cd_info.cd_title }}
<p>Cd Total Time: {{ cd_info.cd_total_time|time:"H:i:s" }}
<p>Cd Run Time: {{ cd_info.cd_run_time|time:"H:i:s" }}
<p>Cd Remaining Time:
{% if cd_info.cd_run_time_delta > cd_info.cd_total_time_delta %}
(-{{ cd_info.cd_remaining_time|time:"H:i:s" }})
{% else %}
{{ cd_info.cd_remaining_time|time:"H:i:s" }}
{% endif %}
<TABLE BORDER="0" TABLE_LAYOUT="fixed" WIDTH="100%">
<TR BGCOLOR="#B0B0FF">
<TD ALIGN="Center"> Track #</TD>
<TD ALIGN="Center"> Cut Title</TD>
<TD ALIGN="Center">Track Length</TD>
<TD ALIGN="Center" BGCOLOR="#CC99CC">Run Time</TD>
<TD ALIGN="Center" BGCOLOR="#CC99CC">Time Remaining</TD>
</TR>
{% for tracks in cd_info.cd_tracks.all %}
{% if tracks.id != cd_edit.pk %}
<TR>
<TD ALIGN="Left" VALIGN="Top" WIDTH="10"> {{ tracks.track_number }}</TD>
<TD ALIGN="Left" VALIGN="Top"> {{ tracks.track_title }}</TD>
<TD ALIGN="Left" VALIGN="Top">{{ tracks.trk_length_time|time:"H:i:s" }}</TD>
<TD ALIGN="Left" VALIGN="Top">{{ tracks.trk_run_time|time:"H:i:s" }}</TD>
{% if tracks.trk_run_time_delta > cd_info.cd_total_time_delta %}
<TD BGCOLOR="#8DF1BF" ALIGN="Left"> (-{{ tracks.trk_remaining_time|time:"H:i:s" }})</TD>
{% else %}
<TD BGCOLOR="#8DF1BF" ALIGN="Left"> {{ tracks.trk_remaining_time|time:"H:i:s" }}</TD>
{% endif %}
</TR>
{% else %}
<form action="" method="post">
{% csrf_token %}
{{ form }}
<tr>
<td> </td>
<td><input type="submit" value="Update Track Values"></td>
</tr>
</form>
{% if form.errors %}
<p>There were some errors in the information you entered. Please correct the following:</p>
<ul>
{% for field in form %}
{% if field.errors %}
<li>{{ field.label }}:
{{ field.errors|striptags }}</li>
{% endif %}
{% endfor %}
</ul>
{% endif %}
{% endif %}
{% endfor %}
</TABLE>
{% endif %}
{% endblock content %}
The form itself is the following:
class TrackForm(forms.ModelForm):
class Meta:
model = Track
exclude = ('trk_length_time_delta',
'trk_run_time',
'trk_run_time_delta' ,
'trk_remaining_time',
'trk_remaining_time_delta',
)
widgets = {
'cd_id': forms.HiddenInput()
}
I even put a print in the invalid_form function - so it seems to know the form is invalid,
but it just redisplays my form with the previous data.
Any ideas what I am missing here?
Thanks
You use UpdateView yet for some reason you go and redefine most of it's useful methods while not even making any useful or new changes. The main problem is that you override get_context_data and overwrite the form while manually defining it even though the super method has already added the form properly to the context.
Let UpdateView do it's job most of the code you write is not needed as UpdateView already does that:
class Cd_MixedView(UpdateView):
model = Track
template_name = 'cd_mixed_view.html'
form_class = TrackForm
context_object_name = 'cd_edit'
def get_context_data(self, **kwargs):
context = super(Cd_MixedView,self).get_context_data(**kwargs)
cur_track = self.object # no need to get the object again it is already present in `self.object`
# form is already added to context by super method
context['cd_info'] = Cd.objects.get(id=cur_track.cd_id.pk)
return context
# `post`, `form_valid` and `form_invalid` methods were same as super so no need to write yourself

Django paginator returning same data on seperate pages

Problem:
I am developing an application in django that uses paginator for the list page of a model, it is set to display 25 instances of the model per page, when i view the first page everything works fine but when i move to the second page it shows some values from the first again. i have checked the database and there is no data duplication either.
Cause/attempted solutions:
while not 100% i believe the problem originates from the order_by in the queryset but even after changing and removing the problem persists
Details:
snips of list for the first and second page
First: https://imgur.com/tyY5xu0
Second: https://imgur.com/UcGWEFN (note CO01, 4 and 5 appear again)
Views.py:
def view_jobs(request):
query_results = Job.objects.select_related('contract').order_by('-active', '-order_date')
paginate = Paginator(query_results, 25)
page_no = request.GET.get('page')
page_obj = paginate.get_page(page_no)
context = {"query_results": page_obj}
return render(request, 'view_jobs.html', context)
view_jobs.html:
<table id="PageTable" class="table table-striped">
<thead>
<tr>
<th class="dropdown">
<a class="dropdown-toggle" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true"
aria-expanded="false">
<h6>Number</h6>
</a>
</th>
</tr>
</thead>
<tbody>
{% for item in query_results %}
<td>
<small>{{ item|filter_prep:"order" }}</small>
{% if item.help_text %}
<small style="color: grey">{{ item.help_text }}</small>
{% endif %}
{% for error in item.errors %}
<p style="color: red">{{ error }}</p>
{% endfor %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="pagination">
<span class="step-links">
{% if query_results.has_previous %}
« first
previous
{% endif %}
<span class="current">
Page {{ query_results.number }} of {{ query_results.paginator.num_pages }}.
</span>
{% if query_results.has_next %}
next
last »
{% endif %}
</span>
</div>
feel free to ask for any extra details.

Passing context to django admin index page

I'm trying to create a table on django admin's index page, listing all users registered in a specific timeframe. I've managed to already edit the index page to include my table but I now want to populate the table. I tried declaring the extra_context variable but it still doesn't pass it to the template. I've been on this issue for days and still can't figure out what I'm doing wrong. This is my admin.py file
from django.contrib import admin
from django.contrib.auth.models import Group
from django.contrib.auth.admin import UserAdmin
from .forms import SignUpForm, EditUserForm
from .models import CustomUser
from django.urls import path
from datetime import datetime, timedelta
from django.utils import timezone
class CustomUserAdmin(UserAdmin):
list_filter = ['created_at',]
list_display = ['username', 'email', 'created_at', 'is_active']
# index_template = 'admin/my_index.html'
def time_threshold(num):
num = int(num)
thresh = datetime.now(tz=timezone.utc) - timedelta(hours=num)
return thresh
print(time_threshold(30))
def get_urls(self):
urls = super().get_urls()
custom_urls = [
path("user_metrics/", self.user_metrics),
]
return custom_urls + urls
def user_metrics(self, request, extra_context=None):
extra_context = extra_context or {}
user_24 = CustomUser.objects.filter(created_at__gt=time_threshold(730))
extra_context['users_in_past_24_hours'] = CustomUser.objects.filter(created_at__gt=time_threshold(24))
extra_context['users_in_past_week'] = CustomUser.objects.filter(created_at__gt=time_threshold(168))
extra_context['users_in_past_month'] = CustomUser.objects.filter(created_at__gt=time_threshold(730))
print(user_24)
return super(CustomUserAdmin, self).user_metrics(request, extra_context=extra_context)
admin.site.register(CustomUser, CustomUserAdmin)
admin.site.unregister(Group)
admin.site.site_header = "Savests Custom Admin"
And this is my index.html file I have inside template/admin folder
{% extends "admin/base_site.html" %}
{% load i18n static %}
{% block extrastyle %}{{ block.super }}<link rel="stylesheet" type="text/css" href="{% static "admin/css/dashboard.css" %}">{% endblock %}
{% block coltype %}colMS{% endblock %}
{% block bodyclass %}{{ block.super }} dashboard{% endblock %}
{% block breadcrumbs %}{% endblock %}
{% block nav-sidebar %}{% endblock %}
{% block content %}
<div id="content-main">
{% include "admin/app_list.html" with app_list=app_list show_changelinks=True %}
</div>
<div>
<h5>Users in the last 24 hours</h5>
<table class="table table-hover table-bordered">
<caption>User Information</caption>
<thead class="thead-dark">
<th>User ID</th>
<th>Username</th>
<th>Email Address</th>
<th>Active Status</th>
<th>Staff Status</th>
</thead>
{% for a in users_in_past_24_hours %}
<tr>
<td>{{ a.id }}</td>
<td>{{ a.username }}</td>
<td>{{ a.email }}</td>
<td>
{% if a.is_active %}
<form action="{% url 'toggle_user_status_false' user_id=a.id %}" method="post">
{% csrf_token %}
<button class="btn btn-danger" type="submit">
Deactivate
</button>
</form>
{% else %}
<form action="{% url 'toggle_user_status_true' user_id=a.id %}" method="post">
{% csrf_token %}
<button class="btn btn-primary" type="submit">
Activate
</button>
</form>
{% endif %}
</td>
<td>
{% if a.is_staff %}
Staff
{% else %}
Not Staff
{% endif %}
</td>
</tr>
{% endfor %}
</table>
<br>
<hr>
<h5>Users in the past week</h5>
<table class="table table-hover table-bordered">
<caption>User Information</caption>
<thead class="thead-dark">
<th>User ID</th>
<th>Username</th>
<th>Email Address</th>
<th>Active Status</th>
<th>Staff Status</th>
</thead>
{% for a in users_in_past_week %}
<tr>
<td>{{ a.id }}</td>
<td>{{ a.username }}</td>
<td>{{ a.email }}</td>
<td>
{% if a.is_active %}
<form action="{% url 'toggle_user_status_false' user_id=a.id %}" method="post">
{% csrf_token %}
<button class="btn btn-danger" type="submit">
Deactivate
</button>
</form>
{% else %}
<form action="{% url 'toggle_user_status_true' user_id=a.id %}" method="post">
{% csrf_token %}
<button class="btn btn-primary" type="submit">
Activate
</button>
</form>
{% endif %}
</td>
<td>
{% if a.is_staff %}
Staff
{% else %}
Not Staff
{% endif %}
</td>
</tr>
{% endfor %}
</table>
<br>
<hr>
<h5>Users in the past month</h5>
<table class="table table-hover table-bordered">
<caption>User Information</caption>
<thead class="thead-dark">
<th>User ID</th>
<th>Username</th>
<th>Email Address</th>
<th>Active Status</th>
<th>Staff Status</th>
</thead>
{% for a in users_in_past_month %}
<tr>
<td>{{ a.id }}</td>
<td>{{ a.username }}</td>
<td>{{ a.email }}</td>
<td>
{% if a.is_active %}
<form action="{% url 'toggle_user_status_false' user_id=a.id %}" method="post">
{% csrf_token %}
<button class="btn btn-danger" type="submit">
Deactivate
</button>
</form>
{% else %}
<form action="{% url 'toggle_user_status_true' user_id=a.id %}" method="post">
{% csrf_token %}
<button class="btn btn-primary" type="submit">
Activate
</button>
</form>
{% endif %}
</td>
<td>
{% if a.is_staff %}
Staff
{% else %}
Not Staff
{% endif %}
</td>
</tr>
{% endfor %}
</table>
<br>
<hr>
</div>
{% endblock %}
{% block sidebar %}
<div id="content-related">
<div class="module" id="recent-actions-module">
<h2>{% translate 'Recent actions' %}</h2>
<h3>{% translate 'My actions' %}</h3>
{% load log %}
{% get_admin_log 10 as admin_log for_user user %}
{% if not admin_log %}
<p>{% translate 'None available' %}</p>
{% else %}
<ul class="actionlist">
{% for entry in admin_log %}
<li class="{% if entry.is_addition %}addlink{% endif %}{% if entry.is_change %}changelink{% endif %}{% if entry.is_deletion %}deletelink{% endif %}">
{% if entry.is_deletion or not entry.get_admin_url %}
{{ entry.object_repr }}
{% else %}
{{ entry.object_repr }}
{% endif %}
<br>
{% if entry.content_type %}
<span class="mini quiet">{% filter capfirst %}{{ entry.content_type.name }}{% endfilter %}</span>
{% else %}
<span class="mini quiet">{% translate 'Unknown content' %}</span>
{% endif %}
</li>
{% endfor %}
</ul>
{% endif %}
</div>
</div>
{% endblock %}
1st way is to declare subclass django.contrib.admin.site.AdminSite() and override the .index() method in admin.py
class MyAdminSite(django.contrib.admin.site.AdminSite):
def index(self, request, extra_context=None):
if extra_context is None:
extra_context = {}
user_24 = CustomUser.objects.filter(created_at__gt=time_threshold(730))
extra_context['users_in_past_24_hours'] = CustomUser.objects.filter(created_at__gt=time_threshold(24))
extra_context['users_in_past_week'] = CustomUser.objects.filter(created_at__gt=time_threshold(168))
extra_context['users_in_past_month'] = CustomUser.objects.filter(created_at__gt=time_threshold(730))
extra_context["app_list"] = get_app_list_in_custom_order()
return super(MyAdminSite, self).index(request, extra_context)
then you should register your site admin (also in admin.py)
my_admin_site = MyAdminSite(name='myadmin')
when you create your own AdminSite you need to register all models using it, so instead of
admin.site.register(YourModel) you should use my_admin_site.register(YourModel) for all models you use. you also need to add path to your adminsite in urls.py
from pathtoyouradmin.admin import my_admin_site
urlpatterns = [
...
path('admin/', my_admin_site.urls),
...
]
you can solve your problem other way. you can create contextprocessor where you check path of current page and if it admin index then provide needed extra_context
def context_users_info(request):
extra_context = {}
if request.path == 'index admin page'# you need to put path to your index admin page
user_24 = CustomUser.objects.filter(created_at__gt=time_threshold(730))
extra_context['users_in_past_24_hours'] = CustomUser.objects.filter(created_at__gt=time_threshold(24))
extra_context['users_in_past_week'] = CustomUser.objects.filter(created_at__gt=time_threshold(168))
extra_context['users_in_past_month'] = CustomUser.objects.filter(created_at__gt=time_threshold(730))
extra_context["app_list"] = get_app_list_in_custom_order()
return extra_context
and don't forget to register your context processor in settings.py

Using distinct() with filter() in django

I'm trying to create a query in Django that calls unique rows (using distinct) that meet some condition of a filter (using filter)
here are the used files :
views.py
def cat_details(request, pk):
current_user = request.user
selected_cat = get_object_or_404(Category, pk=pk)
selected_items = ItemIn.objects.all().filter(item_category=selected_cat).values_list('item_name', flat=True).distinct()
all_cats = Category.objects.all()
cat_count = all_cats.count()
item_count = ItemIn.objects.values_list('item_name', flat=True).distinct().count() # returns a list of tuples..
#all_units = Item.objects.aggregate(Sum('item_quantity'))['item_quantity__sum']
context = {
#'all_units': all_units,
'item_count': item_count,
'cat_count': cat_count,
'selected_items': selected_items,
'selected_cat': selected_cat,
'current_user': current_user,
}
return render(request, 'townoftech_warehouse/cat_details.html', context)
The variable called selected_items is where the problem!
and here is how I used this view function
HTML
{% extends 'townoftech_warehouse/base.html' %}
{% block content %}
{% load static %}
<div class="card">
<div class="card-header">
الاصناف فى المخزن
</div>
<div class="card-body">
<h3 align="right"> {{ selected_cat }}</h3>
<footer><button type="button" class="btn btn-dark">تعديل إسم الفئة</button>
<button type="button" class="btn btn-dark">مسح الفئة</button>
</footer>
</div>
</div>
<div style="overflow: auto;height: 280px">
<table class="table table-bordered">
<tbody>
{% for item in selected_items %}
<tr align="right">
<th scope="row">{{ item.item_name }}</th>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<br>
<br>
<div align="right"><button type="button" class="btn btn-danger">رجوع</button></div>
{% endblock %}
whenever I try to open this page the error I get is :
error
NoReverseMatch at /category/15/
Reverse for 'items' with arguments '('',)' not found. 1 pattern(s) tried: ['item\\/(?P<pk>[0-9]+)\\/$']
update
I've removed the link from the HTML files
changed
{% for item in selected_items %}
{{ item.item_name }}
{% endfor %}
to be like
{% for item in selected_items %}
<tr align="right">
<th scope="row">{{ item.item_name }}</th>
</tr>
{% endfor %}
the error disappeared but it gives me a list of empty values now!
selected_items variable contains list of string objects(item names). String dont have pk attribute, so item.pk in template returns nothing.
Istead of values_list you neet pass to template list of objects. If you are using postgres you can use distinct() with argument.
selected_items = ItemIn.objects.all().filter(item_category=selected_cat).distinct('item_name')
Otherwise you can try to use values with 'item_name', 'pk':
selected_items = ItemIn.objects.all().filter(item_category=selected_cat).values('item_name', 'pk').distinct()

Select objects with checkboxes in Class Based ListView

I'm a django newbie, I'm making a little app to record work calls received during nighttime.
At the moment the app works fine. I have made a form to fill call data, which is then presented as a table using a generic ListView.
class IndexView(LoginRequiredMixin, generic.ListView):
login_url = '/login/'
redirect_field_name = 'redirect_to'
template_name = 'chiamate/list_full.html'
context_name = 'lista_chiamate'
def get_queryset(self):
return Chiamata.objects.all
Here is the code for the template:
{% extends 'chiamate/base.html' %}
{% block content %}
{% if user.is_authenticated %}
<i class="fa fa-plus-square-o fa-lg" aria-hidden="true"></i> Nuova Chiamata
<p></p>
{% else %}
<p>Welcome, Guest please [login]</p>
{% endif %}
<div class="table-responsive">
<table class="table table-striped">
<form action="{{ action }}" method="post">
{% csrf_token %}
{% for chiamata in object_list %}
{% if chiamata.data_chiusura.weekday == 4 or chiamata.data_chiusura.weekday == 5 or chiamata.data_chiusura.weekday == 6 %}
<tr class="info">
{% elif chiamata.data_chiusura == None %}
<tr class="danger">
{% else %}
<tr>
{% endif %}
<td><input class="checkbox" name="chiamata_mail" type="checkbox" id="checkbox_{{ chiamata.id }}"value="{{ chiamata.id }}"></td>
<td class="txtdata">{{ chiamata.utente.get_full_name|wordwrap:5 }}</td>
<td class="txtdata">{{ chiamata.data_chiamata|date:"l d M Y H:i" }}</td>
<td>{{ chiamata.interlocutore }}</td>
<td>{{ chiamata.testo_chiamata|truncatechars:200 }}</td>
<td class="txtdata">{{ chiamata.reperibile|wordwrap:5 }}</td>
<td>{{ chiamata.data_chiusura|date:"H:i" }}</td>
<td></i> Edit</td>
<td><i class="fa fa-trash-o fa-lg" aria-hidden="true"></i> Delete</td>
</tr>
{% endfor %}
<input id="send_selected" type="submit" value="Send" />
</form>
</table>
</dv>
{% endblock %}
I've already tried to add the checkboxes here. When I do, they show on the page but then when I press the send button (currently implemented as a form send, but I want to use a bootstrap button) I don't know how to pass the objects to the email function, or at least show them in a new page.
You should define the post method of your view:
class IndexView(LoginRequiredMixin, generic.ListView):
def post(self, request, *args, **kwargs):
return ChiamataUpdateView.as_view()(request)
And handle the post data on the other view.
Also, you get_queryset isn't returning a queryset since you're not calling all(). It should be:
return Chiamata.objects.all()

Categories

Resources