Django sub models do not appear in template - python

Maybe I cannot see the forest because of all the trees, but I have a very strange issue.
views.py:
from django.shortcuts import render
from models import Question, QuestionAnswerAlloc, Section
def home(request):
sections = Section.objects.all()
for s in sections:
questions = Question.objects.filter(section=s)
for q in questions:
answersalloc = QuestionAnswerAlloc.objects.filter(question=q)
q.answers.append(answersalloc)
s.questions.append(questions)
return render(request, "questionaire/index.html", {'sections': sections})
models.py:
from django.db import models
from portal.models import Customer
class Section(models.Model):
title = models.CharField(max_length=150)
weight = models.FloatField()
maxscore = models.FloatField()
questions = []
def __unicode__(self):
return "%s" % (self.title)
class Question(models.Model):
title = models.TextField()
section = models.ForeignKey(Section)
weight = models.FloatField()
answers = []
def __unicode__(self):
return self.title
class Answer(models.Model):
title = models.CharField(max_length=150)
points = models.IntegerField(default=0, help_text="This has to be a value between 0 and 5")
is_weighted = models.BooleanField(default=True, help_text="If this answer does not apply (N/a) it is not weighted!")
def __unicode__(self):
return self.title
class QuestionAnswerAlloc(models.Model):
question = models.ForeignKey(Question)
answer = models.ForeignKey(Answer)
def __unicode__(self):
return "Possible Answer"
class Report(models.Model):
STATUS_STARTED = "started"
STATUS_FIN = "finished"
STATUS_INPROG = "inprogress"
STATUS_ABORT = "aborted"
date = models.DateField(auto_now_add=True, blank=True)
title = models.CharField(max_length=150)
started_time = models.DateTimeField()
end_time = models.DateTimeField()
status = models.CharField(max_length=150, default=STATUS_STARTED)
guid = models.CharField(max_length=150, unique=True)
def __unicode__(self):
return self.title
class ReportAnswer(models.Model):
title = models.CharField(max_length=150)
orignal_answer = models.ForeignKey(Answer)
question = models.ForeignKey(Question)
section = models.ForeignKey(Section)
report = models.ForeignKey(Report)
points = models.FloatField()
weight = models.FloatField()
is_weighted = models.BooleanField(default=True)
customer = models.ForeignKey(Customer, blank=True, null=True)
def __unicode__(self):
return self.title
And my template:
{% for s in sections %}
<div class="row">
<div class="col-sm-12">
<div class="FormStepInfo">
<p class="QuestionaireSectionTitle">{{s.title}}</p>
<p class="QuestionaireSectionDesc"></p>
</div>
</div>
</div>
{% for q in s.questions %}
<div class="row">
<hr/>
<div class="col-sm-2 quest-num">{{forloop.counter }}</div>
<div class="col-sm-10 quest-title">
<label>
{{q.title}}
</label>
<br/>
<div class="CheckboxQuestion">
{% for a in q.answers %}
<label for=""><input type="radio" name="Q3" value="{{a.points}}" id="q3a1">{{a.title}}</label>
{% endfor %}
</div>
</div>
</div>
{% endfor %}
{% endfor %}
Unfortunately, the question title is not shown, neither the answers.
If I print out to sys.stderr i can see that there are questions assigned to the section. Am I missing something? I have restarted my "webserver", as I am using "python manage.py runserver" about 10 times and deleted my cache.

You have a fairly large misunderstanding of class definitions in Python. Usually when you define an attribute at class level it is shared by all members of the class. Django fields do some special magic to ensure that the values are per-instance rather than per-class, but your questions and answers lists do not do that. So even if you could get your code to work, all the answers would be associated with all the questions.
Luckily there's no need to do any of this. Django provides you with reverse accessors that provide exactly what you need. So the view can be simplified to just:
def home(request):
sections = Section.objects.all()
return render(request, "questionaire/index.html", {'sections': sections})
and the view becomes:
{% for s in sections %}
...
{% for q in s.question_set.all %}
...
{% for a in q.questionansweralloc_set.all %}
...etc

