Django printing dynamic field in template - django

With a given model:
class Ventas(models.Model):
producto = models.CharField(max_length=200, help_text="", blank=True, null=True)
stock = models.IntegerField(help_text="Tier", blank=True, null=True)
marca = models.ForeignKey(Marcas, help_text="Usuario", blank=True, null=True, on_delete=models.CASCADE)
categoria = models.ImageField(upload_to='', default="", blank=True, null=True)
def __str__(self):
return str(self.producto )
I annotate a queryset using a dynamicaly chosen field as follows:
ventas_producto = ventas.values(ver_por_choices).annotate(
uds_totales=F("uds_totales"),
share=F("uds_totales"),
).order_by('-uds_totales')
The var "ver_por_choices" can take values of the fields of the model: producto, stock, marca or categoria
Then in the template I want to print the values as
{% for venta in ventas_producto %}
<div>{{ venta.uds_totales}}</div>
<div>{{ venta.share}}</div>
{% endfor %}
How can I print the dynamic field?

Why not include it in the queryset as key:
ver_por_choices = 'Some field name'
ventas_producto = ventas.values(ver_por_choices).annotate(
uds_totales=F('uds_totales'),
share=F('uds_totales'),
key=F(ver_por_choices)
).order_by('-uds_totales')
or even more convenient:
ventas_producto = ventas.values(
uds_totales=F('uds_totales'),
share=F('uds_totales'),
key=F(ver_por_choices)
).order_by('-uds_totales')
Then you can usse this in the {% for … %} loop with:
{% for venta in ventas_producto %}
<div>{{ venta.key }}</div>
<div>{{ venta.uds_totales}}</div>
<div>{{ venta.share}}</div>
{% endfor %}

Related

Django ValidationErrors not being displayed

