Django odd boolean bahavior - django

I have a boolean field for whether or not an item is active:
is_active = models.BooleanField(default=True)
It seems pretty straightforward, my template will display items that are active:
{% for p in products|dictsortreversed:"id" %}
{% if p.is_active %}
<a href="{{ p.get_absolute_url }}">
{{ p.name }}
</a>
{% endif %}
For some reason all items are returned even if the field is 0 in the database. When I uncheck the boolean field in the django admin, it updates correctly to 0 in the database, but still shows as being checked in the admin...
It seems like django is reading the field as True, regardless of the boolean value.
Model
class Product(models.Model):
name = models.CharField(max_length=255, unique=True)
slug = models.SlugField(max_length=255, unique=True, help_text='Unique value for product page URL, created from name')
price = models.DecimalField(max_digits=9, decimal_places=2, blank=True, default=0.00)
old_price = models.DecimalField(max_digits=9, decimal_places=2, blank=True, default=0.00)
image = models.CharField(max_length=50)
is_active = models.BooleanField(default=True)
quantity = models.IntegerField()
description = models.TextField()
meta_keywords = models.CharField('Meta Keywords', max_length=255, help_text='Comma-delimited set of SEO keywords for meta tag')
meta_description = models.CharField('Meta Description', max_length=255, help_text='Content for description meta tag')
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
categories = models.ForeignKey(Category, null=True)
publish_date = models.DateField(blank=True, null=True)
issue_one = models.CharField(blank=True, null=True, max_length=255)
issue_two = models.CharField(blank=True, null=True, max_length=255)
issue_three = models.CharField(blank=True, null=True, max_length=255)
class Meta:
db_table = 'products'
ordering = ['-created_at']
def __unicode__(self):
return self.name
#models.permalink
def get_absolute_url(self):
return ('catalog_product', (), {'product_slug': self.slug})
View:
def index(request, template_name="catalog/index.html"):
""" site home page """
page_title = 'Visible Language Ordering'
return render_to_response(template_name, locals(), context_instance=RequestContext(request))

Related

Django How to get the value from many to many relationship

I have a product update form where I want to update the sizes of a product, with a many-to-many column relation.
I am able to get the saved values but I can't get item ID or size.
{{item.id}} shows empty value.
{% for item in form.size.value %}
<span>
<input type="checkbox" name="size" id="{{ item.id }}" value="{{ item.id }}">
<label for="{{ item.id }}">{{ item }}</label>
</span>
{% endfor %}
SIZE MODEL
class Size(models.Model):
identifier = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
size = models.CharField(max_length=200, unique=True, null=False, blank=False)
active = models.BooleanField(default=True)
date_created = models.TimeField(verbose_name='Date Created', auto_now_add=True)
date_updated = models.DateTimeField(verbose_name='Last Updated', auto_now=True)
PRODUCT MODEL
class Product(models.Model):
identifier = models.UUIDField(default=uuid.uuid4, editable=False, unique=True)
name = models.CharField(max_length=200, null=False, blank=False)
slug = models.SlugField(max_length=30, unique=True)
showcased = models.BooleanField(default=False)
recommended = models.BooleanField(default=False)
active = models.BooleanField(default=True)
price = models.DecimalField(max_digits = 5, decimal_places = 2, null=True, blank=True)
pagetitle = models.CharField(max_length=200, null=True, blank=True)
shortDescription = models.CharField(max_length=200, null=True, blank=True)
longDescription = HTMLField(null=True, blank=True)
specifications = models.TextField(null=True, blank=True)
features = models.TextField(null=True, blank=True)
care = models.TextField(null=True, blank=True)
category = models.ForeignKey(Category, on_delete=models.PROTECT)
subCategory = models.ForeignKey(SubCategory, null=True, blank=True, on_delete=models.PROTECT)
image = models.ManyToManyField(Image, blank=True)
size = models.ManyToManyField(Size, blank=True)
tag = models.ManyToManyField(Tag, blank=True)
date_created = models.TimeField(verbose_name='Date Created', auto_now_add=True)
date_updated = models.DateTimeField(verbose_name='Last Updated', auto_now=True)
I have tried different ways but not had success in getting the name or id
def updateProduct(request, pk):
categories = Category.objects.all()
sizes = Size.objects.all()
tags = Tag.objects.all()
product = Product.objects.get(id=pk)
subCategories = SubCategory.objects.filter(category=product.category.id)
images = product.image.all()
if request.method == 'POST':
form = ProductForm(request.POST, instance=product)
if form.is_valid():
form.save()
return redirect('product-panel')
form = ProductForm(instance=product)
return render(request, 'public/views/backend/product-update.html', {'categories':categories,'subCategories':subCategories, 'sizes':sizes, 'tags':tags, 'form':form, 'images':images})

Django how to generate a filtered queryset

