printing values django templates using for loop - python

I have two models interrelated items and broken :
class Items(models.Model):
id = models.AutoField(primary_key=True)
item_name = models.CharField(max_length=50, blank=False)
item_price = models.IntegerField(blank=True)
item_quantity_received = models.IntegerField(blank=False)
item_quantity_available = models.IntegerField(blank=True)
item_purchased_date = models.DateField(auto_now_add=True, blank=False)
item_units = models.CharField(max_length=50, blank=False)
def __str__(self):
return self.item_name
class Broken(models.Model):
item = models.ForeignKey(Items, default=1, on_delete=models.CASCADE)
item_quantity_broken = models.IntegerField(blank=True)
item_broken_date = models.DateField(auto_now_add=True, blank=False)
item_is_broken = models.BooleanField(default=True)
date_repaired = models.DateField(auto_now=True, blank=True)
def __str__(self):
return self.item.item_name
I wrote this view function to retrieve data to a table into a template:
def broken_items(request):
br = Broken.objects.select_related('item').all()
print(br.values_list())
context = {
'title': 'broken',
'items': br,
}
return render(request, 'store/broken.html', context)
this is the executing query:
SELECT "store_broken"."id",
"store_broken"."item_id",
"store_broken"."item_quantity_broken",
"store_broken"."item_broken_date",
"store_broken"."item_is_broken",
"store_broken"."date_repaired",
"store_items"."id",
"store_items"."item_name",
"store_items"."item_price",
"store_items"."item_quantity_received",
"store_items"."item_quantity_available",
"store_items"."item_purchased_date",
"store_items"."item_units"
FROM "store_broken"
INNER JOIN "store_items"
ON ("store_broken"."item_id" = "store_items"."id")
looks like it gives me all the fields I want. In debugger it shows data from both tables,
so I wrote for loop in template,
{% for item in items %}
<tr>
<td>{{item.id}}</td>
<td>{{item.item_id}}</td>
<td>{{item.item_quantity_broken}}</td>
<td>{{item.item_broken_date}}</td>
<td>{{item.item_is_broken}}</td>
<td>{{item.date_repaired}}</td>
<td>{{item.item_name }}</td>
<td>{{item.item_item_quantity_received}}</td>
<td>{{item.item_quantity_available}}</td>
<td>{{item.item_purchased_date}}</td>
<td>{{item.items_item_units}}</td>
</tr>
{% endfor %}
The thing is this loop only gives me data from broken table only. I can't see data from Items table.
can someone help me to find the reason why other details are not showing?

Your items query is of Broken objects. So in order to access the Items values you need to change your table. For better understanding change your view like this:
brokens = Broken.objects.select_related('item').all()
context = {
'title': 'broken',
'brokens ': brokens,
}
and then your table:
{% for broken in brokens %}
<tr>
<td>{{broken.id}}</td>
<td>{{broken.item.pk}}</td> # This is the item id
<td>{{broken.item_quantity_broken}}</td>
<td>{{broken.item_broken_date}}</td>
<td>{{broken.item_is_broken}}</td>
<td>{{broken.date_repaired}}</td>
<td>{{broken.item.item_name}}</td>
<td>{{broken.item.item_quantity_received }}</td>
<td>{{broken.item.item_quantity_available}}</td>
<td>{{broken.item.item_purchased_date}}</td>
<td>{{broken.item.items_item_units}}</td>
</tr>
{% endfor %}

you loop over a List of Broken objects
to access the related item objects
item.item.item_name

Related

How to save address form data and display in template using Django

Brand new to Django/Python and have almost completed my first big project. I've built a small ecommerce store with a staff backend to update/delete and create products. I would like to display the address entered in by the User at checkout with in the Staff template.
My code so far looks like this:
models.py:
class Address(models.Model):
ADDRESS_CHOICES = (
('B', 'Billing'),
('S', 'Shipping'),
)
user = models.ForeignKey(
User, blank=True, null=True, on_delete=models.CASCADE)
street_address = models.CharField(max_length=150)
town_or_city = models.CharField(max_length=100)
county = models.CharField(max_length=100, default=True)
postcode = models.CharField(max_length=20)
address_type = models.CharField(max_length=1, choices=ADDRESS_CHOICES)
default = models.BooleanField(default=False)
def __str__(self):
return f"{self.street_address}, {self.town_or_city}, {self.county}, {self.postcode}"
class Meta:
verbose_name_plural = 'Addresses'
I would like to captcha the data from the 'street_address', 'town_or_city', 'county' and 'postcode' fields and have that info displayed with in my staff template.
The idea I had was to import my Address model and grab all objects using Address.objects.all() and have this display with in the template using something like {{ user_address}}
views.py / StaffView:
class StaffView(LoginRequiredMixin, generic.ListView):
template_name = 'staff/staff.html'
queryset = Order.objects.filter(ordered=True).order_by('-ordered_date')
paginate_by = 10
context_object_name = 'orders'
def get_address(self):
user_address = Address.objects.all()
return user_address
staff.html:
<tr>
<td><a class="order-ref-number-link" href="{% url 'cart:order-detail' order.pk %}">#{{ order.reference_number }}</a>
</td>
<td>{{ order.ordered_date }}</td>
<td>{{ order.user.email }}</td>
<td>£{{ order.get_total }}</td>
<td>{% if order.ordered %}Paid{% else %}Not Paid!{% endif %}</td>
<td>{{ user_address }}</td> <--HERE IS WHERE I'M TRYING TO DISPLAY ADDRESSES
</tr>
{% empty %}
So far this method i've tried alone returns nothing, im still finding my way around Django so would really appreciate if someone could help me find a simple solution for this. If any additional info is needed I'll be happy to provide. Thanks in advance.