I'm applying a validation for the datepicker when the user selects a future date. So far, the form does not save an invalid entry but the problem is that it doesn't display the error message for the field. This is what I've tried so far:
forms.py
class PostPagos(forms.ModelForm):
def clean(self):
cleaned_data = super(PostPagos, self).clean()
fecha = cleaned_data.get('fecha')
hoy = datetime.date.today()
if fecha > hoy:
raise forms.ValidationError(
'La Feha no puede ser mayor al día de hoy')
class Meta:
model = Pagos
fields = ('carro', 'pago', 'fecha', 'semana', 'renta')
widgets = {'fecha': forms.DateInput(attrs={'type': 'date'}),
'semana': forms.DateInput(attrs={'type': 'week'})
}
views.py
class PagosCreate(CreateView):
form_class = PostPagos
template_name = "AC/add_expense.html"
def form_valid(self, form):
object = form.save(commit=False)
object.startweek, object.endweek = self.weekdatetimeconverter(
object.semana)
object.save()
return super(PagosCreate, self).form_valid(form)
def weekdatetimeconverter(self, semana):
d = semana
startweek = datetime.datetime.strptime(d + '-1', "%Y-W%W-%w")
endweek = datetime.datetime.strptime(d + '-0', "%Y-W%W-%w")
return (startweek, endweek)
models.py
class Pagos(models.Model):
carro = models.ForeignKey(
Carros, on_delete=models.CASCADE, blank=False, null=False)
pago = models.DecimalField(max_digits=6, decimal_places=2)
fecha = models.DateField(
auto_now=False, auto_now_add=False, blank=True, null=True)
semana = models.CharField(max_length=20)
startweek = models.DateField(
auto_now=False, auto_now_add=False, blank=True, null=True)
endweek = models.DateField(
auto_now=False, auto_now_add=False, blank=True, null=True)
renta = models.ForeignKey(
Renta, on_delete=models.PROTECT, blank=False, null=False)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
verbose_name_plural = "Pagos"
def get_absolute_url(self):
return reverse('pagos')
HTML
{% extends "base.html" %}
{% load widget_tweaks %}
{% block content %}
<div class='container'>
<form method="POST">
{% csrf_token %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% for field in form.visible_fields %}
<div class="form-group">
<div class='column'>
<label>{{ field.label_tag }}</label>
{% render_field field class="form-control" %}
{% for error in field.errors %}
<span class="help-block">{{ error }}</span>
{% endfor %}
</div>
</div>
{% endfor %}
<div class="form-group">
<button type="submit" class="btn btn-success">
<span class="glyphicon glyphicon-ok"></span> Save
</button>
Cancel
</div>
</form>
</div>
{% endblock content%}
I'm using django-widget-tweaks
After reading again the documentation [https://docs.djangoproject.com/en/3.0/ref/forms/validation/#cleaning-a-specific-field-attribute][1]
one of my mistakes was that I was not doing a return, and it turns out the code needed was way simple to what I had, here it goes:
forms.py
class PostPagos(forms.ModelForm):
def clean_fecha(self):
fecha = self.cleaned_data['fecha']
if fecha > datetime.date.today():
raise forms.ValidationError(
'La Fecha no puede ser mayor al día de hoy')
return fecha
class Meta:
model = Pagos
fields = ('carro', 'pago', 'fecha', 'semana', 'renta')
widgets = {'fecha': forms.DateInput(attrs={'type': 'date'}),
'semana': forms.DateInput(attrs={'type': 'week'})
}

How to loop 'add' tag in Django template?

I want to count how many Product variations available in each Market. For now I'm only able to count Product variations for each Distributor. I'm thinking about using 'add' built-in template tag to sum Product variation in each Distributor to solve this problem, but don't know how to implement this in template for loop. Or is there any better solution? I'm open for suggestions.
My 5 related models in Django:
class Market(models.Model, RecordStatus):
name = models.CharField(max_length=100)
class Country(models.Model):
market = models.ForeignKey(Market, on_delete=models.SET_NULL, null=True, blank=True)
name = models.CharField(max_length=100)
class Distributor(models.Model, RecordStatus):
headquarter = models.ForeignKey('self', on_delete=models.CASCADE, null=True, blank=True)
country = models.ForeignKey(Country, on_delete=models.SET_NULL, null=True, blank=True)
name = models.CharField(max_length=100, null=True, blank=True)
class Product(models.Model, RecordStatus):
video = models.URLField(verbose_name='Video URL', max_length=250, null=True, blank=True)
class ProductStock(models.Model):
distributor = models.ForeignKey(Distributor, on_delete=models.CASCADE)
product = models.ForeignKey(Product, on_delete=models.CASCADE)
stock = models.PositiveIntegerField(null=True, blank=True)
My views.py:
def market_list_view(request):
markets = Market.objects.all()
context = {
'market_list': markets,
}
return render(request, 'product_visualizers/market_list.html', context)
My current attempt on market_list.html template:
{% for market in market_list %}
<h3>{{market.name}}</h3>
<p>{% for country in market.country_set.all %}
{% for distributor in country.distributor_set.all %}
{{ distributor.productstock_set.all|length }} # should I write |add besides |length to sum the numbers?
{% endfor %}
{% endfor %}</p>
{% endfor %}
What should I code in the nested for inside the template?
You can use:
class Market(models.Model, RecordStatus):
name = models.CharField(max_length=100)
def get_product_variations(self):
return Product.objects.filter(productstock__distributor__country__market=self).count()
and for your template:
{% for market in market_list %}
<h3>{{market.name}}</h3>
<p>Product variations: {{ market.get_product_variations }}</p>
{% endfor %}

Search function returning nothing -Django

def Search(request):
if request.method == 'GET' and request.GET['x']:
parameter = request.GET['x']
results = Category.objects.filter(advert__Seller_Name__icontains = parameter)
return render(request, 'campusbuy/search.html', {'results': results})
else:
return render(request, 'campusbuy/search.html')
Above is my search function. When I try to search for an object in my template, it returns nothing. However, when I deliberately search for a Seller_name that's not in the db it returns the {% else %} value. Below is the template:
% extends 'campusbuy/base.html' %}
{% block content %}
{% if results %}
{% for ads in results.advert_set.all %}
<p>{{ads.Seller_Name }}</p>
<p>{{ads.Location}}</p>
<p>{{ads.Description}}</p>
<p>{{ads.Asking_Price}}</p>
{% endfor %}
{% else %}
<p>No Ad matched your search criteria.</p>
{% endif %}
{% endblock %}
Here's the models.py:
class Category(models.Model):
Name = models.CharField(max_length=20, null=True, blank=True)
Details = models.CharField(max_length=100, default="Default")
Category_Logo = models.ImageField(max_length=100, upload_to='uploads')
def __str__(self):
return self.Name
class Advert(models.Model):
HALL3 = 'HALL3'
HALL4 = 'HALL4'
HALL2 = 'HALL2'
MAIN_GATE = 'MAINGATE'
HALL1 = 'HALL1'
Location_Choices = (
(HALL3, 'Hall3'),
(HALL4, 'Hall4'),
(HALL2, 'Hall2'),
(MAIN_GATE, 'Main_gate'),
(HALL1, 'Hall1')
)
category = models.ForeignKey(Category, on_delete=models.CASCADE)
Seller_Name = models.CharField(max_length=50, blank=False, null=False)
Phone_Number = models.CharField(max_length=11, blank=False, null=False,
help_text='<p style="color: red; font: italic 12px tahoma;">**Please input a working Phone Number that you can be contacted with on the fly</p>')
image = models.ImageField(max_length=100, upload_to='uploads')
Item = models.CharField(max_length=20, blank=False, null=False)
Location = models.CharField(max_length=10, choices=Location_Choices, default=HALL3, blank=False)
Description = models.TextField(max_length=250, blank=False, null=False)
Asking_Price = models.CharField(max_length=20, blank=False, null=False)
published_date = models.DateTimeField(blank=False, default=timezone.now)
Thank you in advance!
I still haven't understood why you've tried to include Category in the query, since you are not using it at all either in the query itself or in the template. Just query and use Adverts directly:
results = Advert.objects.filter(Seller_Name__icontains=parameter)
and iterate over it also directly:
{% for ads in results %}
<p>{{ads.Seller_Name }}</p>
<p>{{ads.Location}}</p>
<p>{{ads.Description}}</p>
<p>{{ads.Asking_Price}}</p>
{% endfor %}
Also note, you don't need the if block, because the for template tag has an [empty`](https://docs.djangoproject.com/en/2.1/ref/templates/builtins/#for-empty) clause that is displayed if the loop was empty:
{% for ads in results %}
<p>{{ads.Seller_Name }}</p>
<p>{{ads.Location}}</p>
<p>{{ads.Description}}</p>
<p>{{ads.Asking_Price}}</p>
{% empty %}
<p>No Ad matched your search criteria.</p>
{% endfor %}

