Tried to get data from ManyToManyField - python

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>

Related

Django - How access the value of an instance in views.py

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)

Showing Many-To-Many in different model's form in Django?

Say I have three models, a Professor model, a Course model, and a Review model. The user is allowed to make a Review, which reviews a Professor that teaches a certain Course.
I'm thinking of how to model the many to many relationship of Professor and Course, and how to reference that relationship in Review. My idea so far is to use models.ManyToMany to link Professor and Course.
Models.py (Prof)
class Prof(models.Model):
first_name = models.CharField(max_length = 20, unique = False)
last_name = models.CharField(max_length = 20, unique = False)
def __str__ (self):
return self.first_name + " " + self.last_name
class Course(models.Model):
name = models.CharField(max_length = 20, unique = True)
prof = models.ManyToManyField(Prof)
def __str__ (self):
return self.name
Models.py (Review)
class Review(models.Model):
message = models.TextField(max_length = 4000)
created_at = models.DateTimeField(auto_now_add = True)
updated_at = models.DateTimeField(null = True)
rating = models.IntegerField(
default = 5,
validators = [MaxValueValidator(5), MinValueValidator(0)]
)
prof = models.ForeignKey(Prof, related_name = 'reviews')
course = models.ForeignKey(Course, related_name = 'reviews')
user = models.ForeignKey(User, related_name = 'reviews')
def __str__ (self):
return self.message
forms.py
class ReviewForm(ModelForm):
rating = CharField(widget=TextInput(attrs={'type': 'number','value': 5, 'min': 0, 'max': 5}))
class Meta:
model = Review
fields = ['message', 'rating', 'prof', 'course', 'user']
This is my code so far for displaying the form
<h1>New Review</h1>
<form method="POST">
{% csrf_token %}
<p>{{ review_form.message }}</p>
<p>{{ review_form.rating }}</p>
<p>{{ review_form.prof }}</p>
<!-- The prof chosen's courses should be shown here -->
<button type="submit">Save</button>
</form>
Right now, forms.py shows all the objects under Course, and i'm not sure how to instead show the courses of a professor. Is it possible to filter the form after a prof is chosen from the drop down, to display the courses he/she teacher?
It sounds like you're going about this the right way. You haven't mentioned your urls.py structure yet, or views.py but the most straightforward way to do this is to display the courses by professor, taking the professor's id (or slug-field) in as a parameter - either in the URL (v straightforward) or as the output from a form on a previous page (and reload the template with a professor parameter) or in Ajax, depending on your appetite for shiny-new-things.
In your view, when you call the form, you can then do, along the lines from this answer -
form.courses.queryset = Course.objects.filter(professor__in=[professor.id,])
Note that I've put filtered on a list here, which only has one item - it does give you scope to expand, or to use a queryset for more complicated functions later.
Tweak as appropriate if you're using class-based views. :)

Sum of fields for filtered queryset using django_filters

I have the following view
class AuthorList(FilterView):
model = Author
filterset_class = AuthorFilter
context_object_name = 'authors'
In the template, one of the field is {{ author.value }}, which is an integer.
What I would like to do is to show the sum of all {{ author.value }} in my template, but in a dynamic way (if some filters are used, the sum is updated with the current Queryset).
I have tried adding extra context with get_context_data but I couldn't find out how to make it in a dynamic way.
EDIT
tried this, still not working:
#property
def get_sum_values(self):
sum_values = self.objects.all().aggregate(Sum('value'))['value__sum']
return sum_values
and in the template: {{ authors.get_sum_values }}
I have also tried to add a print statement in the property, but nothing shows up, so I guess the function is not even loaded.
my models:
class Author(models.Model):
name = models.CharField(max_length=50, blank=True, null=True)
value = models.IntegerField(null=True, blank=True)
Have you tried doing the sum in the model as a function ?
#property
def wallet_amount_guests(self):
data_payments = self.user.earnings_set.filter(transaction_type='g').aggregate(Sum('amount'))['amount__sum']
if data_payments == None:
data_payments = 0
return data_payments
The above is just an example I have used before. You can then call in the html as blah.function_name

django get distinct value from queryset

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

Django - filtering on foreign key

I have a problem about filter in django. Please help me. I want to display the objects of the product which has different categories when I click on l.category_name
my html (CategoryList.html):
{% for l in forms %}
<h2>{{ l.category_name }}</h2>
{% endfor %}
CategoryView.html
{{get_product.product_name}}
my model:
class Category(models.Model):
category_id = models.AutoField(primary_key = True)
category_name = models.CharField(max_length = 20)
def __unicode__(self):
return self.category_name
class Product(models.Model):
product_id = models.AutoField(primary_key = True)
product_name = models.CharField(max_length = 50)
product_category = models.ForeignKey(Category)
product_color = models.CharField(max_length = 30)
def __unicode__(self):
return self.product_name
my view:
def category_list(request):
list = Category.objects.all()
context = {'forms':list}
return render(request,'webpage/CategoryList.html',context)
def category_view(request,category_id):
all = Product.objects.all()
if request.POST:
get_id = Category.objects.get(category_id = request.POST['category_id'])
get_category = Product.objects.get(product_category =
request.POST['product_category'])
get_category.product_category = get_id
get_category.save()
if get_category:
get_product = Product.objects.filter(product_category__category_name =
request.POST['category_name'])
context = {'get_product':get_product}
return render(request,'webpage/CategoryView.html',context)
I read document in https://docs.djangoproject.com/en/1.6/topics/db/queries/ but i don't understand .I know i was wrong category_view
There seem to be a lot of problems with your code.
First, you don't have to declare ids in your code. Django does that automatically for you. So, categor_id and product_id are unnecessary.
Second,
Remove the .POST check. You aren't posting anything.
Third,
get_id = Category.objects.get(category_id = request.POST['category_id']) # returns a category, not an id
get_category = Product.objects.get(product_category =
request.POST['product_category']) # returns the product list, not a category
get_category.product_category = get_id
is the same as
category = Category.objects.get(category_id = request.POST['category_id'])
product_list = Product.objects.get(product_category = category)
Fourth, don't hardcode URLs in your template. Use the {% url %} tag instead.
Finally,
You can then pass this product_list to the template
context = {'product_list':product_list}
return render(request,'webpage/CategoryView.html',context)
The way foreign keys are stored is through automatic fields(IDs). Since 'Category' is a foreign field of 'Product', when you make a record entry, the id of category is stored in 'product_category' field in products table.
I think your code is a little confusing since you are trying to do somethings django does automatically for you. Like, once you define a foreign key, the id of the foreign key table record is stored automatically, you don't have to get the id of 'category' entry and store it in products table entry.
What you are trying to achieve is simple, lets say you have the category_name and nothing else, get the id of the category table entry,
category_object = Category.objects.get(category_name = category_name)
category_id = category_object .id
If you already have the ID of category, then you can skip the above step, and simply use the ID to query the products table to get the needed records
Product.objects.filter(product_category = category_id)
In your templates, you can iterate through these product records and display whatever is needed.
BTW, use the .update() method to update any fields instead of save() method.
Something like this:
Entry.objects.all().update(blog=b)
It will be well worth your time reading through the queries help.
Django queries

Categories