Django: can "double" 'render_to_response' be unified into only one view? - html

I have defined two functions in views.py to obtain first prova.html with certain elementimenu and then, after clicking over one of them, I obtain again the page with elementimenu and elementi associated to elementimenu with the same id i.e.:
another_app.model.py
...
class ElementiTab(models.Model):
author = models.ForeignKey('auth.User', null=True, blank=False)
des = models.CharField(max_length=30)
x = models.FloatField()
y = models.FloatField()
res = models.FloatField(default=0)
created_date = models.DateTimeField(default=timezone.now)
...
And here the code that I like to get better:
views.py
from another_app.model import ElementiTab
def show_elementi(request):
elementimenu = ElementiTab.objects.all()
return render_to_response('homepage/prova.html',{'elementimenu': elementimenu, 'user.username': request}, context_instance = RequestContext(request))
def show_detail(request,id):
elementimenu = ElementiTab.objects.all()
detail = get_object_or_404(ElementiTab, pk=id)
return render_to_response('homepage/prova.html',{'elementimenu': elementimenu, 'detail': detail, 'user.username': request}, context_instance = RequestContext(request))
urls.py
...
url(r'^homepage/prova/$', views.show_elementi),
url(r'^show_detail/(?P<id>\d+)/$', views.show_detail),
...
prova.html
...
<div class="elementi">
{% for elementi in elementimenu %}
{{elementi.des}}
{% endfor %}
</div>
<div class="table-responsive">
<table class="table table-bordered">
<tr class="info">
<td width="35%" align="center"> NOME</td>
<td width="35%" align="center"> DATA CREAZIONE </td>
<td width="30%" align="center"> AUTORE </td>
</tr>
{% if detail %}
<div class="dettagli">
<tr>
<td>{{detail.des}}</td>
<td>{{detail.created_date}}</td>
<td>{{detail.author}}</td>
</tr>
{% endif %}
</div>
</table>
</div>
...
I had used this "trick" in show_detail view so that I can see elementimenu even after calling this function.
Is there a more elegant way to do this?

Yes, you can use the single view. Add the default None value for the id (or pk) argument:
def show_elementi(request, pk=None):
elementimenu = ElementiTab.objects.all()
detail = get_object_or_404(ElementiTab, pk=pk) if pk else None
return render(request, 'homepage/prova.html',
{'elementimenu': elementimenu, 'detail': detail})
And then map both urls to this view:
url(r'^homepage/prova/$', views.show_elementi),
url(r'^show_detail/(?P<pk>\d+)/$', views.show_elementi),

Related

How can I display html using a view that displays multiple object items and after one of those items has been deleted from the Django database?