Django : render the parent's data to the template only if the child of the child has data

this is my models.py
class Category(models.Model):
name = models.CharField(max_length=50)
ordering_num = models.IntegerField(default=0)
class Meta:
ordering = ['ordering_num']
def __str__(self):
return self.name
class SubCategory(models.Model):
category = models.ForeignKey('Category', on_delete=models.CASCADE)
name = models.CharField(max_length=50)
ordering_num = models.IntegerField(default=0)
class Meta:
ordering = ['ordering_num']
def __str__(self):
return self.name
class ProductBasicModels(models.Model):
whose = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
category = models.ForeignKey(SubCategory, on_delete=models.CASCADE)
name = models.CharField(max_length=50)
standard = models.CharField(max_length=50)
maker = models.CharField(max_length=50, blank=True)
outbox = models.CharField(max_length=50, blank=True)
extra = models.CharField(max_length=100, blank=True)
orderto = models.ForeignKey(OrderCompany, null=True, blank=True, on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
ordering = ['name']
def __str__(self):
return self.name
views.py
# login_required
def product_list(request):
categories = Category.objects.all()
context = {'categories': categories}
return render(request, 'medicalapp_1/products_h.html', context)
products_h.html
(simple structure...)
...
{% for category in categories %}
{{ category.name }}
{% for sub_category in category.subcategory_set.all %}
{{ sub_category.name }}
{% for list in sub_category.productbasicmodels_set.all %}
{% if list.whose.id is request.user.id %}
{{ list.name }}
{% endif %}
{% endfor %}
{% endfor %}
{% endfor %}
....
according to my code.. all of category and subcategory and products being displayed. But I want to make them display only products models has data.
like this..
category1
subcategory1
product1
product2
product3
category4
subcategory1
product4
product5
subcategory3
product6
(category2,3) and (subcategory2 of category4) are not displayed because they don't have product..
How can I make filter in the view to work like it?
Make use of regroup tag. No need to fetch all categories in the product_list() method. Instead fetch all products (as the name intents)
- with prefetch_related to its foreign key(s), to optimise the query. Then regroup the queryset. That's all!
def product_list(request):
products = ProductBasicModels.objects.all().prefetch_related('category','category__category')
context = {'products': products}
return render(request, 'medicalapp_1/products_h.html', context)
Then, in the template,
{% regroup products by category.category as cats %}
{% for cat in cats %}
<br>{{cat.grouper}}
{% regroup cat.list by category as subcats %}
{% for subcat in subcats %}
<br>{{subcat.grouper}}
{% for product in subcat.list %}
<br>{{product}}
{% endfor %}
{% endfor %}
{% endfor %}
PS :Two separate (& similar) models for category & sub-category is redundant and you shouldn't be using it. You may just use a single model with ForeignKey to 'self'

query and display the data in template

models.py
class ReportType(models.Model):
report = models.ForeignKey(Report)
title = models.CharField('Incident Type', max_length=200)
type = models.ForeignKey(Types, null=False, default=False)
class Types(models.Model):
user = models.ForeignKey(User, null=True)
title = models.CharField('Incident Type', max_length=200)
parent_type_id = models.CharField('Parent Type', max_length=100, null=True, blank=True)
is_active = models.BooleanField('Is Active', default=True)
views.py
def method(request):
report_types = ReportType.objects.filter(report=int(report_id)).select_related("type")[:3]
return{'what_tab': report_types,}
template.html
{% if leftbar.what_tab.0.type.title%}{{ leftbar.what_tab.0.type.title}}{%endif%}
I am storing the integer value in type column in ReportType model.
I am able to display the 1st item alone into template.I don't know how to display all the saved item into template.
Need help.
Thanks
I dont know what leftbar is, but assuming you got all the other stuff right,
{% for tab in leftbar.what_tab %}
{% if tab.type.title %}
{{ tab.type.title}}
{% endif %}
{% ifnotequal forloop.counter leftbar.what_tab %},{% endnotifequal %}
{% endfor %}
Since title is not nullable, {% if tab.type.title %} should never be the case.