ManyToMany Query (Django) - python

How might I query through a ManytoMany field to list the shows an Artist has played (along with their genre which has been completed). I am fairly new to Django with just finishing up the Tango with Django tutorial, but what I have so far is below.
models.py
class Genre(models.Model):
name = models.CharField(max_length=20, unique=True, blank=False)
def __unicode__(self):
return self.name
class Artist(models.Model):
name = models.CharField(max_length=50, unique=True, blank=False)
photo = models.ImageField(upload_to='artist_photos', blank=True)
logo = models.ImageField(upload_to='artist_logos', blank=True)
genre = models.ManyToManyField(Genre)
twitter = models.URLField(blank=True)
facebook = models.URLField(blank=True)
instagram = models.URLField(blank=True)
def __unicode__(self):
return self.name
class Venue(models.Model):
name = models.CharField(max_length=50, unique=True, blank=False)
logo = models.ImageField(upload_to='venue_logos', blank=True)
capacity = models.IntegerField(blank=False)
address = models.CharField(max_length=50, blank=True)
city = models.CharField(max_length=50, blank=True)
state = models.CharField(max_length=50, blank=True)
zip_code = models.IntegerField(max_length=50, blank=True, null=True)
website = models.URLField(blank=True)
twitter = models.URLField(blank=True)
facebook = models.URLField(blank=True)
instagram = models.URLField(blank=True)
def __unicode__(self):
return self.name
class Show(models.Model):
venue = models.ForeignKey(Venue)
date_time = models.DateTimeField(blank=False)
attendance = models.IntegerField(blank=False)
bands = models.ManyToManyField(Artist)
views.py
def artists(request):
context = RequestContext(request)
artists = Artist.objects.order_by('name')
shows = Show.objects.order_by('-date_time')
# artist_shows = Show.objects.filter(????????)
context_dic = {'artists': artists, 'shows': shows}
return render_to_response('artistdb/artists.html', context_dic, context)
artist.html
<h2>Artists</h2>
{% if artists %}
<ul>
{% for artist in artists %}
<li>{{ artist.name }}<br />
<ul>
{% for g in artist.genre.all %}
<li>{{ g.name }}</li>
{% endfor %}
</ul>
</li>
<br />
{% endfor %}
</ul>
{% else %}
There are no artist.
{% endif %}

To get the shows that an artist has played, you can do this:
artist = Artist.objects.get(name="johndt6")
artist.show_set.all() # Will return all shows related to the artist
A recommendation is to set a related_name argument on your foreign keys and many to many fields. So, under the Show model, the many to many relation to artist would read:
bands = models.ManyToManyField(Artist, related_name="shows")
Then, you could query an artist's shows as follows:
artist.shows.all() # Will return all of the artists shows
You can also use normal queries if you wish:
shows = Show.objects.filter(bands__in=artist) # Will return all of an artist's shows
However, this isn't quite as nice as using Django's built in relations.
See documentation here

Related

Django I can't pull data from database

Admin can change the web title,keywords or description. But it's not working rn. When i entry website everything is fine i don't have any error but informations didn't come from database.
This is my home/models.py
from django.db import models
class Setting(models.Model):
title = models.CharField(max_length=150)
keywords = models.CharField(max_length=255)
description = models.CharField(max_length=255)
company = models.CharField(max_length=50)
address = models.CharField(blank=True, max_length=150)
phone = models.CharField(blank=True, max_length=15)
fax = models.CharField(blank=True, max_length=15)
email = models.CharField(blank=True, max_length=50)
smptpserver = models.CharField(blank=True, max_length=30)
smptemail = models.CharField(blank=True, max_length=30)
smptpassword = models.CharField(blank=True, max_length=150)
smptport = models.CharField(blank=True, max_length=15)
icon = models.ImageField(blank=True, upload_to='images/')
facebook = models.CharField(blank=True, max_length=50)
instagram = models.CharField(blank=True, max_length=50)
twitter = models.CharField(blank=True, max_length=50)
aboutus = models.CharField(max_length=50)
contact = models.CharField(max_length=50)
contact_map = models.CharField(max_length=50)
references = models.CharField(max_length=50)
status = models.CharField(max_length=10, choices=STATUS)
create_at = models.DateTimeField(auto_now_add=True)
uptade_at = models.DateTimeField(auto_now=True)
def __str__(self):
return self.title
This is my home/views.py
from django.http import HttpResponse
from django.shortcuts import render
from home.models import Setting
def index(request):
setting=Setting.objects.all()
context={'setting':setting}
return render(request,'index.html',context)
This is my home/temp/index.html
{% block title %} {{ setting.title }} {% endblock %}
{% block keywords %} {{ setting.keywords }} {% endblock %}
{% block description %} {{ setting.description }} {% endblock %}
Your issue is that you're returning a whole queryset, not a single item
setting=Setting.objects.all()
context={'setting':setting}
If you only ever have one Setting record, you could use Setting.objects.first() instead. If you have more than one you should use Setting.objects.get(...) to retrieve a single record.
You can see this for yourself if you examine the value of setting in the view before you return it (use a breakpoint() to look at the vars in the shell, or just print it out).
As long as you use all() the template will be expecting an iterable of objects for you to loop over - that iterable will not have properties like keywords, description etc.

