I am trying to setup a relation with another model using FK in django but I can't call FK related model fields in django templates. In template when I call "provider.name" it shows me "None" as result. I do have 5 different suppliers listed and can see from admin. I have providers and I got products like below:
class Product(models.Model):
title = models.CharField(max_length=500)
description = models.TextField(blank=True, null=True)
price = models.DecimalField(max_digits=20, decimal_places=2)
sku = models.CharField(null=True, max_length=100)
url = models.URLField(blank=True)
slug = models.SlugField(unique=True)
providers = models.ManyToManyField('Provider', blank=True)
def __unicode__(self):
return self.title
class Provider(models.Model):
name = models.CharField(max_length=200)
description = models.TextField(null=True, blank=True)
logo = models.ImageField(upload_to='products/')
shipping_method = models.CharField(max_length=250)
shipping_time = models.CharField(max_length=250)
return_policy = models.CharField(max_length=200)
free_delivery = models.CharField(max_length=200)
customer_service_number = models.CharField(max_length=200)
shipping_charges = models.CharField(max_length=200)
def __unicode__(self):
return self.name
In template the way I am calling it is:
{% with provider=object.providers %}
{{ provider.name }}
{% endwith %}
As result it shows "None". I am trying to call provider in a different template. In it's own List/Detail generic views it works just fine. I am trying to call it in different app templates. Please advise.
Update................
My search.html for whoosh search engine includes
{% for result in page.object_list %}
<div class="col-lg-1-5 col-md-3 col-sm-4 col-xs-12">
<div class="pbox">
<div class="photo">
<img src="{{ result.object.get_image_url }}" alt="product">
</div>
<div class="info">
<div class="url">
name
{% for item in result.object.providers.all %}
{{ result.provider.name }}
{% endfor %}
</div>
<div class="description">
{{ result.object.description|truncatewords:7 }}
</div>
<div class="price">
{{ result.object.price|intcomma }}
</div>
</div>
</div>
</div>
As I am not using any ModelManager or just using default Managers pre-defined for models. I've added a line of code under Product App model like this:
def get_provider(self):
item = self.providers.all()
return item
I case of calling provider you call related manager so it return None because manager have no method like this.
If you want to retrieve objects from managers, you should call self.providers.all()
In your case, template tags should looks like this:
{% for item in object.providers.all %}
{{ provider.name }}
{% endfor %}
Related
In my Django project, I am trying to create a website that streams TV shows. Each show belongs in many categories, hence the use of many to many relations in my model. What I want to do with a certain page on my website is dynamically load a page of shows belonging to a specific category. However, all of my attempts have ended in failure as I am unable to figure out a way on how to access the actual category data from each show.
In views.py
def shows_in_category(request, category_slug):
category = get_object_or_404(Category, slug=category_slug)
showsall = theShow.objects.all()
shows = []
for show in showsall:
print(show.category.name, category.name)
if show.category.name == category.name:
shows.append(show)
print(shows)
return render(request, 'show/show_list_view.html', {'category':category, 'shows': shows})
In models.py
class Category(models.Model):
name = models.CharField(max_length=255, db_index=True)
slug = models.SlugField(max_length=255, unique=True)
class Meta:
verbose_name_plural = 'Categories'
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse("theshowapp:shows_in_category", args=[self.slug])
class theShow(models.Model):
english_name = models.CharField(max_length=400)
show_type = models.CharField(max_length=200, blank=True)
is_active = models.BooleanField(default=False)
category = models.ManyToManyField(Category)
slug = models.SlugField(max_length=400,unique=True)
class Meta:
verbose_name_plural = 'Shows Series'
def __str__(self):
return self.english_name
In the template (show_list_view.html)
{% for show in shows %}
<script> console.log("I'm trying to get in")</script>
<script> console.log("{{ show.name }} {{show.category.name}}")</script>
<script> console.log("I'm in")</script>
<div class="row">
<div class="col-lg-4 col-md-6 col-sm-6">
<div class="product__item">
<div class="product__item__text">
<ul>
{% for genre in show.category %}
<li>{{ show.category }}</li>
{% endfor %}
</ul>
<h5>{{ show.english_name }}</h5>
</div>
</div>
</div>
</div>
{% endfor %}
Any insight on this matter would be much appreciated.
What you're doing here violates some of the best practices of Django and also isn't using the Django ORM to its full potential. Please replace the lines
showsall = animeShow.objects.all()
shows = []
for show in showsall:
print(show.category.name, category.name)
if show.category.name == category.name:
shows.append(show)
print(shows)
with
shows = animeShow.objects.filter(category__name=category.name)
Also in the template change <li>{{ show.category }}</li> to <li>{{ genre }}</li> since that's the iterating variable.
I read up a bit more on the many to many fields examples in Django's documentation and figured out that I should use this:
shows = animeShow.objects.all().filter(category__name=category)
I am trying to ad a condition into an html model in Django (python) and it is not working:
This is my HTML:
<p class="card-text text-muted h6">{{ post.author }} </p>
{% if post.author == 'John_Woo' %}
<p class="card-text text-muted h6"> NOK </p>
{% else %}
<p class="card-text text-muted h6"> ok </p>
{% endif %}
Not sure what is wrong here...
Even though I have a John_Woo author, I only get ok message
This is my models.py:
class Post(models.Model):
title = models.CharField(max_length=200, unique=True)
slug = models.SlugField(max_length=200, unique=True)
author = models.ForeignKey(User, on_delete= models.CASCADE,related_name='blog_posts')
This is my views.py:
from django.views import generic
from .models import Post
class PostList(generic.ListView):
queryset = Post.objects.filter(status=1).order_by('-created_on')
template_name = 'index.html'
class PostDetail(generic.DetailView):
model = Post
template_name = 'post_detail.html'
Post.author returns class's representation like(str, unicode, repr) function. You have to override this functions which is depends on your django version. But you have one way to compare this. Like if Post.author.first_name == "John_Woo"
You want post.author.name (where .name is whatever field of an User object that will sometimes contain the string 'John_Woo' )
Im a newbie working on a news site (or at least trying to, a lot of "problems" in the last few days lol ) trying to learn Django the best I can.
This is what I want to do :
I have an Article Model, it used to have 6 image fields that I used to send to the template and render the images, each image field had its own name and all was well in the world.
Then I got tasked with puting the Article images in a separate Image model.
So I did this :
class Article(models.Model):
title = models.CharField('title', max_length=200, blank=True)
slug = AutoSlugField(populate_from='title', default="",
always_update=True, unique=True)
author = models.CharField('Author', max_length=200, default="")
description = models.TextField('Description', default="")
is_published = models.BooleanField(default=False)
article_text = models.TextField('Article text', default="")
pub_date = models.DateTimeField(default=datetime.now, blank=True)
article_category = models.ForeignKey(Category, on_delete="models.CASCADE", default="")
def __str__(self):
return self.title
class ArticleImages(models.Model):
article = models.ForeignKey(Article, on_delete="models.CASCADE", related_name="image")
image = models.ImageField("image")
name = models.CharField(max_length=50, blank=True)
But so far I wasnt able to access my images in my template using
{{ article.image.url }} or {{ article.image.image.url }}
or any other combination. Why is that ?
Did I set up my models correctly ? One person suggested that I should change the model field from ForeignKey to OneToOneField, but I didn't get much feedback on why and how ?
So, how would I make a for loop that loops through the Articles model and then gets the related images for each Article ? I essentially want it to behave like I still have the 6 different fields like I did before. ( I have to do it this way, it's a part of the task ).
here are my views and my "index" template that I used to loop through the Articles and display 6 latest news on my home page. (please ignore the tags,I am aware they aren't working like this..the template is just so you can understand what I am talking about )
my views.py:
class IndexView(generic.ListView):
template_name = 'news/index.html'
context_object_name = 'latest_article_list'
def get_queryset(self):
return Article.objects.all()
class CategoryView(generic.ListView):
template_name = 'news/categories.html'
context_object_name = 'category'
def get_queryset(self):
return Article.objects.filter(article_category__category_title="Politics")
class ArticlesView(generic.ListView):
context_object_name = 'latest_article_list'
template_name = 'news/articles.html'
paginate_by = 5
def get_context_data(self, **kwargs):
context = super(ArticlesView, self).get_context_data(**kwargs)
context['categories'] = Category.objects.all()
return context
def get_queryset(self):
category_pk = self.request.GET.get('pk', None)
if category_pk:
return Article.objects.filter(article_category__pk=category_pk).order_by("-pub_date")
return Article.objects.order_by("-pub_date")
def article(request, article_id):
article = get_object_or_404(Article, pk=article_id)
context = {'article': article,
'article_category': article.article_category.category_title}
return render(request, 'news/article.html', context)
template that I used with my old model :
{% for article in latest_article_list %}
<img class="single-article-img" src="{{ article.image.name.url }}" alt="">
<div class="container row">
<!-- Start Left Blog -->
<div class="article mt-10 col-md-4 col-sm-4 col-xs-12">
<div class="single-blog" style="margin:10px auto;">
<div class="single-blog-img">
<a href="{% url 'news:article' article.id %}#article-title">
<img class="for-imgs" src="{{ article.image.url }}" alt="">
</a>
</div>
<div class="blog-meta">
<span class="date-type">
<i class="fa fa-calendar"></i>{{ article.pub_date }}
</span>
</div>
<div class="xx blog-text">
<h4>
{{ article.title }}
</h4>
<p>
{{ article.description|truncatewords:30 }}
</p>
</div>
<span>
Read more
</span>
</div>
</div>
{% endfor %}
Thank you !
You need to loop over the images as you have many images against a single article object. You can have something like below to show images in your template:
{% if latest_article_list.articleimages %}
{% for articleimage in latest_article_list.articleimages.all %}
<img src="{{ articleimage.image.url }}" class="d-block w-100" alt="...">
{% endfor %}
{% endif %}
I created a custom plugin for my project in Django/Django-CMS and the plugin has a list of testimonials that the user pick when adding the plugin to the page. The model is this:
class TestimonialsPlugin(CMSPlugin):
n_testimonials = models.PositiveIntegerField(
verbose_name=_('Number of Testimonials'), default=5)
speed_autoplay = models.PositiveIntegerField(
verbose_name=_('Speed of slider (milliseconds)'), default=3000)
picked_testimonials = models.ManyToManyField(Testimonials,
verbose_name=_('picked_testimonials'),
blank=True, null=True)
In the edit mode I can se the testimonials in my page and I can publish without errors but when I see the published page the testimonials doesn't show. The plugin template is being rendered but the picked_testimonials gives None. Here's the template:
<div class="max-width1440 block clearfix relative">
<div class="small-only-text-left small-12 small-offset-0 medium-text-center medium-offset-1 medium-10 large-offset-1 large-10 column pt-px60 pb-px40 pl-px40 pr-px40 slider-testimonials">
{% for testimonial in instance.picked_testimonials.all %}
{% if forloop.counter0 < instance.n_testimonials %}
<div class="slider column">
<blockquote class="acta_mediumitalic size36 pl-px80 pr-px80 line-height140">
{% render_model testimonial "description" %}
</blockquote>
<div class="mt-px30">
<p class="acta_book size20 softblack">{{ testimonial.author }},<span>{{ testimonial.city }}</span>
</p>
</div>
</div>
{% endif %}
{% endfor %}
</div>
</div>
When a page is published, a copy of a plugin is created - which does include plugin's fields but not any relations. There is a provision in the CMS to provide copy method for exactly this purpose, see example from documentation:
class ArticlePluginModel(CMSPlugin):
title = models.CharField(max_length=50)
sections = models.ManyToManyField(Section)
def copy_relations(self, oldinstance):
self.sections = oldinstance.sections.all()
The important bit is the copy_relations, which ensures that the new object has the same relational links.
In your case, something along these lines should work:
class TestimonialsPlugin(CMSPlugin):
n_testimonials = models.PositiveIntegerField(
verbose_name=_('Number of Testimonials'), default=5)
speed_autoplay = models.PositiveIntegerField(
verbose_name=_('Speed of slider (milliseconds)'), default=3000)
picked_testimonials = models.ManyToManyField(Testimonials,
verbose_name=_('picked_testimonials'),
blank=True, null=True)
def copy_relations(self, oldinstance):
self.picked_testimonials = oldinstance.picked_testimonials.all()
First, I have to say that is this my first application in Django. So my knowledge is still limited.
I have this home page where it shows all the data in my model. The model name is "Asset".
I am trying to have a search field inside the home page.
models.py
class Asset(models.Model):
asset_desc = models.CharField(max_length=120, null=False)
BEIRUT = 'Beirut'
SAIDA = 'Saida'
HALBA = "Halba"
base_choice = ((SAIDA, "Saida"), (BEIRUT, "Beirut"), (HALBA, "Halba"))
asset_base = models.CharField(max_length=120, null=False, choices=base_choice)
created_date = models.DateField(auto_now_add=True)
update_date = models.DateTimeField(auto_now=True)
asset_user = models.CharField(max_length=120, blank=True)
slug = models.SlugField()
def save(self, *args, **kwargs):
self.slug = slugify(self.asset_desc)
super(Asset, self).save(*args, **kwargs)
def __str__(self):
return self.asset_desc
views.py
def search_asset(request):
if 'q' in request.GET and request.GET['q']:
q = request.GET['q']
assets = Asset.objects.filter(asset_desc__icontains=q)
context = {'desc': assets}
return render(request, 'home.html', context)
html for the search field:
<form method="GET" class="navbar-form navbar-right">
<input type="text" class="form-control" placeholder="Search..."id="search_box" name="q">
urls.py
url(r'^search/$', "asset.views.search_asset", name="home")
Please any help on why it is not showing the result. I am using Django 1.9.
some corrections:
you dont need null=False for TextField() and CharField(), since they never save Null to database but empty string. so you can remove null=False
the search url name is home which logically not really approriate. it should be changed to search or search_view and then you can refer to it via url tag:
action="{% url 'search' %}"
this is useful if someone should look over your code. "Readability counts" ;)
and finally, put this to your home.html (actually you must already have it)
{% for asset in desc %}
<div>
{{ asset.asset_desc }} <br>
{{ asset.base_choice }} <br>
{{ asset.asset_user }}
</div>
{% endfor %}
I hope, this helps
You have not provided the template or the HTML portion where you list the results. You should consider the name of you context variable, but by following your name, you should list the results like this:
{% for asset in desc %}
<div>
{{ asset }}
</div>
{% endfor %}
Anything else looks correct.
Hope it helps