active state and city display only in django template ForeignKey - django

I have country state city model and here is my view
class Country(models.Model):
name = models.CharField(max_length = 100)
def __str__(self):
return "%s" %(self.name)
class State(models.Model):
name = models.CharField(max_length = 100)
country = models.ForeignKey(Country, on_delete = models.CASCADE)
is_active = models.BooleanField(default = True)
def __str__(self):
return "%s" %(self.name)
class City(models.Model):
name = models.CharField(max_length = 100)
state = models.ForeignKey(State, on_delete = models.CASCADE)
is_active = models.BooleanField(default = True)
def __str__(self):
return "%s" %(self.name)
here is my view
class CountryList(ListView):
def get_template_names(self, *args, **kwargs):
return ['albums/list.html']
def get_queryset(self, *args, **kwargs):
return Country.objects.all()
now i want to show country with active state and active cities only how can do this in my template ?
my view
{% for x in object_list %}
{{x.name}} : <br>
{% for state in x.state_set.all %}
{{ state.name }} >>
{%for city in state.city_set.all %}
------#
{{ city.name }}
{% endfor %}
<br>
{% endfor %}
</br>
{% endfor %}

Related

How to display Data of foreign key in Django html page?

I want to display a Company header and the products below its related company. I am new to django i do not understand this fully.
My models.py
class Company(models.Model):
name = models.CharField(max_length=250)
def __str__(self):
return str(self.name)
class Products(models.Model):
company = models.ForeignKey(Company, on_delete=models.CASCADE, related_name="display")
engine = models.CharField(max_length=250, blank=True)
cyl = models.CharField(max_length=250, blank=True)
bore = models.CharField(max_length=250, blank=True)
def __str__(self):
return str(self.engine) + " (ref:" + str(self.ref) + ")"
My views.py:
def Companies(request):
context = {
'categories': Company.objects.all()
}
return render(request, 'product_list.html', context)
My html:
{% for category in categories %}
<h2>{{ category.name }}</h2>
{% for item in category.item_set.all %}
{{ item_engine }}
{% endfor %}
{% endfor %}
only make changes to your HTML file as below and make sure the class name is Product if you are using product_set.all:
{% for category in categories %}
<h2>{{ category.name }}</h2>
{% for item in category.product_set.all %}
{{ item.engine }}
{% endfor %}
{% endfor %}
If still not working then try to remove : + " (ref:" + str(self.ref) + ")"
and also, I think by mistake you have displayed your models.py wrongly. The str functions should be inside the classes like below:
class Company(models.Model):
name = models.CharField(max_length=250)
def __str__(self):
return str(self.name)
class Product(models.Model):
company = models.ForeignKey(Company, on_delete=models.CASCADE,
related_name="display")
engine = models.CharField(max_length=250, blank=True)
cyl = models.CharField(max_length=250, blank=True)
bore = models.CharField(max_length=250, blank=True)
def __str__(self):
return str(self.engine)

Related products

In my model I have a ManyToManyField to select related products. I'm wondering what would be the best way to bring these into my view and render them in my template.
models.py
class Product(models.Model):
title = models.CharField(max_length=80)
category = models.ManyToManyField(ProductCategory)
featured_image = models.ImageField(upload_to=image_dir)
about_this_product = models.TextField()
standard_features = models.TextField(null=True)
featured = models.BooleanField(default=False)
related_models = models.ManyToManyField("self", blank=True, null=True)
model_slug = AutoSlugField(null=True, default=None,
unique=True, populate_from='title')
class Meta:
verbose_name_plural = "Products"
def __str__(self):
return self.title
views.py
def model_detail_view(request, category_slug, model_slug):
product_model = get_object_or_404(Product, model_slug=model_slug)
context = {
"title": "Products | %s" % product_model.title,
"product": product_model,
}
return render(request=request, template_name='main/product_model_detail.html', context=context)
You can use .prefetch_related(..) just like you do on any one-to-many relation in the view:
def my_view(request):
products = Product.objects.prefetch_related('related_models')
return render(request, 'some_template.html', {'products': products})
Then in the template, you can iterate over the .related_models collection:
{% for product in products %}
{{ product.title }}
related:
{% for rel in product.related_models.all %}
{{ rel.title }}
{% endfor %}
{% endfor %}

How to rewrite data from a template in JSON?

I have this model:
class Category(models.Model):
name = models.CharField(max_length=150, unique=True)
description = models.CharField(max_length=250)
def get_absolute_url(self):
return reverse('categories_url', args=[str(self.id)])
class Company(models.Model):
name = models.CharField(max_length=150, unique=True)
country = models.CharField(max_length=50)
class Motobike(models.Model):
name = models.CharField(max_length=150)
company = models.ForeignKey('Company', on_delete=models.CASCADE)
category = models.ForeignKey('Category', on_delete=models.CASCADE)
And in view i do so..
class CategoryView(DetailView):
model = Category
template_name = 'bikes_site/categories_detail.html'
pk_url_kwarg = 'pk'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
category = self.get_object()
context['motobikes'] = Motobike.objects.filter(category_id=category.pk)
return context
And display everythng in the template
{% for motobike in motobikes %}
<ul>
<p> Name: {{ motobike.name }}</p>
<p> Company: {{ company.name }}</p>
<p> Category: {{ object.name }}</p>
<p> Description: {{ object.description }} </p>
</ul>
{% endfor %}
How to rewrite it to be displayed in JSON format(such task)? It's necessary through HttpResponse.
Here's my test:
client = Client()
category_id = Category.objects.get(name='Мотоциклы').id
response = client.get(f'/categories/{category_id}/')
assert response.status_code == 200
response_data = json.loads(response.content.decode('utf-8'))
assert len(response_data) == 2
assert response_data[1]['name'] == 'Ninja Turbo'
assert response_data[1]['vendor'] == 'Kawasaki'
assert response_data[1]['category'] == 'Мотоциклы'
assert response_data[1]['description'] == ''
How else to push the name of the company??

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'

modelformset_factory foreignkey triggers database query

My model has a foreignkey:
class Status(models.Model):
status_code = models.CharField(max_length=10, verbose_name="Status Code")
description = models.CharField(max_length=256, verbose_name="Description")
def __unicode__(self):
return "%s - %s" % (self.status_code, self.description)
def __str__(self):
return "%s - %s" % (self.status_code, self.description)
class PickUp(models.Model):
name = models.CharField(max_length=60, verbose_name="Name")
status = models.ForeignKey(Status, verbose_name="Status", default=None, blank=True, null=True)
deleted = models.BooleanField(default=False)
def __unicode__(self):
return self.name
This is my (abbreviated) view:
def index(request):
context = dict()
PickupFormSet = modelformset_factory(PickUp, fields='__all__', form=PickupForm)
qs = PickUp.objects.filter(deleted=False).prefetch_related('status')
context['pickupformset'] = PickupFormSet(queryset=qs)
return render(request, "index.html", context)
This is part of the template:
{% for pickup in pickupformset %}
{% if pickup.id.value %}
<tr>
<td>{{ pickup.id }}{{pickup.deleted}}</td>
<td>{{pickup.name}}{{pickup.name.value}}</td>
<td>{{pickup.status}}</td>
</tr>
{% endif %}
{% endfor %}
Each record displayed triggers a database query to get the status description.
SELECT `frontend_status`.`id`, `frontend_status`.`status_code`, `frontend_status`.`description` FROM `frontend_status`
Do you know why or how I can prevent this?