prefetch_related in Django displaying all objects instad of related ones

I am trying to get a list of all categories and below each category the list of all related articles.
The problem is that I am getting the list of all articles under each category. I read documentation and few answers but nothing seems to be working and I am not sure where I am making the mistake.
models.py
class Category(models.Model):
title = models.CharField(max_length=75, default='', blank=False, null=False)
body = CharField(max_length=2000, default='', null=True, blank=True)
slug = models.SlugField(unique=True, blank=True)
publish = models.DateTimeField('publish', default=timezone.now)
class Meta:
ordering = ('-publish',)
verbose_name = 'category'
verbose_name_plural = 'categories'
get_latest_by = 'publish'
class Article(models.Model):
id = models.AutoField(primary_key=True)
author = models.ForeignKey(User, blank=True, null=True, on_delete=models.SET_NULL) #settings INSTALLED_APPS
title = models.CharField('title', max_length=200)
body = CKEditor5Field('Body', config_name='extends')
last_updated = models.DateTimeField(auto_now=True)
publish = models.DateTimeField('publish', default=timezone.now)
#tags = TagField(required=False, widget=LabelWidget)
category = models.ForeignKey(Category, on_delete = models.CASCADE, blank=True, related_name='category')
slug = models.SlugField(unique=True, blank=True)
views.py
#login_required
def hal_home(request):
top_categories = Category.objects.all()[:3]
category_related_articles = Article.objects.prefetch_related('category').all()
context = {
'category_related_articles': category_related_articles
}
return render(request, 'hal/homepage.html', context)
homepage.html
{% for category in top_categories %}
<div class="btn btn-light text-center text-justify">
<div>{{ category.title }}</div>
</div>
<br>
<p>{% for article in category_related_articles %}
{{article.title}}<br>
{% endfor %}</p>
{% empty %}
<div>No categories</div>
{% endfor %}
You should use prefetch_related with your category queryset.
And also I would suggest you to change the related_name to articles since category.articles.all() seems more readable and easier than category.category.all() .
category = models.ForeignKey(Category, on_delete = models.CASCADE, blank=True, related_name='articles')
Now you can change some code in your views and templates.
top_categories = Category.objects.prefetch_related("articles").all()[:3]
context = {'top_categories': top_categories}
Now you can get articles by category in template with:
{% for category in top_categories %}
{{category.title}}
# articles of each category
{% for article in category.articles.all %}
{{article}}
{% endfor %}
{% endfor %}

Detail view context