I have the following models:
CATEGORY_CHOICES = (
('Hotel', 'Hotel'),
('Restaurant', 'Restaurant'),
('Attraction', 'Attraction'),
('Activity', 'Activity')
)
LABEL_CHOICES = (
('P', 'primary'),
('S', 'secondary'),
('D', 'danger')
)
class Item(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=64)
address = models.CharField(max_length=64)
postcode = models.CharField(max_length=7)
category = models.CharField(choices=CATEGORY_CHOICES, max_length=20)
label = models.CharField(choices=LABEL_CHOICES, max_length=1)
slug = models.SlugField()
image = models.ImageField(blank=True, null=True, upload_to="images/")
description = models.TextField()
def __str__(self):
return f"{self.id}: {self.name}"
def get_absolute_url(self):
return reverse("product", kwargs={
'slug': self.slug
})
def get_add_to_cart_url(self):
return reverse("add-to-cart", kwargs={
'slug': self.slug
})
def get_remove_from_cart_url(self):
return reverse("remove-from-cart", kwargs={
'slug': self.slug
})
class OrderItem(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
ordered = models.BooleanField(default=False)
item = models.ForeignKey(Item, on_delete=models.CASCADE)
quantity = models.IntegerField(default=1)
def __str__(self):
return f"{self.quantity} of {self.item.name}"
class Order1(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
step = models.CharField(max_length=1, default=0)
items = models.ManyToManyField(OrderItem)
start_date = models.DateTimeField(auto_now_add=True)
ordered_date = models.DateTimeField()
ordered = models.BooleanField(default=False)
step_duration = models.FloatField(default=0)
def __str__(self):
return self.user.username
def get_total_duration(self):
Pass
def get_total_price(self):
return F"£{self.step_duration * 20}"
class Order2(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
step = models.CharField(max_length=1, default=0)
items = models.ManyToManyField(OrderItem)
start_date = models.DateTimeField(auto_now_add=True)
ordered_date = models.DateTimeField()
ordered = models.BooleanField(default=False)
step_duration = models.FloatField(default=0)
def __str__(self):
return self.user.username
def get_total_duration(self):
Pass
def get_total_price(self):
return F"£{self.step_duration * 20}"
I have the following views:
#login_required(login_url='login')
def OrderSummaryView(request):
try:
order1 = Order1.objects.get(user=request.user, ordered=False)
order2 = Order2.objects.get(user=request.user, ordered=False)
context = {'object1': order1, 'object2': order2}
return render(request, "order_summary.html", context)
except ObjectDoesNotExist:
messages.error(request, "You do not have an active order")
return redirect("/")
#login_required
def add_to_cart1(request, slug):
item = get_object_or_404(Item, slug=slug)
order_item, created = OrderItem.objects.get_or_create(
item=item,
user=request.user,
ordered=False
)
order_qs = Order1.objects.filter(user=request.user, ordered=False)
if order_qs.exists():
order = order_qs[0]
# check if order item is in the order
if order.items.filter(item__slug=item.slug).exists():
order_item.quantity += 1
order_item.save()
messages.info(request, "This item quantity was updated.")
else:
order.items.add(order_item)
messages.info(request, "This item was added to your cart.")
return redirect("product", slug=slug)
else:
ordered_date = timezone.now()
order = Order1.objects.create(
user=request.user, ordered_date=ordered_date, step=1)
order.items.add(order_item)
messages.info(request, "This item was added to your cart.")
return redirect("product", slug=slug)
#login_required
def add_to_cart2(request, slug):
item = get_object_or_404(Item, slug=slug)
order_item, created = OrderItem.objects.get_or_create(
item=item,
user=request.user,
ordered=False
)
order_qs = Order2.objects.filter(user=request.user, ordered=False)
if order_qs.exists():
order = order_qs[0]
# check if order item is in the order
if order.items.filter(item__slug=item.slug).exists():
order_item.quantity += 1
order_item.save()
messages.info(request, "This item quantity was updated.")
else:
order.items.add(order_item)
messages.info(request, "This item was added to your cart.")
return redirect("product", slug=slug)
else:
ordered_date = timezone.now()
order = Order2.objects.create(
user=request.user, ordered_date=ordered_date)
order.items.add(order_item)
messages.info(request, "This item was added to your cart.")
return redirect("product", slug=slug)
#login_required
def remove_from_cart(request, slug):
item = get_object_or_404(Item, slug=slug)
order_qs = Order1.objects.filter(
user=request.user,
ordered=False
)
if order_qs.exists():
order = order_qs[0]
# check if order item is in the order
if order.items.filter(item__slug=item.slug).exists():
order_item = OrderItem.objects.filter(
item=item,
user=request.user,
ordered=False
)[0]
# order.items.remove(order_item)
# order.delete()
order_item.delete()
order_qs.delete()
messages.info(request, "This item was removed from your cart.")
return redirect("product", slug=slug)
else:
messages.info(request, "This item was not in your your cart.")
return redirect("product", slug=slug)
else:
messages.info(request, "You do not have an active order.")
return redirect("product", slug=slug)
#login_required
def remove_from_cart2(request, slug):
item = get_object_or_404(Item, slug=slug)
order_qs = Order2.objects.filter(
user=request.user,
ordered=False
)
if order_qs.exists():
order = order_qs[0]
# check if order item is in the order
if order.items.filter(item__slug=item.slug).exists():
order_item = OrderItem.objects.filter(
item=item,
user=request.user,
ordered=False
)[0]
# order.items.remove(order_item)
# order.delete()
order_item.delete()
order_qs.delete()
messages.info(request, "This item was removed from your cart.")
return redirect("product", slug=slug)
else:
messages.info(request, "This item was not in your your cart.")
return redirect("product", slug=slug)
else:
messages.info(request, "You do not have an active order.")
return redirect("product", slug=slug)
I have the following order_summary.html:
{% extends "layout.html" %}
{% block body %}
<!--Main layout-->
<main class="mt-5 pt-4">
<div style="max-width: 70%; position: relative; margin: auto;">
<!-- <div class="table-responsive text-nowrap"> -->
<h2>Booking Summary</h2>
<table class="tabled">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Name</th>
<th scope="col">Address</th>
<th scope="col">Category</th>
</tr>
</thead>
<tbody>
{% for order_item in object1.items.all %}
<tr>
<!-- <th scope="row">{{ forloop.counter }}</th> -->
<th scope="row">1</th>
<td>{{ order_item.item.name }}</td>
<td>{{ order_item.item.address }}</td>
<td>{{ order_item.item.category }}</td>
<td><a class='btn btn-warning btn-md my-0 p float-right' href="{% url 'item-list' %}">Edit</a></td>
<td><a href="{% url 'remove-from-cart' order_item.item.slug %}" class="btn btn-danger btn-md my-0 p" >Remove from cart
</a></td>
</tr>
{% empty %}
<tr>
<td colspan="5">Your cart is empty</td>
</tr>
<tr>
<td colspan="5">
<a class='btn btn-primary float-right' href="{% url 'index' %}">Continue shopping</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<br>
<table class="tabled">
<thead>
<tr>
<th scope="col"></th>
<th scope="col"></th>
<th scope="col"></th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
{% for order_item in object2.items.all %}
<tr>
<th scope="row">2</th>
<td>{{ order_item.item.name }}</td>
<td>{{ order_item.item.address }}</td>
<td>{{ order_item.item.category }}</td>
<td><a class='btn btn-warning btn-md my-0 p float-right' href="{% url 'item-list2' %}">Edit</a></td>
<td><a href="{% url 'remove-from-cart2' order_item.item.slug %}" class="btn btn-danger btn-md my-0 p" >Remove from cart
</a></td>
</tr>
{% empty %}
<tr>
<td colspan="5">Your cart is empty</td>
</tr>
<tr>
<td colspan="5">
<a class='btn btn-primary float-right' href="{% url 'index' %}">Continue shopping</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% if object.get_total %}
<tr>
<td colspan="4"><b>Vehicle Size</b></td>
<td><b></b></td>
</tr>
<tr>
<td colspan="4"><b>Duration</b></td>
<td><b></b></td>
</tr>
<tr>
<td colspan="4"><b>Total Price</b></td>
<td><b></b></td>
</tr>
<tr>
<td colspan="5">
<a class='btn btn-warning float-right ml-2' href="{% url 'checkout' %}">Proceed to checkout</a>
<a class='btn btn-primary float-right' href="{% url 'index' %}">Continue shopping</a>
</td>
</tr>
{% endif %}
</tbody>
</table>
<!-- </div> -->
</div>
</main>
<!--Main layout-->
{% endblock %}
The application defaults back to the landing html (should be order_summary.html) after an item has been deleted from either Order1 or Order2 and the Cart that displays the order has been clicked. I would like to be able to display the order summary that displays both items, delete one of the items, and then have the user directed to the order summary (the Cart) but only able to see the remaining item. I think the issue is in the view. can anyone help? There are other views that add and delete the items from Order1 and Order2. The bottom part of the html from {% if object.get_total %} is not finished.
The problem seems to be that you are redirecting to the ”products” page once the items are deleted. The urls.py file isn’t included otherwise I could validate the redirect name ”order_summary” is correct.
Each place you see this in the delete view
return redirect("product", slug=slug)
It should be this instead.
return redirect("order_summary")
That way it sends you to the order summary when completed.

Django database data not showing in Templete

I have a class HardBook that inherits from Book:
class Book(models.Model):
title = models.CharField('Book Title', max_length=200)
image = models.ImageField('Book Cover', upload_to='covers')
description = models.CharField('Description', max_length= 350)
class HardBook(Book):
quantity = models.IntegerField('Quantity')
views.py
class BookCreateView(CreateView):
def get_context_data(self,**kwargs):
context = super(BookCreateView, self).get_context_data(**kwargs)
context['softbooks'] = SoftBook.objects.all()
context['hardbooks'] = SoftBook.objects.all()
return context
I want to display the field data in a table, I want to show title, image and quantity. Everthing is displayed except quantity.
{% for hardbook in hardbooks %}
<tr>
<td>
<div class="cover-image" style="background-image:url({{hardbook.image.url}});"></div>
</td>
<td>{{hardbook.title}}</td>
<td>{{hardbook.quantity}}</td>
</tr>
{% endfor %}

Django error stating model field not defined

So I am trying to create a django view where retrieval is done on the basis of past number of months for the current logged in user, as selected by him/her in the radio choices. But I am facing an error stating that one of my model fields 'timestamp' is not defined. Also, I am a bit confused as to how to print the retrieved model in the html. Given below are my files:
html:
{% if model %}
<table>
<thead>
<tr>
<th style = "padding: 20px;">Vendor ID</th>
<th style = "padding: 20px;">Employee ID</th>
<th style = "padding: 20px;">Debit</th>
<th style = "padding: 20px;">Credit</th>
<th style = "padding: 20px;">Time of transaction</th>
</tr>
</thead>
<tbody>
{% for i in model %}
<tr>
<td style="text-align: center;">{{ i.vendor_id }}</td>
<td style="text-align: center;">{{ i.emp_id }}</td>
<td style="text-align: center;">{{ i.debit }}</td>
<td style="text-align: center;">{{ i.credit }}</td>
<td style="text-align: center;">{{ i.timestamp }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<p>There are no active transactions!</p>
{% endif %}
Views.py
if 'form2' in request.POST:
d = {}
date_id = request.POST["groupOfDefaultRadios1"]
x = employee.objects.get(name = request.user)
if date_id == 1:
d = transaction.objects.filter(emp_id = x, timestamp = datetime.date.today-timestamp(days=30))
elif date_id == 2:
d = transaction.objects.filter(emp_id = x, timestamp = datetime.date.today-timestamp(days=60))
else:
d = transaction.objects.filter(emp_id = x, timestamp = datetime.date.today-timestamp(days=180))
print(d)
return render(request, 'profiles/userLogin.html', {'model':d})
models.py:
class vendor(models.Model):
id = models.CharField(max_length=20, primary_key=True)
name = models.CharField(max_length=30)
class employee(models.Model):
name = models.OneToOneField(User, on_delete=models.CASCADE)
id = models.CharField(max_length=20, primary_key=True)
balance = models.IntegerField(default=0)
class transaction(models.Model):
vendor_id = models.ForeignKey(vendor, on_delete=models.CASCADE)
emp_id = models.ForeignKey(employee, on_delete=models.CASCADE)
debit = models.IntegerField()
credit = models.IntegerField()
timestamp = models.DateField(("Date"), default=datetime.date.today)
Any help is appreciated.
If i understand you right, you want filter transaction if their timestamp date less than 30, 60, 180 days from today
Then your filter should look like this
d = transaction.objects.filter(emp_id = x, timestamp__gte = datetime.date.today() - datetime.timedelta(days=30))
e.t.c
p.s.: Avoid naming models field with names that used in libs that you use, like timestamp
First things first, when Django raised an undefined error, are you sure that you applied migrations to this application?
python manage.py makemigrations APP_NAME
python manage.py sqlmigrate APP_NAME 0001
python manage.py migrate
Next, in your models file:
timestamp = models.DateField(("Date"), default=datetime.date.today)
When I looked up Django's model field reference, I found this:
class DateField(auto_now=False, auto_now_add=False, **options)
After reviewing your needs, will it help when you switch auto_now_add to True? I'm doubtful that default= will work in every circumstance. https://docs.djangoproject.com/en/3.0/ref/models/fields/#datefield
As a side note, when you create an object in the admin dashboard, sometimes Django will mischeck field requirements (like creating superusers), so please do watch out those objects in the management site.

New line in html table

My model:
class Affiliation(models.Model):
name = models.CharField(max_length=32)
slug = models.SlugField(unique=True)
descrizione = models.CharField(max_length=500, blank=True, null=True)
class Reg_Affiliation(models.Model):
reg = ...
affiliazione = models.ForeignKey(Affiliation, null=True,
on_delete=models.CASCADE, related_name='affiliation_conoscenza')
My descrizione field (for example):
descrizione = 'line1 <br> line2'
edit: added something about this field, see below /edit
I tried too:
descrizione = "line1 '<br>' line2"
descrizione = 'line1 "<br>" line2'
descrizione = 'line1 \n line2'
descrizione = 'line1 \r\n line2'
My template:
<div class="panel panel-default">
<table class="table table-striped table table-bordered table table-hover table table-condensed">
<thead>
<tr>
<th>Nome</th>
<th>Descrizione</th>
</tr>
</thead>
<tbody>
{% for aff in lista %}
<tr>
<td>
<b>{{ aff.affiliazione }}</b>
</td>
<td>
{{ aff.affiliazione.descrizione }}
</td>
</tr>
{% endfor %}
</tbody>
</table>
I expect:
line1
line2
in the same field of my table, instead I obtain:
line1 <br> line2
My views:
#login_required
def affiliation_list(request):
lista_a=[]
for a in Affiliation.objects.all():
ra=Reg_Affiliation(affiliazione=a,
conoscenza=c,
rapporto=r)
lista_a.append(ra)
context_dict['lista'] = lista_a
return render(request, 'core/affiliation_list.html', context_dict)
I'm using bootstrap, firefox, windows7
Thank you for your help
edit:
maybe it make difference how I add the descrizione field, so:
My populate script:
import os
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'sitoposs.settings')
import django
django.setup()
def populate():
affiliation1 = add_affiliation('name affiliation1', '''long line1 <br> long line2''')
affiliation2 =
...
def add_affiliation(name, descrizione):
a = Affiliation.objects.get_or_create(name=name)[0]
a.descrizione=descrizione
a.save()
return a
if __name__ == '__main__':
populate()
In my database I read
long line1 <br> long line2
In source page (on the browser right click on the page, view source page or something like that, I don't use english version) I read:
long line1 <br> long line2
In my populate script I tried also:
affiliation1 = add_affiliation('name affiliation1', 'long line1 and <br> long line2 in the same line, so unreadable')
use descrizione = models.TextField(max_length=500, blank=True, null=True) instead of descrizione = models.CharField(max_length=500, blank=True, null=True)
and
use {% autoescape off %}{{ aff.affiliazione.descrizione }}{% endautoescape %} instead of {{ aff.affiliazione.descrizione }}
Generally django escape all html tag and render as raw text, to render actual html you can also use {{ aff.affiliazione.descrizione|safe }}

How can I take input from a text field in a Django page then update a SQL table with the response?

I am working on a site that will be used to clean up inactive Tableau workbooks. Logging into this site will allow my users to see their old workbooks and decide which ones to keep.
This is going to be accomplished by taking some simple text input from an HTML page, K for keep | D for delete.
The response from the user will then be stored as a Python variable that will go into an if then statement. The if then statement will basically update each row in SQL, adding either K or D to a column called "Marked_for_Deletion".
From there, a stored procedure will run, check that column, and delete all things marked with a D.
Is this feasible? If so, how would I go about pulling that input and making sure it gets added to the right column/row? If not, can you offer any suggestions on a substitute method I can use?
Thanks!
Edit: Here is the code for my table.
<table class="blueTable">
<thead>
<tr>
<th>Workbook Name</th>
<th>Deletion Deadline</th>
<th>Keep or Delete?</th>
</tr>
</thead>
<tbody>
{% for book in Workbooks %}
<tr>
<td>{{ book.name }}</td>
<td>{{ book.owner_name }}</td>
<td>
<label class="container" style="margin-bottom: 25px">
<input type="text" placeholder="(Enter K for Keep, D for Delete)">
</label>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<form method="post">
{% csrf_token %}
<button type="submit" name="run_script">Submit</button>
</form>
</body>
</html>
I want to be able to pull the input from the last td tag and store it with the submit button below there.
I'm kind of late, but I hope it helps you out.
urls.py
from django.urls import path
from workbook_app import views
app_name = 'workbook_app'
urlpatterns = [
path('books/', views.BookListView.as_view(), name='books'),
path('keep_or_delete/<int:pk>/', views.KeepOrDeleteView.as_view(), name='keep_or_delete'),
]
models.py
from django.db import models
class Book(models.Model):
name = models.CharField(max_length=250)
owner_name = models.CharField(max_length=250)
marked_for_deletion = models.BooleanField(default=False)
views.py
from django.views.generic import ListView
from workbook_app.models import Book
from django.http import HttpResponse, HttpResponseRedirect
from django.views import View
from django.urls import reverse
class BookListView(ListView):
template_name = 'workbook_app/books.html'
def get_queryset(self):
return Book.objects.all()
class KeepOrDeleteView(View):
def post(self, request, pk):
book = Book.objects.get(pk=pk)
print(book, book.marked_for_deletion, not book.marked_for_deletion)
book.marked_for_deletion = not book.marked_for_deletion
book.save()
url = reverse('workbook_app:books')
return HttpResponseRedirect(url)
books.html
<div class="container">
<h2>Books</h2>
<table class="table">
<tr>
<th>Workbook Name</th>
<th>Deletion Deadline</th>
<th>Keep or Delete?</th>
</tr>
{% for book in object_list %}
<tr>
<td>{{book.name}}</td>
<td>{{book.owner_name}}</td>
<td>
<form action="{% url 'workbook_app:keep_or_delete' pk=book.pk %}" method="POST">
{% csrf_token %}
<button type="submit" class="btn btn-{%if book.marked_for_deletion %}primary{% else%}danger{% endif %}">{%if book.marked_for_deletion %}Keep{% else%}Delete{% endif %}</button>
</form>
</td>
</tr>
{%endfor%}
</table>
P.S. I'm not handling exceptions, messages, etc. You're just gonna have to figure it out yourself or open a new question.