I have a model:
class Organisation(User):
organisation_name = models.CharField(max_length=200)
first_parent = models.ForeignKey('Parent', related_name="first", blank=True, null=True)
second_parent = models.ForeignKey('Parent', related_name="second", blank=True, null=True)
def __unicode__(self):
return self.username
and my Parent model:
class Parent(models.Model):
parent_name = models.CharField(max_length=50)
def __unicode__(self):
return self.parent_name
Here I want the list of parents in my templates that are unique. I dont want repeted parents.
I have gone through:
organisations = Organisation.objects.all().distinct('first_parent')
but this is not supported by mysql.
I tried to get list of first parents from organisations then its set gives only unique value like:
organisations = Organisation.objects.all()
parent_list = organisations.first_parent ## it gives error says 'QuerySet' object has no attribute 'first_parent'
I have thought about grouping in template but i was not able to..
What I want is list of first_parent or organisation with its id in template so that I can redirect it to some page with id like
{% for parent in parent_list %}
{{parent}}
<a href="{% url "some_url" parent.id %}"
first_parent I get should be unique.
How can I get this. please help
For backend that do not support distinct('...') like MySQL, use Organisation.objects.values('first_parent').distinct(),
this gives you a list of {'first_parent': value} dictionaries
To get a list of just the values do
parent_list = [org['first_parent'] for org in Organisation.objects.values('first_parent').distinct()]
Related
I am using .values() and .annotate()to sum up 2 models fields based on matching criteria.
I wrapped this in a forloop in my template to iterate.
Problem: I cannot call the model fields anymore. The forloop returns the venue_id instead of the name and the usual approach to call the logo does not work anymore.
(these were rendering fine before I used .values() and .annotate(). Makes me think I am missing something in the logic here. Any ideas?
Models
class Venue(models.Model, HitCountMixin):
id = models.AutoField(primary_key=True)
name = models.CharField(verbose_name="Name",max_length=100, blank=True)
logo = models.URLField('Logo', null=True, blank=True)
class Itemised_Loyatly_Card(models.Model):
user = models.ForeignKey(UserProfile, blank=True, null=True, on_delete=models.CASCADE)
venue = models.ForeignKey(Venue, blank=True, null=True, on_delete=models.CASCADE)
add_points = models.IntegerField(name = 'add_points', null = True, blank=True, default=0)
use_points = models.IntegerField(name= 'use_points', null = True, blank=True, default=0)
Views
from django.db.models import Sum, F
def user_loyalty_card(request):
itemised_loyalty_cards = Itemised_Loyatly_Card.objects.filter(user=request.user.id).values('venue').annotate(add_points=Sum('add_points')).annotate(use_points=Sum('use_points')).annotate(total=F('add_points')-F('use_points'))
return render(request,"main/account/user_loyalty_card.html", {'itemised_loyalty_cards':itemised_loyalty_cards})
Templates
{%for itemised_loyatly_card in itemised_loyalty_cards %}
<img"src="{{itemised_loyatly_card.venue.logo}}">
{{itemised_loyatly_card.venue}}
{{itemised_loyatly_card.total}}
{%endfor%}
Renders
It returns only the value ID because that is the only field you passed in as an argument to .values('venue'). Whereas if you want another attribute you have to use field lookups, like so:
.values('venue__name'. 'venue__logo')
Also, .values() returns a QuerySet that returns dictionaries and not object instances, so if you pass that data into the template you can not access related data, meaning
{{itemised_loyatly_card.venue.logo}} will not work, but taking the first codeblock as an example {{itemised_loyatly_card.venue__logo}} works.
Another "mistake" is at these two annotations, annotations are a per object aggregation, these two lines are redundant, your model already has these fields.
.annotate(add_points=Sum('add_points'))
.annotate(use_points=Sum('use_points'))
That being said, if you want objects instead of values, that leaves you with:
views.py
itemised_loyalty_cards = (
Itemised_Loyatly_Card.objects.filter(user=request.user.id)
.annotate(total=F('add_points')-F('use_points'))
)
template.html
{%for itemised_loyatly_card in itemised_loyalty_cards %}
<p>
{{itemised_loyatly_card.venue.name}}
{{itemised_loyatly_card.add_points}}-
{{itemised_loyatly_card.use_points}}=
{{itemised_loyatly_card.total}}
</p>
<img src="{{itemised_loyatly_card.venue.logo}}" alt="" >
{%endfor%}
models.py
class products(models.Model):
name = models.CharField(max_length=100)
sku = models.CharField(max_length=50)
vendor = models.CharField(max_length=50)
brand = models.CharField(max_length=50)
price = models.FloatField()
product_status = models.BooleanField()
quantity = models.IntegerField()
def __str__(self):
return self.name
# categories
class categories(models.Model):
category_name = models.CharField(max_length=50)
parent_id = models.IntegerField()
# product categories
class product_categories(models.Model):
product = models.ForeignKey(products, on_delete=models.CASCADE)
category = models.ForeignKey(categories, on_delete=models.CASCADE)
def __str__(self):
return self.category
I can access 'category' table data(inside django shell) using
data = products.objects.all()
data.values('product_categories__category__category_name')
output: <QuerySet [{'product_categories__category__category_name': 'xxxx'}}]>
If I put this(inside django shell)
data.product_categories.category
output: 'QuerySet' object has no attribute 'product_categories'
How do I get a queryset(can be passed to html) which includes data from "categories" table along with the data of "products" table
There are a couple of issues happening here. First, data is a queryset, which is kind of like a list of objects, even though here there's just one object in the list. What you want is to get an attribute off of the item in the list, so you need something like a data.first() to get to that object before you start dotting into its attributes.
Secondly, the way Django handles reverse FK relationships requires that you refer to the FK by the standard name of, in your case, product_categories_set, OR you set your own related_name attribute on the FK. Something like:
# product categories
class product_categories(models.Model):
product = models.ForeignKey(products, on_delete=models.CASCADE, related_name='product_categories')
category = models.ForeignKey(categories, on_delete=models.CASCADE, related_name='product_categories')
def __str__(self):
return self.category
so that you can refer to your product_categories model from both the product and categories using just data.product_categories.
Thirdly, when accessing a reverse FK relationship, just like in point (1) above, you will get a related manager, from which you can get a queryset of items. Thus, to get the category name, you need to indicate which item you want the category name for. Assuming it's just the first item for everything, it would look something like:
data = products.objects.all()
product_category = data.product_categories.all()
category_name = product_category.category.category_name
Of course once you have more data, you'll not always want to just pick the first item, so you'll need to add filtering logic into the query to make sure you get the item you're looking for.
ETA, I do agree with the comment by Jorge above - a MTM would make this a bit simpler and would, in essence, create your product_categories table for you.
I have this model
class Post(models.Model):
title = models.CharField(max_length=100)
title2 = models.CharField( max_length=100)
content = models.TextField(default=timezone.now)
content2 = models.TextField(default=timezone.now)
post_image = models.ImageField(upload_to='post_pics')
post_image2 = models.ImageField(upload_to='post2_pics')
date_posted = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
Then I have this simple view function that allows me to access each of its field in my HTML:
def home(request):
postings = {
'listings' : Post.objects.all(),
}
return render(request, 'front/front.html', postings)
{% for listings in listings%}
<h1>{{listings.content}}</h1>
{% endfor %}
With this, I'm able to access the content field for every instance of that model and display it
My question is how can I access the content field in my view function and change it. The content field holds a zipcode and I want to use an API to display the city of that zipcode(which I already know how to do) and pass it back to the h1 tag. Each instance holds a unique zipcode so I need it to apply for each instance. How would I approach this?
the simplest way would be to create another variable(from views) which finds the city for a corresponding zipcode and send it through the context dictionary to the template.
OR
Add a model city setting default and Null and later based on the entered pincode you can set value to the city attribute of the model..
If you want to edit the value of the CONTENT to the city name ... then ,
The best way would be to override the save method and set the value there,
models.py :
class Post(models.Model):
...
def save(self, *args, **kwargs):
self.content = API_VALUE_OF_city_name
super(Post, self).save(*args, **kwargs)
if you want to update it from views,
in views.py :
instance_update = Post.objects.filter(id = <pk of Post>).update(content = NEWLY FOUND CITY NAME)
I have a webpage where you can add a new computer/ip to the database, or choose a previously added from a dropdown list. Everything works fine, except that what I get after the user is selecting an item from the list is the index of it, and not its name.
How can I get the name? I am trying to access the queryset as a vector as seen here, but I get a TypeError.
views.py:
d = DropDownList(request.POST or None)
if d.is_valid():
c = request.POST.get('current')
return HttpResponse(d.qs[c-1])
models.py:
class DropDownList(forms.Form):
qs = Computer.objects.all().order_by('name')
current = forms.ModelChoiceField(qs, widget=forms.Select(attrs={"onChange":'submit()'}))
class Computer(models.Model):
name = models.CharField(max_length=200, default='')
ip = models.CharField(max_length=200, default='')
def __unicode__(self):
return self.name
home.html:
<form method="post">
{{ current }}
</form>
The whole point of using a form is that it takes care of validation and data conversion, so in your view you should get the data from the form, not from the POST itself.
if d.is_valid():
c = d.cleaned_data['current']
I tried to get data from ManyToManyField but found not luck. Will you please help me?
Here is My Song App Models.
class Artist(models.Model):
name = models.CharField(max_length=100)
slug = models.SlugField(unique = True,max_length=100,help_text="Suggested value automatically generated from name. Must be unique.")
class Album(models.Model):
name = models.CharField(max_length=100)
slug = models.SlugField(unique = True,max_length=100,help_text="Suggested value automatically generated from name. Must be unique.")
path = models.CharField(max_length=100,null=True, blank=True)
language = models.ForeignKey(Category)
albumid = models.CharField(max_length=100)
class Song(models.Model):
title = models.CharField(max_length=100)
artist = models.ManyToManyField(Artist)
music = models.ForeignKey(Music)
album = models.ForeignKey(Album)
Here is my view. I want to print Artist with titles. Titles are working fine. but not Artist
def movie_details(request,slug):
movies = get_object_or_404(Movie,slug=slug)
# calculating wikipedia directory structer for images
#image_name = movies.image
name = movies.title
album_name = Album.objects.get(name__exact=name)
album_id = album_name.id
song_list = Song.objects.filter(album=album_id)
#image_path = generateWikiImage(image_name)
#
return render_to_response('base_movies.html',locals(),
context_instance=RequestContext(request)
)
I tried in template like this. {{song_list.artist}} and getting message like this <django.db.models.fields.related.ManyRelatedManager object at 0x024CBED0>
thanks
ManyRelatedManager is the object that handles the ManyToMany relation there. To get the list of objects that you're looking for, you need to use its all() method.
In this case, you'd use {{song_list.artist.all}}, which will give you a QuerySet that you can then iterate over in your template.
ManyToManyField holds queryset, so you can't just output it in template. You should iterate over it.
Like this (song is some Song instance)
<ul>
{% for artist in song.artist.all %}
<li>{{ artist.name }}</li>
{% endfor %}
</ul>