Sum Foreignkey objects to loop

I'm trying create a table with 2 columns:
1) Collections and 2) Qualified Sales.
Like the image above.
Each book count the own qualified_sales.
The Qualified sales(column in the table) must sum all qualified_sales of all books of each collection.
models.py
class Publishing_company(models.Model):
title = models.CharField(max_length=50)
class Collection(models.Model):
publishing_company = models.ForeignKey(Publishing_company, on_delete=models.CASCADE)
class Book(models.Model):
publishing_company = models.ForeignKey(Publishing_company, on_delete=models.CASCADE)
class Sale(models.Model):
book = models.ForeignKey(Book, on_delete=models.CASCADE)
qualified_sale = models.IntegerField(default=0)
views.py
def qlf_sales(request):
book = Collection.objects.filter(user=request.user)
qualified_sum = Sale.objects.filter(user=request.user, book__publishing_company__collection__in=book).aggregate(Sum('qualified_sale'))['qualified_sale__sum'] or 0
context = {'qualified_sum': qualified_sum}
return render(request, 'template.html', context)
template.html
{% for collection in collections %}
<tr>
<td>{{collection}}</td>
<td>{{qualified_sum}}%</td>
</tr>
{% endfor %}
But this code not work. Dont appear any debug error, but in the all fields in the Qualified Sales' column appear the same value: the sum of all qualified_sales of all sales of all book.
why didn't separate by collection?
If anyone can help me. Please i go a lot grateful.

Django Passing Through List Items