how can i get all images of item into context
i tried {% for image in item.images.all %} in template but it doesn't work.
i dunno how to filter it , ty for ur answer
models
class Item(models.Model):
name = models.CharField(max_length=255)
slug = models.SlugField(max_length=255, unique=True)
brand = models.ForeignKey(Brand, on_delete=models.CASCADE, blank=True)
collection = models.ForeignKey(Collection, on_delete=models.CASCADE)
category = models.ForeignKey(Category, on_delete=models.CASCADE)
sub_category = models.ForeignKey(SubCategory, on_delete=models.CASCADE, null=True)
description = models.TextField(blank=True)
image = models.ImageField(upload_to='photos/%Y/%m/%d/', null=True)
size = ArrayField(models.CharField(max_length=255))
price = models.PositiveIntegerField()
on_sale = models.BooleanField(default=0)
discount = models.PositiveIntegerField(null=True, blank=True)
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('single_product', kwargs={'slug': self.slug})
def get_sale(self):
price = int(self.price * (100 - self.discount) / 100)
return price
class ItemImage(models.Model):
item = models.ForeignKey(Item, on_delete=models.CASCADE, null=True, related_name='images')
images = models.ImageField(upload_to='photos/%Y/%m/%d/', null=True)
def __str__(self):
return self.item.name
views
class ItemDetail(DetailView):
model = Item
context_object_name = 'item'
template_name = 'essense/single-product-details.html'
def get_context_data(self, *, object_list=None, **kwargs):
context = super().get_context_data(**kwargs)
You're pretty close. In your template tag {% for image in item.images.all %}, image refers to an instance of your ItemImage model. You need to reference the ImageField within that model, which you've named images. So, instead of
src="{{ image.url }}" use src="{{ image.images.url }}"
<div className="single_product_thumb clearfix">
<div className="product_thumbnail_slides owl-carousel">
{% for image in item.images.all %} <img
src="{{ image.images.url }}" alt="" width="360" height="539">
{% endfor %}
</div>
</div>```

Django filter a queryset based on the template name

In my Django App, I have 2 models. One called Post and one called Categories. When a user clicks on a category, I want only the posts that are in that category to appear in the category detail view. For example if a user clicks on the medical category, I only want the posts in the medical category to appear.
Models:
class Category(models.Model):
title = models.CharField(max_length=200)
colorcode = models.CharField(max_length=20, blank=True, null=True)
description = models.TextField()
image = models.ImageField(blank=True, null=True)
slug = models.SlugField(unique=True)
class Post(models.Model):
author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
title = models.CharField(max_length=200)
text = models.TextField()
sub_description = models.TextField(blank=True, null=True)
created_date = models.DateTimeField(default=timezone.now)
published_date = models.DateTimeField(blank=True, null=True)
category = models.ForeignKey(Category, on_delete=models.CASCADE, blank=True, null=True)
image = models.ImageField(blank=True, null=True)
live = models.BooleanField(default=False)
slug = models.SlugField(unique=True)
Views:
class CategoryDetailView(DetailView):
model = Category
def get_context_data(self, **kwargs):
context = super(CategoryDetailView, self).get_context_data(**kwargs)
context['category_posts'] = Post.objects.filter(live=True)
return context
Template:
{% for post in category_posts %}
<div class="post">
<div class="post-title">
{{ post.title }}
</div>
<div class="post-author">
{{ post.author }}
</div>
</div>
{% endfor %}
In a DetailView, you have access to the actual object being rendered (in your case the Category instance) through self.object.
So in your get_context_data method you can do:
context['category_posts'] = Post.objects.filter(live=True, category=self.object)
Note that self.object might be None so you may want to deal with that case.

nested loop in django template is not showing correct output

I am trying to print brand and it's links and I am using nested loops but it is not showing correct output
here is my code
{% for brand_report in brand_reports %}
<h1> REPORT for Brand: {{ brand_report.brand.name }}</h1>
{% for link in brand_report.links.all %}
<h3>link:</h3>{{link.url}}
{% endfor %}
{% endfor %}
Desired output is
REPORT for Brand: SizCom
link:
https://www.justdial.com/Kozhikode/SizCom-Near-to-Big-Bazaar-Calicut-City/0495PX495-X495-151217184614-Z4I2_BZDET
REPORT for Brand: SizCom
link:
https://www.justdial.com/Kozhikode/SizCom-Near-to-Big-Bazaar-Calicut-City/0495PX495-X495-151217184614-Z4I2_BZDET
But i am getting output like this
REPORT for Brand: SizCom
REPORT for Brand: SizCom
link:
https://www.justdial.com/Kozhikode/SizCom-Near-to-Big-Bazaar-Calicut-City/0495PX495-X495-151217184614-Z4I2_BZDET
link:
https://www.justdial.com/Kozhikode/SizCom-Near-to-Big-Bazaar-Calicut-City/0495PX495-X495-151217184614-Z4I2_BZDET
Don't know what i am doing wrong
model:
class Brand(models.Model):
"""For the brand"""
name = models.CharField(max_length=500)
description = models.TextField(blank=True, null=True)
context = models.ManyToManyField(Context, blank=True)
variation = models.ManyToManyField('BrandVariation', blank=True, related_name='brand')
status = models.BooleanField(default=False)
def __str__(self):
return self.name
class ResultLink(models.Model):
"""for results"""
url = models.URLField(max_length=1000)
country = models.ForeignKey(Country, blank=True, null=True)
parent_site = models.ForeignKey(Domain, on_delete=models.CASCADE, blank=True, null=True)
variation = models.ForeignKey(BrandVariation, on_delete=models.CASCADE, blank=True, null=True)
brand = models.ForeignKey(Brand, on_delete=models.CASCADE, blank=True, null=True, related_name='link')
date = models.DateField(auto_now_add=True)
def __str__(self):
return "%s" % self.url
class BrandReport(TimeStampedModel):
""""""
brand = models.ForeignKey(Brand, related_name='counterfeit_report')
links = models.ManyToManyField(ResultLink, blank=True)
class Meta:
verbose_name = "Brand Report"
Views :
def view(request,brands):
template_path = 'profile_brand_report.html'
brand_reports = BrandReport.objects.filter(brand__id__in=brands)
context = {'brand_reports': brand_reports}
html = render_to_string(template_path, context)
I recreated your project. The only thing you missed providing was your view. So I suppose that is where your problem is. Here is my view:
def demoview(request):
objs = BrandReport.objects.all()
c = {
"brand_reports": objs,
}
return render(request, "blog/demoview.html", c)
And here is my template:
{% for brand_report in brand_reports %}
<h1> REPORT for Brand: {{ brand_report.brand.name }}</h1>
{% for link in brand_report.links.all %}
<h3>link:</h3>{{link.url}}
{% endfor %}
{% endfor %}
And my result is exactly how you have desired. Please check your view.
You obviously have a first BrandReport without any related link and a second BrandReport with two related links - check your database.
FWIW, I actually don't get what your BrandReport model is since you already have a foreignkey to Brand in ResultLink. Your BrandReport model is not only redundant (as far as we can tell) but also brittle since it allows to relate any ReportLink to any Brand without respecting the ReportLink.brand constraint.

Categories