Display ForeignKey attributes in template - django

I have the following models:
# models.py
class Site(models.Model):
name = models.CharField(max_length=75)
slug = models.SlugField(_('slug'), max_length=75, blank=True, null=True)
link = models.CharField(max_length=150)
created_on = models.DateTimeField(auto_now_add=True, editable=False)
modified_on = models.DateTimeField(auto_now=True)
class SiteRatings(models.Model):
site = models.ForeignKey('Site', related_name='siterating', blank=True, null=True)
overall_rating = models.FloatField(blank=True, null=True)
plans_rating = models.FloatField(blank=True, null=True)
prices_rating = models.FloatField(blank=True, null=True)
design_rating = models.FloatField(blank=True, null=True)
support_rating = models.FloatField(blank=True, null=True)
def save(self, *args, **kwargs):
self.overall_rating = (self.plans_rating + self.prices_rating + self.design_rating + self.support_rating)/4
super(SiteRatings, self).save(*args, **kwargs)
def __str__(self):
return self.site.name
My views
# views.py
def home(request):
print(user_language)
site_list = Site.objects.order_by('-date_launched')
return render_to_response('index.html', {'site_list': site_list}, RequestContext(request))
In template
# template
{% for site in site_list %}
<h4><span class="label label-info">{{ site.name }}</span></h4>
<h4><span class="label label-info">{{ site.siterating.overall_rating }}</span></h4>
{% endfor % }
The problem is that when I try to access {{ site.siterating.overall_rating }} nothing is being returned, I tried to change for {{ site.siterating.0.overall_rating }} and it is not displaying yet.

I solved my problem. First in models I created a method to get the site rating (thank you karthikr for your suggestion):
#models
class Site(models.Model):
name = models.CharField(max_length=75)
slug = models.SlugField(_('slug'), max_length=75, blank=True, null=True)
link = models.CharField(max_length=150)
created_on = models.DateTimeField(auto_now_add=True, editable=False)
modified_on = models.DateTimeField(auto_now=True)
def get_site_rating(self):
return self.siterating.filter(site = self)
After, I went to my template and used the class method that I had created:
{% for site in site_list %}
<h4><span class="label label-info">{{ site.name }}</span></h4>
<h4><span class="label label-info">{{ site.get_site_rating.0.overall_rating }}</span></h4>
{% endfor % }
Please, note that I used ...get_site_rating.0... just because in my case I have just 1 rating/site.

Related

Django render many to many in template