I have got 2 models. Asset and Asset_Type. In my asset_type detail view i would like to list all assets of that asset type. I think I have to use models.Asset.queryset().filter() but i can't get it to work.
On my template I would like to loop though the list with a 'for' (example: object in list) and print the values like this {{ object.name }}
models.py
class Asset(models.Model):
# Relationships
room = models.ForeignKey("asset_app.Room", on_delete=models.SET_NULL, blank=True, null=True)
model_hardware = models.ForeignKey("asset_app.Model_hardware", on_delete=models.SET_NULL, blank=True, null=True)
# Fields
name = models.CharField(max_length=30)
serial = models.CharField(max_length=30, unique=True, blank=True, null=True, default=None)
mac_address = models.CharField(max_length=30, null=True, blank=True)
purchased_date = models.DateField(null=True, blank=True)
may_be_loaned = models.BooleanField(default=False, blank=True, null=True)
notes = models.TextField(max_length=448, null=True, blank=True)
ip = models.CharField(max_length=90, null=True, blank=True)
created = models.DateTimeField(auto_now_add=True, editable=False)
last_updated = models.DateTimeField(auto_now=True, editable=False)
class Meta:
ordering = ["name"]
def __str__(self):
return str(self.name)
def get_absolute_url(self):
return reverse("asset_app_asset_detail", args=(self.pk,))
def get_update_url(self):
return reverse("asset_app_asset_update", args=(self.pk,))
class Asset_type(models.Model):
# Fields
name = models.CharField(max_length=30)
last_updated = models.DateTimeField(auto_now=True, editable=False)
created = models.DateTimeField(auto_now_add=True, editable=False)
notes = models.TextField(max_length=448, null=True, blank=True)
class Meta:
ordering = ["name"]
def __str__(self):
return str(self.name)
def get_absolute_url(self):
return reverse("asset_app_asset_type_detail", args=(self.pk,))
def get_update_url(self):
return reverse("asset_app_asset_type_update", args=(self.pk,))
class Model_hardware(models.Model):
# Relationships
asset_type = models.ForeignKey("asset_app.Asset_type", on_delete=models.SET_NULL, blank=True, null=True)
brand = models.ForeignKey("asset_app.Brand", on_delete=models.SET_NULL, blank=True, null=True)
# Fields
name = models.CharField(max_length=30)
notes = models.TextField(max_length=448, null=True, blank=True)
created = models.DateTimeField(auto_now_add=True, editable=False)
last_updated = models.DateTimeField(auto_now=True, editable=False)
class Meta:
ordering = ["name"]
def __str__(self):
return str(self.name) + " :: " + str(self.brand.name) + " :: " + self.asset_type.name
def get_absolute_url(self):
return reverse("asset_app_model_hardware_detail", args=(self.pk,))
def get_update_url(self):
return reverse("asset_app_model_hardware_update", args=(self.pk,))
views.py
class Asset_typeDetailView(generic.DetailView):
model = models.Asset_type
form_class = forms.Asset_typeForm
You can simply iterate over the related objects in the template by using the default related name which is the model name in lowercase with _set appended. So asset_type.model_hardware_set.all() will give you all Model_hardware instances related to Asset_type and similarly for model_hardware.asset_set.all():
{% for model_hardware object.model_hardware_set.all %}
{% for asset in model_hardware.asset_set.all %}
{{ asset.name }}
{% endfor %}
{% endfor %}
But this can become slow, since we run into the N + 1 problem that is for each model hardware we will be making queries to get it's assets. We can use prefetch_related_objects on your model instance to prefetch all the related objects (in fewer queries) this and make it faster:
from django.db.models import prefetch_related_objects
from django.views.generic import DetailView
class YourDetailView(DetailView):
model = Asset_type
template_name = '<your_template_name>.html'
def get_object(self, queryset=None):
obj = super().get_object(queryset=queryset)
prefetch_related_objects([obj], 'model_hardware__asset')
return obj
Note: Class names in python should ideally be in PascalCase not Some_case (Don't think there is any such convention as you make
here), hence ModelHardware instead of Model_hardware and
AssetType instead of Asset_type would be better names.

Django - How do I render a parent object in template?

I need to display some product's supplier, next to {{product.description}} but I can't get it to show on my table.
models.py
class Supplier(models.Model):
name = models.CharField(max_length=200, null=True)
phone = models.CharField(max_length=200, null=True, blank=True)
email = models.CharField(max_length=200, null=True, blank=True)
date_created = models.DateTimeField(auto_now_add=True, null=True)
def __str__(self):
return self.name
class Product(models.Model):
sku = models.IntegerField(null=True)
description = models.CharField(max_length=30)
costprice = models.FloatField(null=True, max_length=99, blank=True)
retailprice = models.FloatField(null=True, max_length=99, blank=True)
barcode = models.CharField(null=True, max_length=99, unique=True)
image = models.ImageField(null=True, blank=True)
supplier = models.ForeignKey(Supplier, on_delete=models.CASCADE, null=True)
def __str__(self):
return self.description
views.py
def products(request):
products = Product.objects.all()
suppliers = Supplier.objects.all()
context = {'products': products,
'suppliers': suppliers}
return render(request, 'crmapp/products.html', context)
products.html
<tr>
{% for product in products %}
<td>{{product.id}}</td>
<td><h6><strong>{{product.description}}</strong></h6></td>
<td >{{products.supplier}}</td>
<td>£{{product.costprice |floatformat:2}}</td>
<td>£{{product.retailprice |floatformat:2}}</td>
<td>{{product.barcode}}</td>
</tr>
{% endfor %}
Spelling mistake, I think.
<td >{{products.supplier}}</td>
Must be:
<td >{{product.supplier}}</td>
Notice I've removed the s in products.
Also, you don't need this in your views.py:
suppliers = Supplier.objects.all()
{{product.supplier}} will trigger a query to the db. To avoid that, use prefetch_related.
products = Product.objects.all().prefetch_related('supplier')
Note that this is optional. It will just improve efficency, but merely fixing the spelling mistake answers your question.