Related

Django queryset filter based on slug

I want to put a filter on a page which shows videos selecting an album shows up on album page not all the videos but my current filter is showing all the published videos. I couldn't find a way to put a filter based on slug that if an album's slug is matching with the current url then shows the video selecting that album. For example:- Videos created by Gaurav should only visible on Gaurav’s album not anyone else. I am all confused help me.
models.py
from django.db import models
from django.urls import reverse
STATUS = (
(1, "Publish"),
(0, "Draft")
)
class WatchCategory(models.Model):
title = models.CharField(max_length=20)
slug = models.SlugField(max_length=2000, unique=True)
def __str__(self):
return self.title
class Genre(models.Model):
title = models.CharField(max_length=20)
slug = models.SlugField(max_length=2000, unique=True)
def __str__(self):
return self.title
class Album(models.Model):
title = models.CharField(max_length=2000)
slug = models.SlugField(max_length=2000, unique=True)
image = models.CharField(max_length=2000, blank=True)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('Watch:album', kwargs={
'slug': self.slug
})
class Video(models.Model):
title = models.CharField(max_length=2000)
slug = models.SlugField(max_length=2000, unique=True)
thumbnail = models.CharField(max_length=2000, unique=True)
updated_on = models.DateTimeField(auto_now=True)
file = models.CharField(max_length=2000)
time = models.CharField(max_length=2000, blank=True)
about = models.TextField(blank=True)
category = models.ManyToManyField(WatchCategory)
album = models.ManyToManyField(Album)
genre = models.ManyToManyField(Genre)
created_on = models.DateTimeField(auto_now_add=True)
status = models.IntegerField(choices=STATUS, default=1)
class Meta:
ordering = ['-created_on']
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('Watch:video', kwargs={
'slug': self.slug
})
views.py
class Album(ListView):
queryset = Video.objects.filter(status=1).order_by('-created_on')
template_name = 'Watch/album.html'
paginate_by = 6
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['title'] = 'Explore & Watch your favourite'
return context
album.html
{% extends "Watch/layout.html" %}
{% load static %}
{% block content %}
<div class="video-block section-padding">
<div class="row">
{% for video in video_list %}
<div class="col-xl-3 col-sm-6 mb-3">
<div class="video-card">
<div class="video-card-image">
<a class="play-icon" href="{% url 'Watch:video' video.slug %}"><i class="fas fa-duotone fa-circle-play"></i></a>
<img class="img-fluid" src="{{ video.thumbnail }}" alt="">
<div class="time">{{ video.time }}</div>
</div>
<div class="video-card-body">
<div class="video-title">
{{ video.title }}
</div>
</div>
</div>
</div>
{% endfor %}
</div>
</div>
{% endblock %}

how to use Exists and OuterRef in prefetch_related in Django?

