I am learning python and django and I am coding a project similar to IMDB.
I am using python 3.8.2 64 bit and django 3
I want to display the latest review a movie received regardless of the user that wrote it.
Now it shows the user's own latest review and after logging the user out the review remains without displaying the user that wrote it. I have tried to clear cache and history, didn't help. this is the model:
from django.db import models
from django.contrib.auth.models import User
class Movie(models.Model):
movie_title = models.CharField(max_length=250)
movie_poster = models.ImageField(default='default.png', blank=True)
movie_short_description = models.TextField()
director = models.CharField(max_length=250)
actor1 = models.CharField(max_length=250)
actor2 = models.CharField(max_length=250)
actor3 = models.CharField(max_length=250)
actor4 = models.CharField(max_length=250)
year = models.IntegerField()
def __str__(self):
return self.movie_title + ' - ' + str(self.year)
class Review(models.Model):
movie = models.ForeignKey(Movie, on_delete=models.CASCADE)
user = models.ForeignKey(User, default = None, on_delete=models.DO_NOTHING)
score = models.IntegerField()
review_title = models.CharField(max_length=250, default="")
movie_review = models.TextField()
date = models.DateTimeField(auto_now_add=True)
class Meta:
get_latest_by = 'date'
def __str__(self):
return self.review_title
views.py
def movie_detail(request, pk):
try:
movie = Movie.objects.get(pk=pk)
review = Review.objects.all().latest()
except Exception as e:
print(e)
return render (request, 'movies/movie_detail.html', {'movie': movie, 'review': review})
html code:
</table>
</p>
<p>User Reviews</p>
<h3>Score: {{review.score}} {{review.review_title}}</h3>
<h6>{{review.date}}, by {{ user.get_username }}</h6>
<p>{{review.movie_review}}</p>
Review this title
</div>
</div>
{% endblock %}
I would create a property on Movie that gives you all reviews and then get the latest Review from this queryset. Here' the code:
# models.py
class Movie(models.Model):
# your other code
#property
def reviews(self) -> QuerySet:
return self.review_set.all()
# views.py
def movie_detail(request, pk):
movie = get_object_or_404(Movie, pk=pk)
latest_review = movie.reviews.latest()
# return
Ps: I would rename movie_title, movie_poster and movie_short_description to just title, poster and short_description. It is obvious that the title on Movie is the movies' title. I would also strongly suggest to change the 4 actors to a single model with a ManyToMany-relation (but I think you will read on that in the documentation later).
Related
Hello Everyone i have Two model first one is as following:
class Item(models.Model):
title = models.CharField(max_length=100)
price = models.FloatField()
bargainprice = models.FloatField(default=0)
discount_price = models.FloatField(blank=True, null=True)
category = models.CharField(choices=CATEGORY_CHOICES, max_length=2)
label = models.CharField(choices=LABEL_CHOICES, max_length=1)
slug = models.SlugField()
description = models.TextField()
image = models.ImageField()
and i am getting this model data using the following view:
class ItemDetailView(DetailView):
model = Item
template_name = "product.html"
and in product.html i am accessing Item objects like this:
<span class="mr-1">
<del>₹ {{ object.price }}</del>
</span>
<span>₹ {{ object.discount_price }}</span>
{% else %}
<span> ₹ <span id="pp">{{ object.price }}</span></span>
and so on..
everything working fine up here. but problem arises when i created the following model:
class BargainModel(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL,
on_delete=models.CASCADE)
itemId = models.IntegerField()
bprice = models.FloatField()
i joined this with foreign key as mentioned.
**what i want to do is print the " bprice " in the product.html of the same user but i am not able to do it **
can anyone help me with this i am new to Django.
Thanks in advance
in this case you need to import User like
from django.contrib.auth.models import User
class BargainModel(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
itemId = models.ForeignKey(Item, on_delete=models.CASCADE)
bprice = models.FloatField()
in product.html you can call the model of BargainModel it also contains the Item with user
It is better to work with a ForeignKey since this will guarantee referential integrity. You thus shoudl define the BargainModel as:
from django.conf import settings
class Bargain(models.Model):
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE
)
item = models.ForeignKey(
Item,
on_delete=models.CASCADE
)
bprice = models.FloatField()
class Meta:
constraints = [
models.UniqueConstraint(fields=['item', 'user'], name='unique_user_item')
]
In the DetailView, we can then look if there is a Bargain record for the given item and user with:
class ItemDetailView(DetailView):
model = Item
template_name = "product.html"
def get_bargain(self):
if self.request.user.is_authenticated():
return Bargain.objects.filter(item=self.object, user=request.user).first()
Then you can render this with:
{{ view.get_bargain.bprice }}
if there is a related Bargain, then it will show the corresponding bprice.
Note: Models normally have no Model suffix. Therefore it might be better to rename BargainModel to Bargain.
I want to fetch all the foreignkey table's attribute and show it in my HTML template. Here is my code in models, views and in the template:
models.py:
class OrderDashboard(models.Model):
title = models.CharField(max_length=100,default=None)
single_slug = models.SlugField(max_length=100, default=1)
description = models.TextField(max_length=1000)
thumb = models.ImageField()
date = models.DateField()
def __str__(self):
return self.title
class OrderScenario(models.Model):
webshop = models.CharField(max_length=100)
title = models.ForeignKey(OrderDashboard, default=None, on_delete=models.SET_DEFAULT)
order_qty = models.TextField(max_length=10)
order_date = models.DateField()
current_status = models.CharField(max_length=100)
ticket = models.CharField(max_length=200)
remark = models.TextField()
class Meta:
verbose_name_plural = "Scenario"
def __str__(self):
return self.webshop
Views.py:
def single_slug(request, single_slug):
report = OrderDashboard.objects.get(single_slug=single_slug)
return render(request, 'order_dashboard/report.html', {'report': report,
'OrderScenario': OrderScenario.objects.all})
I only want to view all the scenarios added in OrderScenario with respect to Title in OrderDashboard.
You should use backward relationship here; if you are passing the slug through the url, you can use:
views.py:
def single_slug(request, slug): # why you have self as the first argument?
report = OrderDashboard.objects.get(single_slug=slug)
return render(request, 'order_dashboard/report.html', {'report': report}
report.html:
{{ report.title }}
</p>Order Scenarios:</p>
{% for scenario in report.orderscenario_set.all %}
{{ scenario }}
{% endfor %}
I have django project with three below models:
models.py
from django.db import models
from django.contrib.auth.models import User
class Album(models.Model):
owner = models.ForeignKey(User)
title = models.CharField(max_length=127)
artist = models.CharField(max_length=63)
release_date = models.DateField()
logo = models.ImageField(blank=True, upload_to='album_logos', default='album_logos/no-image.jpeg')
t_added = models.DateTimeField(auto_now_add=True)
slug = models.SlugField(null=True, blank=True, max_length=63)
class Meta:
ordering = ['-release_date']
def __str__(self):
return self.title
class Song(models.Model):
album = models.ForeignKey(Album, on_delete=models.CASCADE)
name = models.CharField(max_length=255)
# is_favorite = models.BooleanField(default=False)
favorites = models.IntegerField(default=0)
song_file = models.FileField(blank=True, null=True, upload_to='song_files', default='song_files/mektub.mp3')
class Meta:
ordering = ['name']
def __str__(self):
return self.name
class Favorite(models.Model):
user = models.ForeignKey(User)
song = models.ForeignKey(Song)
created = models.DateTimeField(auto_now_add=True)
As you can see from these models many users can favorite many songs. In template, I want to add class to songs which are favorited by authenticated user:
template
<span {% if authenticated user favorited this song %}class="favorited" {% endif %}></span>
My problem is, I don't know how to write "if authenticated user favorited this song" in template. In terminal, I can get this information by this code:
user_favorited_this = song.favorite_set.filter(user=sample_user) and True or False
I couldn't do the same thing in template, since it doesn't support passing argument to filter method. How can I overcome this problem?
A tag filter can do what you want:
If the User.favorite_set.all has something in common with Song.favorite_set.all this means the current user has favorited that song
from django import template
register = template.Library()
# Method 1 for django queryset (Better)
#register.filter
def intersection(queryset1,queryset2):
return queryset1 & queryset2
# Method 2 for queryset or python List
#register.filter
def intersection(queryset1,queryset2):
return list(set.intersection(set(queryset1),set(queryset2)))
html:
{% if request.user.favorite_set.all|intersection:song.favorite_set.all %} class="favorited" {% endif %}
It may just be simpler to do this in the view, and then pass the result to the template as a boolean flag.
For example:
def song_view(request):
...
song = Song.objects.get(pk=request.GET['song_id'])
is_favorite = song.favorite_set.filter(user=request.user).exists()
return render(request, 'my_template.html', {'is_favorite': is_favorite})
or for a generic class based view:
class SongDetail(DetailView):
...
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
song = self.get_object()
is_favorite = song.favorite_set.filter(user=self.request.user).exists()
context['is_favorite'] = is_favorite
return context
and then the code in your template can be simplified to:
<span {% if is_favorite %}class="favorited" {% endif %}></span>
Am relatively new to django and I have searched for this problem but couldn't find a solution. Forgive me if the solution is obvious but I just can't seem to get it right.
So, this is the issue. I have two models Parishioner and Community. Parishioner has a many-to-one relationship with Community. On the parishioner_detail page, I am trying to display the community name as a link to the community_detail page. I feel I am not using the get_absolute_url() method correctly. Any help would be appreciated.
Models:
from django.db import models
from django.core.urlresolvers import reverse
class Community(models.Model):
name = models.CharField(max_length=41)
description = models.TextField()
leader = models.CharField(max_length=41)
email = models.EmailField()
phone_number = models.CharField(max_length=20)
slug = models.SlugField(max_length=31, unique=True)
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('people_community_detail', kwargs={'slug': self.slug})
class Parishioner(models.Model):
name = models.CharField(max_length=41)
date_of_birth = models.DateField('date of birth', blank=True)
email = models.EmailField()
phone_number = models.CharField(max_length=20)
start_date = models.DateField('date posted')
societies = models.ManyToManyField(Society, blank=True, related_name='parishoners')
communities = models.ForeignKey(Community, blank=True, related_name='parishoners')
sacraments = models.ManyToManyField(Sacrament, blank=True, related_name='parishoners')
slug = models.SlugField(max_length=31, unique=True)
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('people_parishioner_detail', kwargs={'slug': self.slug})
class meta:
ordering = ['name']
verbose_name_plural = "parishioners"
Views:
from django.shortcuts import get_object_or_404, render, redirect
from .models import Society, Community, Sacrament, Festival, Parishioner
def community_list(request):
return render(request, 'people/community_list.html', {'community_list': Community.objects.all()})
def community_detail(request, slug):
community = get_object_or_404(Community, slug__iexact=slug)
return render(request, 'people/community_detail.html', {'community': community})
def parishioner_list(request):
return render(request, 'people/parishioner_list.html', {'parishioner_list': Parishioner.objects.all()})
def parishioner_detail(request, slug):
parishioner = get_object_or_404(Parishioner, slug__iexact=slug)
return render(request, 'people/parishioner_detail.html', {'parishioner': parishioner})
parishioner_detail.html:
<dt>Community</dt>
<dd>{{ parishioner.communities|title }}</dd>
<dt>Societies</dt>
{% for society in parishioner.societies.all %}
<dd>{{ society.name|title }}</dd>
{% endfor %}
The society name links correctly to the society_detail page but the community name links to the parishioner_detail page instead of the community_detail page. It basically reloads the page.
Any help would be appreciated.
Thanks.
The community name does not exist in your context, the href link is therefore empty and you get redirects to the same page.
You should probably be doing:
<dt>Community</dt>
<dd>{{ parishioner.communities|title }}</dd>
Better to change the communities field to singular (i.e. community) since it's a foreign key field, so it's less confusing; one parishioner to one community (not multiple communities).
I have the following blog project :
urls.py conf :
url(r'^author/(?P<author>\w+)/$', views.getAllPosts, name='grabAuthorPosts')
posts/models:
class Post(models.Model):
title = models.CharField(max_length=200)
summary = models.CharField(max_length=500, default = True)
body = models.TextField()
pub_date = models.DateTimeField(default=timezone.now)
category = models.ManyToManyField('Category')
author = models.ForeignKey(User, default=True)
slug = models.SlugField(max_length=100, unique=True, blank=True)
def __str__(self):
return self.title
def slug(self):
return slugify(self.title)
posts/views:
def getAllPosts(request, author=False):
latest_posts = Post.objects.all().order_by('-pub_date')
comments = Comment.objects.all().order_by('-pub_date')
author_posts = User.objects.get(id=author)
author_posts = author_posts.post_set.all()
context = {
'latest_posts':latest_posts,
'comments':comments,
'author_posts':author_posts
}
return render(request, 'posts/getAllPosts.html', context)
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
bio = models.TextField(max_length=500, blank=True)
location = models.CharField(max_length=30, blank=True)
birth_date = models.DateField(null=True, blank=True)
templates/posts/getAllPosts:
<a href={% url 'grabAuthorPosts' author=post.author.username %}>
{{post.author}}</a>
I am trying to make it so that when the post.author link is clicked, the user will be taken to a page consisting of posts related to that particular author. The link formulation itself seems ok, as when clicked on a post created by admin, the url reads localhost/author/admin/
I believe my problem is in getting the context variable author_posts to work. I'm new to Django so any explanation greatly appreciated.
latest_posts, as well as author=False is used elsewhere in the template to get all posts regardless of author, which works fine.
The error is :
ValueError at /author/admin/
invalid literal for int() with base 10: 'admin'