Django show extra content in class based view with ForeignKey models

I'm trying to add extra content to Djangos Class-based view to the template
I have some models like this
class District(models.Model):
district = models.CharField(max_length=255, null=False, unique=False, blank=True)
def __str__(self):
return self.district
class Street(models.Model):
street_name = models.CharField(max_length=255, null=False, unique=False, blank=True)
district = models.ForeignKey(District, verbose_name=_('district'), on_delete=models.CASCADE, null=True, blank=True)
zone = models.IntegerField(blank=True, null=True)
def __str__(self):
return self.street_name
class Article(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, blank=True, related_name="author", on_delete=models.SET_NULL)
timestamp = models.DateTimeField(auto_now_add=True)
status = models.CharField(max_length=1, choices=STATUS, default=CREATED)
comment = models.CharField(max_length=255, null=True, unique=False, blank=True)
name = models.CharField(max_length=255, null=True, unique=False)
street = models.ForeignKey(Street, verbose_name=_('street'), on_delete=models.CASCADE, null=True, blank=True)
class ArticlesListView(LoginRequiredMixin, PermissionRequiredMixin,ListView):
model = Article
paginate_by = 50
context_object_name = "articles"
permission_required = 'is_staff'
def get_context_data(self, *args, **kwargs):
context = super().get_context_data(*args, **kwargs)
context['Filter_name'] = Article.objects.order_by().values('name').distinct()
context['Filter_user'] = Article.objects.order_by().values('user').distinct()
return context
def get_queryset(self, **kwargs):
return Article.objects.all()
And late in the template
{% for f in Filter_name %}
<ul>
<li>{{f.name}}</li>
</ul>
{% endfor %}
How can I display a list of the district names and a list of the author names in the template with ForeignKey?
U can try something like that
{% for item in model_1.foreign_model_set.all %}
<h1>{{ item }}</h1>
{% endfor %}

Select a model instance from HTML form on Django

I am trying to get my html form to allow me to pass the company model instance. As of now, I can pull the names of each company instance, however, what would I put into the value attibute of the option field to have it select the instance correctly?
<option value="what to put here?">{{Company.name}}</option>
I was hoping to do this through HTML forms and not Django forms as I have used AJAX to make a nice little live-updating interface.
models.py
class Company(models.Model):
name = models.CharField(max_length=30, null=True, blank=True)
email = models.CharField(max_length=40, null=True, blank=True)
phone = models.CharField(max_length=15, null=True, blank=True)
address = models.CharField(max_length=100, null=True, blank=True)
notes = models.CharField(max_length=400, null=True, blank=True)
created = models.DateTimeField(auto_now_add=True, blank=True)
updated = models.DateTimeField(auto_now=True, blank=True)
class Meta:
ordering = ["name"]
def __str__(self):
return self.name
class Contact(models.Model):
firstname = models.CharField(max_length=20, null=True, blank=True)
lastname = models.CharField(max_length=20, null=True, blank=True)
email = models.CharField(max_length=40, null=True, blank=True)
phone = models.CharField(max_length=15, null=True, blank=True)
title = models.CharField(max_length=20, null=True, blank=True)
notes = models.CharField(max_length=400, null=True, blank=True)
company = models.ForeignKey(Company, on_delete=models.CASCADE, null=True, blank=True)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
class Meta:
ordering = ["lastname"]
def __str__(self):
return self.firstname
views.py
class contact_manager(ListView):
template_name = 'crm/contact_manager.html'
context_object_name = 'contact_manager'
queryset = Contact.objects.all()
def get_context_data(self, **kwargs):
context = super(contact_manager, self).get_context_data(**kwargs)
context['contact'] = Contact.objects.all()
context['company_list'] = Company.objects.all()
# And so on for more models
return context
contact_manager.html
<div class="form-group">
<select class="form-control" name="company" placeholder="Company">
<option value="">Please select a company</option>
{% for Company in company_list %}
<option value="{{Company.name}}">{{Company.name}}</option>
{% endfor %}
</select>
</div>
If you are looking for a unqiue identifier for each option, that links to a model instance on the backend, that is what the ID field is for (Company.id):
<option value="{{ Company.id }}">{{Company.name}}</option>
Then on the backend you can retrieve the model with the posted id:
Company.get(id=posted_id)
Note: id is by default added to your model as the primary key and is a auto incrememting integer.