I have 3 models and I need to display the area and need items only if there is at least 1 product connected. If there are no products in particular Area and Need models then it should not appear in my HTML file.
I have checked the documentation and several answers related to this topic but I cannot implement it in my script.
I also tried to create my custom filter so I can apply it directly in my template but nothing worked.
My problem is that I am getting the list of all items from Need model and I don't know how to exclude empty items from HTML page.
I will appreciate any help.
models.py
class Area(models.Model):
title = models.CharField(max_length=75, blank=False)
body = models.CharField(max_length=150, default='-', blank=False)
publish = models.DateTimeField('publish', default=timezone.now)
class Need(models.Model):
title = models.CharField(max_length=75, blank=False, null=False, help_text='max 75 characters')
body = models.CharField(max_length=150, default='-', blank=False)
publish = models.DateTimeField(default=timezone.now)
need_area = models.ForeignKey(Area, on_delete=models.CASCADE, related_name='need_area')
class ProductCategory(models.Model):
title = models.CharField(max_length=400, blank=False, null=False, help_text='max 400 characters')
body = models.TextField(default='-')
publish = models.DateTimeField('publish', default=timezone.now)
category_area = models.ForeignKey(Area, on_delete=models.CASCADE, related_name='category_area', null=True)
category_need = models.ForeignKey(Need, on_delete=models.CASCADE, related_name='category_need', null=True)
class Product(models.Model):
id = models.AutoField(primary_key=True)
title = models.CharField(max_length=400, blank=False)
category = models.ForeignKey(ProductCategory, on_delete = models.CASCADE, blank=True, related_name='products')
status = models.IntegerField(choices=STATUS, default=0)
def get_absolute_url(self):
return reverse("product", kwargs={'slug': self.slug})
views.py
class Search(ListView):
template_name = 'search.html'
model = Product
queryset = Product.objects.filter(status=1)
def get_context_data(self, **kwargs):
context = super(Search, self).get_context_data(**kwargs)
filter_need = Area.objects.filter(Exists(Need.objects.filter(need_area=OuterRef('pk'))))
areas = Area.objects.prefetch_related(Prefetch('need_area', queryset=filter_need, to_attr='need_area__category_need__product')).filter(need_area__category_need__product__status=1).distinct()
context['areas'] = areas
return context
search.html
{% if areas %}
{% for area in areas %}
<div class="border mb-4 pb-4 px-2">
<h2 class="fw-bold my-2">{{area.title}}</h2>
{% for need in area.need_area.all %}
<h4 class="text-muted mt-4">{{need.title}}:</h4>
{% for product_category in need.category_need.all %}
{% for product in product_category.product.all %}
<span class="rounded-pill bg-hubble text-dark f-12 p-2">{{product.title}}</span>
{% endfor %}
{% endfor %}
{% endfor %}
</div>
{% endfor %}
{% endif %}

Trouble getting related fields in ForeignKeys to show in Template

I'm working in Django 2.2 trying to build a view for a database that compiles everything for a specific company (locations of all of their stores and notes on the companies) into a single view. I've tried methods in several different answers, but still cannot seem to get data from related foreign keys to show in the template.
models.py
class Company(models.Model):
name = models.CharField(max_length=30, primary_key=True)
official_name = models.CharField(max_length=50)
corporate_address1 = models.CharField(max_length=50)
corporate_address2 = models.CharField(max_length=50)
city = models.CharField(max_length=60)
state_province = models.CharField(max_length=30)
country = models.ForeignKey('Country', on_delete=models.CASCADE)
slug = models.SlugField(max_length=30, unique=True)
def __str__(self):
return self.name
class Stores(models.Model):
store_name = models.CharField(max_length=30, primary_key=True)
owner = models.ForeignKey('Company', on_delete=models.CASCADE)
store_address1 = models.CharField(max_length=50)
store_address2 = models.CharField(max_length=50)
city = models.CharField(max_length=60)
state_province = models.CharField(max_length=30)
country = models.ForeignKey('Country', on_delete=models.CASCADE)
type = models.CharField(max_length=30,choices=store_types)
slug = models.SlugField(max_length=30, unique=True)
def get_absolute_url(self):
return reverse("store-detail", kwargs={"slug": self.slug})
class notes(models.Model):
title = models.CharField(max_length=120)
content = models.TextField()
posted = models.DateTimeField(db_index=True, auto_now_add=True)
category = models.ForeignKey('Company', on_delete=models.CASCADE)
active = models.BooleanField(default=True)
def get_absolute_url(self):
return reverse("article-detail", kwargs={"id": self.id})
class Country(models.Model):
country = models.CharField(max_length=30,choices=countries,primary_key=True)
class Meta:
ordering = ["-country"]
db_table = 'country'
def __str__(self):
return self.country
views.py
class CompanyOverView(LoginRequiredMixin, DetailView):
model = Company
template_name = "company-overview.html"
slug_url_kwarg = 'slug'
query_pk_and_slug = True
pk_url_kwarg = "company.name"
template
<div align="center">
<p>{{ object.name }}<br>({{ object.official_name }})</p>
<p>{{ object.corporate_address1 }}<br>{{ object.corporate_address2 }}<br>
{{ object.city }}<br>{{ object.state_province }}<br>
{{ object.country }}</p>
</div>
<p>List of Stores</p>
<p>
{% for instance in object_list %}
{{ instance.company.stores.store_name }}
{{ instance.company.stores.store_address1 }}
{{ instance.company.stores.store_address2 }}
{{ instance.company.stores.city }}
{{ instance.company.stores.state_province }}
{{ instance.company.stores.country }}
{% endfor %}
</p>
<p>Notes</p>
<p>
{% for instance in object_list %}
{{ instance.company.notes.title }}
{{ instance.company.notes.posted }}
{% endfor %}
</p>
With the above code, the only thing that appears when you enter in the company's name is everything at the top (e.g."object.name" appears on the page as "Acme Corporation"). Nothing in the for loop appears on the web page.
Looking at the documentation, object_list is the default name for context unless specified. I have tried different combinations such as "for store_name in company.store_set.all" and other combinations I found in other posts, but none have worked. I've combed the documentation for everything related to foreign keys, but can't find a solution that works.
Thanks in advance if you can help.
No. object_list is the default context name in a ListView. But you have a DetailView, and you already know what the default context name is for those because you're already using it: object. You just need to iterate over the reverse relation from there:
{% for store in object.stores_set.all %}
{{ store.store_name }}
{{ store.store_address1 }}
...
{% endfor %}