I have this models:
class roles(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
name = models.CharField(max_length=255, blank=False)
company = models.ForeignKey(Company, blank=True, null=True, on_delete=models.SET_NULL)
def __str__(self):
return self.name
class freelancers(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
company = models.ForeignKey(Company, blank=True, null=True, on_delete=models.SET_NULL)
user = models.ForeignKey(User, blank=True, null=True, on_delete=models.SET_NULL)
role = models.ManyToManyField(roles)
I try to get the name that is related to the user at the roles table.
In my view.py It looks like this:
def company_details(request,id):
obj = Company.objects.get(id=id)
pro = Projects.objects.filter(company=id)
free = freelancers.objects.filter(company=id)
#free = freelancers.objects.all()
return render(request, 'company/company_details.html',
{
'obj':obj,
'pro':pro,
'free':free,
}
)
And in the HTML:
{% for f in free %}
{{ f.user }} // <br/>
{% endfor %}
{{ f.role.all }}
{% endfor %}
I have been trying different ways to get the name to show up.
Like: {{ f.role.name }}.
So any tips to make this work?
I think you will have to iterate through the f.role.all

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 %}

Django - Annotation not showing in template

I'm trying to get annotations showing in my templates. I have two models (model1 and model2) and I want to show the number of model2's related to model1.
Here is my views.py:
def model2_count(request, pk):
model2count = models.Model1.objects.filter(pk=model1.pk).annotate(title_count=Count(‘model2__title'))
return render(request, 'model1/_model1.html', {‘m2c’: model2count})
Here is the template (model1/_model1.html):
I tried this:
{% for object in m2c %}</h3>
{{ object.title }}
{{ object.title_count }}
{% endfor %}
And tried this:
{% if m2c.title_count %}
{{ m2c.title_count }}
{% endif %}
I've been pulling my hair out over this for a couple days and can't figure it out. The following has been largely unhelpful:
Django - Annotating Weighted AVG by Group
Django: Annotation not working?
Django templates are not showing values of annotations
Django annotated value in template
What's frustrating is that I can't even say why applying these solutions hasn't worked.
Any input is appreciated.
Also, here are my models with all the BS taken out.
class Publication(models.Model):
title = models.CharField(max_length=150, unique=False, blank=False)
contributors_note = models.TextField(max_length=300, blank=False)
website = models.URLField()
publisher = models.CharField(max_length=250, unique=False)
publication_date = models.DateField(default=datetime.date.today)
slug = models.SlugField(allow_unicode=True, unique=False)
content_type = models.CharField(max_length=100, unique=False)# In this field user's define the type of content (blog, newspaper article, publication etc)
research_type = models.CharField(max_length=100, unique=False)# In this field user's define whether the research is based on primary or secondary research
user = models.ForeignKey(Current_user, related_name="publication")
created_at = models.DateTimeField(auto_now_add=True)
last_updated = models.DateTimeField(auto_now=True)
category = models.ForeignKey(Category, related_name="publication",null=True, blank=False)
comment = models.TextField()
def __str__(self):
return self.title
def save(self, *args, **kwargs):
self.slug = slugify(self.title)
super().save(*args, **kwargs)
def get_absolute_url(self):
return reverse(
"publication:single",
kwargs={
"username": self.user.username,
"pk": self.pk
}
)
class Meta:
ordering = ["-created_at"]
class Assessment(models.Model):
title = models.CharField(max_length=150, unique=False, blank=False)
publication = models.ForeignKey('publication.Publication', on_delete=models.CASCADE, related_name='assessment')
analyst = models.ForeignKey(Current_user, null=True, blank=True, related_name="assessment")
created_at = models.DateTimeField(auto_now_add=True)
approved_comment = models.BooleanField(default=False)
key_finding1 = models.TextField(max_length=300)
key_finding2 = models.TextField(max_length=300)
key_finding3 = models.TextField(max_length=300)
ratings_range = (
('1', 'Very Weak'),
('2', 'Weak'),
('3', 'Moderate'),
('4', 'Strong'),
('5', 'Very Strong'),
)
content_rating_1 = models.CharField(max_length=1, choices=ratings_range)
content_rating_1_comment = models.TextField(max_length=300)
content_rating_2 = models.CharField(max_length=1, choices=ratings_range)
content_rating_2_comment = models.TextField(max_length=300)
content_rating_3 = models.CharField(max_length=1, choices=ratings_range)
content_rating_3_comment = models.TextField(max_length=300)
content_rating_4 = models.CharField(max_length=1, choices=ratings_range)
content_rating_4_comment = models.TextField(max_length=300)
content_rating_5 = models.CharField(max_length=1, choices=ratings_range)
content_rating_5_comment = models.TextField(max_length=300)
source_rating_1 = models.CharField(max_length=1, choices=ratings_range)
source_rating_1_comment = models.TextField(max_length=300)
source_rating_2 = models.CharField(max_length=1, choices=ratings_range)
source_rating_2_comment = models.TextField(max_length=300)
source_rating_3 = models.CharField(max_length=1, choices=ratings_range)
source_rating_3_comment = models.TextField(max_length=300)
source_rating_4 = models.CharField(max_length=1, choices=ratings_range)
source_rating_4_comment = models.TextField(max_length=300)
source_rating_5 = models.CharField(max_length=1, choices=ratings_range)
source_rating_5_comment = models.TextField(max_length=300)
def approve(self):
self.approved_comment = True
self.save()
def __str__(self):
return self.title
class Meta:
ordering = ["-created_at"]
Bad mistake on my part. The solution's given above worked. Here is my final code:
views.py
class PublicationDetail(SelectRelatedMixin, generic.DetailView):
model = models.Publication
select_related = ("category", "user")
def get_queryset(self):
queryset = super().get_queryset()
return queryset.filter(user__username__iexact=self.kwargs.get("username")).annotate(assessment_count=Count('assessment'))
Fellow noobs that follow:
- It's easier for the people that want to help you (and faster for you) if you just post your original code instead of trying to get smart. Don't be embarrassed. I would've saved us all time if I had just done that.
First aggregations are done only using the field name i.e model2 not model2__title
Next getting counts of annotated columns recommended to use .values or values_list but not required.
https://docs.djangoproject.com/es/2.1/topics/db/aggregation/#cheat-sheet
model1 = Model1.objects.get(pk=model1.pk)
model2count = (
Model1.objects.annotate(count=Count('model2'))
.filter(pk=model1.pk)
.values_list('title', 'count', named=True)
)
template.html
{% for object in model2count %}
{{ object.title }}
{{ object.count }}
{% endfor %}

Django odd boolean bahavior

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))

Displaying many-to-many subsets with different names? in Django template

I plan to get rid of the related name the next time I rebuild the database...the models I am using are more of test-models. So, with Class Creator and the writer, cover_artist, etc., how would I go about displaying the issues that Creator has created (once I get rid of the related name, unless there's a way to go around it)?
class Creator(models.Model):
name = models.CharField(max_length=256)
desc = models.TextField("description", blank=True, null=True)
#type = writer, artist, editor, letterer
slug = models.SlugField(blank=True, null=True)
def __unicode__(self):
return self.name
class Meta:
ordering = ['name']
def get_absolute_url(self):
return "/comics2/creators/%s" % self.slug
class Issue(models.Model):
....
writer = models.ManyToManyField(Creator, related_name="written by", help_text="Use cmd/ctrl + click to select multiple names. The same applies to the rest of the creators below.", blank=True, null=True)
artist = models.ManyToManyField(Creator, related_name="drawn by", blank=True, null=True)
cover_artist = models.ManyToManyField(Creator, related_name="cover drawn by", blank=True, null=True)
colorist = models.ManyToManyField(Creator, related_name="colored by", blank=True, null=True)
inker = models.ManyToManyField(Creator, related_name="inked by", blank=True, null=True)
penciller = models.ManyToManyField(Creator, related_name="pencilled by", blank=True, null=True)
letterer = models.ManyToManyField(Creator, related_name="lettered by", blank=True, null=True)
editor = models.ManyToManyField(Creator, related_name="edited by", blank=True, null=True)
arc = models.ManyToManyField(Arc, related_name="related story arc", blank=True, null=True)
...
def __unicode__(self):
return u'%s %s' % (self.title, self.number)
def get_absolute_url(self):
return "/comics2/issues/%s" % self.slug
class Meta:
ordering = ['title', 'number']
def get_stars(self):
star_rating = self.rating * 16
return star_rating
....
{% for issue in creator.____?__.all %}
<ul>
<li>{{ issue }}</li>
</ul>
{% endfor %}
Is not going to work.
Thanks.
I would suggest changing your models.py to have Issue have a Many to Many relationship to Creator through another table, e.g. Role. See docs here.
class Creator(models.Model):
name = models.CharField(max_length=256)
desc = models.TextField("description", blank=True, null=True)
slug = models.SlugField(blank=True, null=True)
def __unicode__(self):
return self.name
class Meta:
ordering = ['name']
def get_absolute_url(self):
return "/comics2/creators/%s" % self.slug
class Issue(models.Model):
creators = models.ManyToManyField(Creator, through='Role')
arc = models.ManyToManyField(Arc, related_name="related story arc", blank=True, null=True)
...
def __unicode__(self):
return u'%s %s' % (self.title, self.number)
def get_absolute_url(self):
return "/comics2/issues/%s" % self.slug
class Meta:
ordering = ['title', 'number']
def get_stars(self):
star_rating = self.rating * 16
return star_rating
class Role(models.Model):
issue = models.ForeignKey(Issue)
creator = models.ForeignKey(Creator)
role = models.CharField()
...
edit:
in your issues view, you would get the different roles and pass it to your template (for example):
def issue_detail(request, issue_slug=None):
issue = get_object_or_404(Issue, slug=creator_slug)
writers = issue.creators.filter(role__role='writer')
cover_artists = issue.creators.filter(role__role='cover artist')
...
context = { 'issue': issue,
'writers': writers,
'cover_artists': cover_artists,
...
}
return render_to_response('issue_detail.html', context,
context_instance=RequestContext(request))
template:
<label>Writers</label>
{% for writer in writers %}
{{ writer }}
{% endfor %}
<label>Cover Artists</label>
{% for cover_artist in cover_artists %}
{{ cover_artist }}
{% endfor %}
creator view:
def creator_detail(request, issue_slug=None):
creator = get_object_or_404(Creator, slug=issue_slug)
issues_as_writer = creator.issue_set.filter(role__role='writer')
issues_as_cover_artists = creator.issue_set.filter(role__role='cover artist')
#all issues related to this creator
all_issues = creator.issue_set.all()
...
context = { 'creator': creator,
'issues_as_writer': issues_as_writer,
'issues_as_cover_artist': issues_as_cover_artist,
...
'all_issues': all_issues,
}
return render_to_response('creator_detail.html', context,
context_instance=RequestContext(request))