I have a todo website that allows users to put a remind in a certain list, such as work, school, groceries, etc. However, I'm a bit lost on how to get the list name and their items to display.
Models.py:
class RemindList(models.Model):
parent_user = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
title = models.CharField(max_length=50)
class Reminder(models.Model):
remind_types = [('Regular', 'Regular'), ('Long Term', 'Long Term')]
title = models.CharField(max_length=100)
description = models.TextField()
remind_time = models.DateTimeField(blank=True)
parent_user = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
parent_list = models.ForeignKey(RemindList, on_delete=models.CASCADE, null=True)
type_of_remind = models.CharField(max_length=12, choices=remind_types, default='Regular')
complete = models.BooleanField(default=False)
Views.py:
#login_required(login_url='/login')
def home(request):
user = get_object_or_404(User, username=request.user.username)
context = {
'events': ToDoItem.objects.filter(parent_user=user),
'reminders': Reminder.objects.filter(parent_user=user, type_of_remind='Regular'),
'long_term_reminders': Reminder.objects.filter(parent_user=user, type_of_remind='Long Term'),
'remind_list_items': RemindList.objects.filter(parent_user=user),
}
return render(request, 'main/home.html', context)
I can pass through the list names, and I planned to just loop through them and add Reminder.objects.filter(parent_user=user, type_of_remind='Regular', parent_list=list_name) to context. However, theres no way to loop through them on the html side (can't do for loop because there are other context types), and you can't filter them on the html side (correct me if I'm wrong). Is there another way to do this?
Ok, it took me a few readings, but if what I understand is correct you want to be able to iterate over the ReminderList objects and also list out the Reminder items under each one.
My suggestion would be to add a method to ReminderList that returns the items in that list, you could then do something like this in your template
{% for list in reminder_lists %}
... List header stuff goes here ...
{% for item in list.get_reminder_items %}
... Print the item ...
{% endfor %}
{% endfor %}
(The Django templating language can be a little interesting in that object.identifier can map to either an attribute or an object method - this can be useful for cases like these).

Is there a way to display information from a connected table if not null?

I built a table with a MySQL backend in Django that lets me store generator charts that would be useful in worldbuilding and character building, like you might find on reddit.com/r/d100. My table can account for 110 potential roll entries, but I anticipate that for some tables (such as d20 tables), a large number of the entries will not be used. Is there a way to display all of the used entries but skip the null entries? If not, I am prepared to hardcore each of the rolls to display on the webpage.
I was anticipating having to plug in something like
<tr>
<th>Roll</th>
<th>Result</th>
</tr>
{% if table.roll_1 is not None %}
<tr>
<td>1</td>
<td>{{ table.roll_1 }}
</tr>
{% endif %}
</table>
This is my generator table model:
class D100Generator(models.Model):
d_100_id = models.AutoField(primary_key=True)
field_of_interest = models.ForeignKey(FieldOfInterest, on_delete=models.CASCADE)
subreddit_post_id = models.ForeignKey(Subreddit, on_delete=models.CASCADE, blank=True, null=True)
module_id = models.ForeignKey(Module, on_delete=models.CASCADE, blank=True, null=True)
generic_website_id = models.ForeignKey(GenericWebsite, on_delete=models.CASCADE, blank=True, null=True)
table_name = models.CharField('table name', max_length=100)
system = models.CharField(max_length=150)
genre = models.CharField(max_length=250)
chart_type = models.CharField('Die used', max_length=15)
chart_instructions = models.TextField('Chart instructions & explanation')
roll_1 = models.TextField('1', blank=True, null=True)
roll_2 = models.TextField('2', blank=True, null=True)
...
roll_109 = models.TextField('109', blank=True, null=True)
roll_110 = models.TextField('110', blank=True, null=True)
table_slug = models.SlugField(unique=True)
def save(self, *args, **kwargs):
if not self.id:
#Newly created object, so set slug
self.table_slug = slugify(self.table_name)
super(D100Generator, self).save(*args, **kwargs)
def __str__(self):
return self.table_name
This is the view that calls the page:
from django.shortcuts import get_object_or_404, render
from .models import D100Generator
def index(request):
latest_table_list = D100Generator.objects.order_by('-d_100_id')[:5]
context = {
'latest_table_list': latest_table_list
}
return render(request, 'generators/index.html', context)
def table(request, table_slug):
table = get_object_or_404(D100Generator, pk=table_slug)
return render(request, 'generators/table.html', {'table': table})
I think you can do as following to filter table data to exclude null or empty roll containing entries
from django.db.models import Q
def index(request):
latest_table_list = D100Generator.objects.filter(
roll_1__isnull=False
).exclude(
roll_1__exact=''
).order_by('-d_100_id')[:5]
context = {
'latest_table_list': latest_table_list
}
return render(request, 'generators/index.html', context)
This will exclude table rows in which roll_1 is None or empty. Then you might not need check None in template.
There are ways to filter out the null entries for a column if multiple rows in a table are being used, but in this case I need to hardcode each successive column name, and there's no way to skip that.

Joining 2 lists Django

I have 2 ArrayField lists and I want to join them using the zip method so I can Iterate through two lists in Django my django templates. But the output is treating each as array as seperate lists.
my model
class programas(models.Model):
title = models.CharField(unique=True, max_length=250)
script = ArrayField(models.CharField(max_length=8000, blank=True))
created_on = models.DateTimeField()
show_date = models.CharField(max_length=300, blank=True, null=True)
script_eng = ArrayField(models.CharField(max_length=8000, blank=True))
description = models.CharField(max_length=2000, blank=True, null=True)
description_eng = models.CharField(max_length=2000, blank=True, null=True)
url = models.CharField(max_length=200, blank=True, null=True)
show_id = models.IntegerField(primary_key=True)
id = models.IntegerField(null=True)
my view where I try to join the lists
def pages(request, id):
obj = programas.objects.get(id=id)
script = programas.objects.values_list('script')
script_eng = programas.objects.values_list('script_eng')
zip_scripts = list(zip(script , script_eng))
context = {'title': obj.title,
'show_date': obj.show_date,
'script' : obj.script,
'script_eng': obj.script_eng,
'description': obj.description,
'description_eng': obj.description_eng,
'show_id':obj.show_id,
'url': obj.url,
'zip_scripts' : zip_scripts,
}
return render(request, 'rtves/pages.html', context)
my code on the template page
{% if script %}
{% for text1, text2 in zip_scripts %}
<p> {{ text1 }} </p>
<p> {{ text2 }} </p>
{% endfor %}
{% else %}
<p>Nothing here</p>
{% endif %}
Have I got to make changes in the database?
programas.objects.values_list('script') gives you a list of the script fields of all the programas objects in the database. So, you effectively have a list of lists.
What you probably want is just the fields from the object you already have. So there's no need to use values_list there.
obj = programas.objects.get(id=id)
script = obj.script
script_eng = obj.script_eng
or, just pass them straight to the zip (note, there's no need for list anyway):
obj = programas.objects.get(id=id)
zip_scripts = zip(obj.script, obj.script_eng)
The reason it "doesn't" work on your perspective is that because when you cast querysets to built-in iterables, you don't get, an an iterable of the values but an iterable of one item tuples like
[('bill',), ('while',), ('participant',), ('you',)]
which, when you cast zip and list upon becomes even weirder, but you can simply flatter this with something like
list(map(o.itemgetter(0), qs))
In your case the whole code would be roughly
flatten = lambda qs: list(map(operator.itemgetter(0), qs))
script = flatten(programas.objects.values_list('script'))
script_eng = flatten(programas.objects.values_list('script_eng'))
# Then you can just zip them together and have what you wanted to begin with
zip_scripts = list(zip(script , script_eng))

Categories