output from different models in Django

I'm new in Django. And I have a problem((I can't display fields from different models. A lot of time was executed, but don't understand.
Here is my code.
This is my models:
from django.db import models
class Abonent(models.Model):
osrah = models.IntegerField(db_column='Osrah', primary_key=True)
pib = models.CharField(db_column='PIB', max_length=70)
adress = models.CharField(db_column='Adress', max_length=70)
meter = models.IntegerField(db_column='Meter')
date = models.DateField(blank=True, null=True)
created = models.DateTimeField(auto_now_add=True, auto_now=False)
updated = models.DateTimeField(auto_now_add=False, auto_now=True)
def __str__(self):
return "%s " % (self.pib)
class Oplata(models.Model):
abonent = models.ForeignKey(Abonent, db_column=False, blank=True,
null=True, default=None,on_delete=models.CASCADE)
idoplata = models.AutoField(primary_key=True)
from_date = models.DateField()
saldo = models.FloatField()
idstala = models.IntegerField(db_column='idStala')
created = models.DateTimeField(auto_now_add=True, auto_now=False)
updated = models.DateTimeField(auto_now_add=False, auto_now=True)
def __str__(self):
return "%s " % ( self.saldo,)
class Rahunok(models.Model):
abonent = models.ForeignKey(Abonent, blank=True, null=True,
default=None,on_delete=models.CASCADE)
idrahunok = models.AutoField(db_column='idRahunok', primary_key=True)
idstala = models.IntegerField(db_column='idStala')
datarah = models.DateField(db_column='dataRah')
pokaz1 = models.FloatField()
pokaz2 = models.FloatField()
spozkwt = models.FloatField(db_column='SpozKWT')
spozuah = models.FloatField(db_column='SpozUAH')
created = models.DateTimeField(auto_now_add=True, auto_now=False)
updated = models.DateTimeField(auto_now_add=False, auto_now=True)
class Meta:
managed = False
db_table = 'rahunok'
And this my url.py:
from django.conf.urls import url, include
from django.views.generic import ListView, DetailView
from abonent.models import Abonent,Oplata
urlpatterns = [
url(r'^$',ListView.as_view(queryset=Abonent.objects.all(),
template_name="abonent/abonents.html")),
url(r'^(?P<pk>\d+)', DetailView.as_view(model=Abonent,
template_name='abonent/persons.html')),
it's my person.html:
{% extends "mainApp/wrapper.html"%}
{% block content %}
<h2 class="text-info">{{ abonent.pib }}</h2>
<h2 class="text-info">{{ abonent.oplata.saldo }}</h2>
<h2 class="text-info">{{ abonent.oplata_set.idstala}}</h2>
<h5 class=" text-info">{{ abonent.adress }}</h5>
{% endblock %}
From model Abonent picks out everything, and doesn't want from Oplata.
What is the problem?
Would be very grateful if someone helps.
Django's DetailView by default puts the object in a key called object
def get_context_data(self, **kwargs):
"""
Insert the single object into the context dict.
"""
context = {}
if self.object:
context['object'] = self.object
context_object_name = self.get_context_object_name(self.object)
if context_object_name:
context[context_object_name] = self.object
context.update(kwargs)
return super(SingleObjectMixin, self).get_context_data(**context)
As you can see, you now have the object in context as the key object
Change your template to the following to make it work:
{% extends "mainApp/wrapper.html"%}
{% block content %}
<h2 class="text-info">{{ object.pib }}</h2>
<h2 class="text-info">{{ object.oplata.saldo }}</h2>
<h2 class="text-info">{{ object.oplata_set.idstala}}</h2>
<h5 class=" text-info">{{ object.adress }}</h5>
{% endblock %}

How can I filter and count objects in DJANGO template?

Hello I justa want to ask this because Im new in django, my trouble is that i want to count how many comments have a post and put it in to the html template.
But the thing is that im using for to gather all the events in the db, but i just want to show only the count of comments that have every event that the "for" are showing.
this is my models, view, and template.
Thank you so much.
MODELS
class Event(TimeStampModel):
name = models.CharField(max_length=200, unique=True)
slug = models.SlugField(editable=False)
summary = models.TextField(max_length=255)
content = models.TextField()
category = models.ForeignKey(Category)
place = models.CharField(max_length=50)
start = models.DateTimeField()
finish = models.DateTimeField()
image = models.ImageField(upload_to = 'eventos')
is_free = models.BooleanField(default=True)
amount = models.DecimalField(max_digits=6, decimal_places=0, default=0)
views = models.PositiveIntegerField(default=0)
organizer = models.ForeignKey(settings.AUTH_USER_MODEL, blank=True, null=True)
def save(self, *args, **kwargs):
if not self.id:
self.slug = slugify(self.name)
super(Event, self).save(*args, **kwargs)
def __unicode__(self):
return self.name
class Comments(TimeStampModel):
user = models.ForeignKey(settings.AUTH_USER_MODEL)
event = models.ForeignKey(Event)
content = models.TextField()
def __unicode__(self):
return "%s %s" % (self.user.username, self.event.name)
VIEW
class IndexView(TemplateView):
template_name = 'eventos/index.html'
def get_context_data(self, **kwargs):
context = super(IndexView, self).get_context_data(**kwargs)
context['events'] = Event.objects.all().order_by('-created')[:6]
context['categories'] = Category.objects.all()
context['comments'] = Comments.objects.all()
return context
HTML TEMPLATE
{% for event in events %}
<li class="span4 ">
<div class="thumbnail thumbnail-1">
<h3 class="titulo-fix" >{{ event.name }}</h3>
<img class="center-cropped" src="{{ event.image.url }}" alt="">
<section>
<h3>{{ event.category }} </h3>
<div class="meta">
<time datetime="2012-11-09" class="date-1"><i class="icon-calendar"></i> {{ event.start }}</time>
<div class="name-author"><i class="icon-user"></i> {{ event.organizer }}</div>
<i class="icon-comment"></i> comments
</div>
<div class="clear"></div>
<p>{{ event.place }}</p>
Leer mas..
</section>
</div>
</li>
{% endfor %}
I want to show it just in that part of the html where it says comments.. with a tag of course, but i just dont know wich tag or how to do it.
You can create a helper method on the model which can help you show the number of comments.
Something like this:
class Event(TimeStampModel):
...
def comments_count(self):
#Your filter criteria can go here.
return self.comments_set.count()
and in the comments:
{{event.comments_count}}
More documentation on the reverse lookups can be found here
If you are not filtering, as, #MadWombat mentions, you could just do
{{event.comments_set.count}}

Categories

Resources