Django Queryset Returning Empty '[]' - django

I have a list of movie genre. Each genre has its own movie. For instance, there is a list of movies for every movie genre but the object_list is empty.
the github link: https://github.com/AdebayoAnuoluwapo/imdb-original.git
My View:
class MovieCategory(ListView):
model = Movie
paginate_by = 2
def get_queryset(self):
self.category = self.kwargs['category']
return Movie.objects.filter(category=self.category)
def get_context_data(self , **kwargs):
context = super(MovieCategory , self).get_context_data(**kwargs)
context['movie_category'] = self.category
print(context)
return context
My Models:
ACTION = 'action'
DRAMA = 'drama'
COMEDY = 'comedy'
ROMANCE = 'romance'
CATEGORY_CHOICES = (
(ACTION, 'Action'),
(DRAMA, 'Drama'),
(COMEDY, 'Comedy'),
(ROMANCE, 'Romance'),
)
class Movie(models.Model):
title = models.CharField(max_length=200)
description = models.TextField(max_length=2000)
image = models.ImageField(upload_to='movies')
category = models.CharField(choices=CATEGORY_CHOICES, max_length=10)
language = models.CharField(choices=LANGUAGE_CHOICES, max_length=7)
status = models.CharField(choices=STATUS_CHOICES, max_length=2)
cast = models.CharField(max_length=100)
year_of_production = models.DateField()
views_count = models.IntegerField(default=0)
def __str__(self):
return self.title
my Urls:
from django.urls import path
from . import views
app_name = 'movie'
urlpatterns = [
path('', views.HomeView.as_view(), name='home'),
path('list/', views.MovieListView.as_view(), name='movie_list'),
path('category/<str:category>', views.MovieCategory.as_view() , name='movie_category'),
path('language/<str:lang>', views.MovieLanguage.as_view(), name='movie_language'),
path('search/', views.MovieSearch.as_view() , name='movie_search'),
path('<int:pk>/', views.MovieDetailView.as_view(), name='movie_detail'),
]
when i print(context) I get
'object_list': <QuerySet []>,
'movie_list': <QuerySet []>
Thanks In Advance...

I have solved it already.
I forgot to add the context_object_name
class MovieCategory(ListView):
model = Movie
paginate_by = 2
context_object_name = 'movies'
def get_queryset(self,**kwargs):
self.category = self.kwargs['category']
return Movie.objects.filter(category=self.category)
def get_context_data(self , **kwargs):
context = super(MovieCategory,self).get_context_data(**kwargs)
context['movie_category'] = self.category
return context

Related

How to pass data (specific fiiled) from views.py to models.py

I have a problem. How can i pass the data (def maybe) from models.py
I need this for filter by category in future
class Tag(models.Model):
.......
category = models.ForeignKey(Category, null=True, on_delete=models.PROTECT, related_name='category', verbose_name='Tag category')
......
def get_category(self):
return self.category
To views.py. This is it doesn't work
class GetDetailTag(DetailView):
model = Tag
template_name = 'main/catalog.html'
context_object_name = 'tag'
category = Tag.get_category
def get_context_data(self, *, object_list=None, **kwargs):
context = super().get_context_data(**kwargs,)
context['pansion_in_tag_list'] = Pansions.objects.filter(tags__slug=self.kwargs['slug'])
context['tags_in_category'] = Tag.objects.filter(category__slug = '...INSERT THE DATA FROM MODEL HERE...')
return context
I was trying to call the 'def'(get_category) in views.py
Anyway? How i can to do that?
You can just obtain this from the tag, so:
{{ tag.category }}
or in the DetailView:
class TagDetailView(DetailView):
model = Tag
template_name = 'main/catalog.html'
context_object_name = 'tag'
def get_context_data(self, *, object_list=None, **kwargs):
context = super().get_context_data(object_list=object_list, **kwargs)
context['pansion_in_tag_list'] = Pansions.objects.filter(
tags__slug=self.kwargs['slug']
)
context['tags_in_category'] = Tag.objects.filter(
category_id=self.object.category_id
)
# category = self.object.category (obtain the category)
return context

apply a filter to the choices field of my model

Hi I have problems with some filters in django.
I have my own view where I can choose the day of the week which is a select choice field
once chosen it is saved in the db.
I would like to filter those already present so as not to repeat them if I had to choose another day.
Can anyone help me out please?
models.py
class Piano(models.Model):
nome_piano = models.CharField(max_length=100)
data_inizio = models.DateField()
data_fine = models.DateField()
utente_piano = models.ForeignKey(
User,
on_delete = models.CASCADE,
related_name = 'utente_piano'
)
def __str__(self):
return self.nome_piano
class Meta:
verbose_name = "Piano alimentare"
verbose_name_plural = "Piani alimentari"
class PianoSingleDay(models.Model):
giorni_settimana_scelta = [
("1","Lunedì"),
("2","Martedì"),
("3","Mercoledì"),
("4","Giovedì"),
("5","Venerdì"),
("6","Sabato"),
("7","Domenica")
]
giorni_settimana = models.CharField(
choices = giorni_settimana_scelta,
max_length = 300
)
single_piano = models.ForeignKey(
Piano,
on_delete = models.CASCADE,
related_name = 'single_piano'
)
def __str__(self):
return self.giorni_settimana
class Meta:
verbose_name = "Piano singolo"
verbose_name_plural = "Piani singoli"
views.py
#login_required
def PianoSingleView(request, id):
piano = get_object_or_404(models.Piano, id = id, utente_piano = request.user)
if request.method == 'POST':
giorno_form = PianoSingleDayForm(request.POST, prefix = 'giorno')
if giorno_form.is_valid():
day_piano = giorno_form.save(commit = False)
day_piano.single_piano = piano
day_piano.save()
return redirect('gestione-piano', id = piano.id)
else:
giorno_form = PianoSingleDayForm(prefix = 'giorno')
context = {'piano': piano, 'giorno_form': giorno_form}
return render(request, 'crud/create/gestione_piano_single.html', context)
forms.py
class PianoSingleDayForm(forms.ModelForm):
class Meta:
model = models.PianoSingleDay
exclude = ['single_piano']
1
2
You can let the PianoSingleDayForm exclude the days that have already been selected for that Piano with:
class PianoSingleDayForm(forms.ModelForm):
def __init__(self, *args, piano=None, **kwargs):
super().__init__(*args, **kwargs)
if piano is not None:
days = set(PianoDaySingle.objects.filter(
single_piano=piano
).values_list('giorni_settimana', flat=True))
self.fields['giorni_settimana'].choices = [
(k, v)
for k, v in self.fields['giorni_settimana'].choices
if k not in days
]
class Meta:
model = models.PianoSingleDay
exclude = ['single_piano']
We can then use this in the view by passing the Piano object to the form both in the GET and POST codepath:
#login_required
def PianoSingleView(request, id):
piano = get_object_or_404(models.Piano, id=id, utente_piano=request.user)
if request.method == 'POST':
giorno_form = PianoSingleDayForm(request.POST, piano=piano, prefix='giorno')
if giorno_form.is_valid():
giorno_form.instance.single_piano = piano
giorno_form.save()
return redirect('gestione-piano', id=piano.id)
else:
giorno_form = PianoSingleDayForm(piano=piano, prefix='giorno')
context = {'piano': piano, 'giorno_form': giorno_form}
return render(request, 'crud/create/gestione_piano_single.html', context)

How to get books of the the same author in Django

I am developing an online Book Store.
Here is the models:
class Author(models.Model):
name = models.CharField(max_length=250, unique=True)
class Publisher(models.Model):
name = models.CharField(max_length=250, unique=True)
class Book(models.Model):
author = models.ManyToManyField(Author, related_name='authors')
publisher = models.ForeignKey(Publisher, on_delete=models.PROTECT, blank=True, null=True)
isbn13 = models.BigIntegerField(unique=True)
name = models.CharField(max_length=500)
...
Here is the View:
class AuthorsListView(ListView):
model = Author
context_object_name = 'authors_list'
template_name = 'authors_list.html'
paginate_by = 500
class AuthorBooksListView(ListView):
model = Book
context_object_name = 'author_books'
template_name = 'author_books.html'
def get_queryset(self, **kwargs):
author_id = Author.objects.get(pk = self.kwargs['pk'])
qs = super().get_queryset(**kwargs)
return qs.filter(author = author_id)
def get_context_data(self, **kwargs):
# Call the base implementation first to get a context
context = super().get_context_data(**kwargs)
# Add in a QuerySet
context['author'] = Author.objects.get(pk = self.kwargs['pk'])
return context
class PublishersListView(ListView):
model = Publisher
context_object_name = 'publishers_list'
template_name = 'publishers_list.html'
paginate_by = 500
class PublisherBooksListView(ListView):
model = Book
context_object_name = 'publisher_books'
template_name = 'publisher_books.html'
paginate_by = 20
def get_queryset(self, **kwargs):
publisher_id = Publisher.objects.get(pk = self.kwargs['pk'])
qs = super().get_queryset(**kwargs)
return qs.filter(publisher = publisher_id)
def get_context_data(self, **kwargs):
# Call the base implementation first to get a context
context = super().get_context_data(**kwargs)
# Add in a QuerySet
context['publisher'] = Publisher.objects.get(pk = self.kwargs['pk'])
return context
class BooksListView(ListView):
model = Book
context_object_name = 'books_list'
template_name = 'books_list.html'
paginate_by = 100
class BookDetailView(DetailView):
model = Book
template_name = 'book_detail.html'
Here is the urls:
path('authors/', AuthorsListView.as_view(), name = 'authors_list'),
path('author/<int:pk>/', AuthorBooksListView.as_view(), name='author_detail'),
path('publishers/', PublishersListView.as_view(), name='publishers_list'),
path('publisher/<int:pk>/', PublisherBooksListView.as_view(), name='publisher_detail'),
path('', BooksListView.as_view(), name='books_list'),
path('book/<int:pk>/', BookDetailView.as_view(), name='book_detail'),
On the Book Detail Page I want to display:
Related books by the same author
Related books by the same publisher
How can I do this? Please help me.
I was trying to add these code to the BookDetailView:
def get_queryset(self, **kwargs):
book = Book.objects.get(pk = self.kwargs['pk'])
queryset = {
'books': Book.objects.all(),
'publisher_books': Book.objects.filter(publisher = book.publisher.id),
}
return queryset
But it gives me an error:
'dict' object has no attribute 'filter'
#djangodjarhes - Can you try the following? Ideally I modify the get_queryset if I want to change the way the queryset should be filtered other than the URL kwargs. For anything else, I override the get_context_data
def get_context_data(self, **kwargs):
context = super(BookDetailView, self).get_context_data(**kwargs)
book = Book.objects.get(pk = self.kwargs['pk'])
publisher_books = Book.objects.filter(publisher = book.publisher.id)
context["publisher_books"] = publisher_books
return context
In your case and feel free to correct me
queryset = {
'books': Book.objects.all(),
'publisher_books': Book.objects.filter(publisher = book.publisher.id),
}
This is not right. You are returning a dict when the get_queryset is supposed to return a queryset. You cannot return a dict. Either you change it to do this
queryset = Book.objects.filter(publisher = book.publisher.id)
return queryset
or use get_context_data if you want to return a dict.

Django REST api and django_filter problem

I have problem with rest_framework.viewsets.ReadOnlyModelViewSet.
class ProductFilter(filters.FilterSet):
meat_type = filters.CharFilter(lookup_expr='slug__iexact')
category = filters.CharFilter(lookup_expr='slug__iexact')
class Meta:
model = Product
fields = {
'price': ['gte', 'lte'],
}
ordering_fields = ['price', ]
class ProductViewSet(viewsets.ReadOnlyModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
filterset_class = ProductFilter
#action(methods=['get'], detail=False)
def get_products(self, request):
products = self.get_queryset().order_by('-created')
serializer = self.get_serializer_class()(products, many=True)
print('SHOW IT')
if len(products) == 0:
return Response(status=status.HTTP_204_NO_CONTENT)
return Response(serializer.data, status=status.HTTP_200_OK)
My problem is that print in get_products not work, but code give good result with filters objects. My urls:
router = routers.DefaultRouter()
router.register('', views.ProductViewSet)
urlpatterns = [
path('shop/', include(router.urls))
]
Tests:
class TestViews(TestCase):
def setUp(self):
self.client = Client()
self.url = "/api/shop/"
self.search_url = "/api/shop/?price__lte={}&price__gte={}&meat_type={}&category={}"
self.category1 = Category.objects.create(name='cattest1',
slug='cattest1')
self.category2 = Category.objects.create(name='cattest2',
slug='cattest2')
self.meat_type1 = MeatType.objects.create(name='meattest1',
slug='meattest1')
self.meat_type2 = MeatType.objects.create(name='meattest2',
slug='meattest2')
self.product1 = Product.objects.create(category=self.category1,
meat_type=self.meat_type2,
name='prodtest1',
slug='prodtest1',
price=50)
self.product2 = Product.objects.create(category=self.category1,
meat_type=self.meat_type1,
name='prodtest2',
slug='prodtest2',
price=75)
self.product3 = Product.objects.create(category=self.category2,
meat_type=self.meat_type2,
name='prodtest3',
slug='prodtest3',
price=20)
self.product4 = Product.objects.create(category=self.category2,
meat_type=self.meat_type1,
name='prodtest4',
slug='prodtest4',
price=150)
def test_get_products_all(self):
response = self.client.get(self.url)
self.assertEqual(200, response.status_code)
self.assertEqual(4, len(response.data))
def test_get_products_no_content(self):
Product.objects.all().delete()
response = self.client.get(self.url)
self.assertEqual(204, response.status_code)
def test_product_greater_than(self):
response = self.client.get(self.search_url.format(
"", "55", "", ""
))
self.assertEqual(200, response.status_code)
self.assertEqual(2, len(response.data))
Test test_get_products_no_content fail with error:
assertionError: 204 != 200.
Somebody have any idea?
Thanks for any answer
Magnus
EDIT
Created this function, is pass good data to filter.
DICT {'price__lte': '50', 'price__gte': '100', 'meat_type': 'wieprzowina'}
But I have problem when I put it as filter argument. Got error:
invalid literal for int() with base 10: 'wieprzowina'. It try to change string to number, but I dont know why.
def get_queryset(self):
filter_params = self.request.query_params
filter_params_dict = {k: str(v) for (k, v) in filter_params.dict().items()
if v is not None and str(v) != ""}
print('DICT', filter_params_dict)
queryset = Product.objects.filter(**filter_params_dict)
return queryset
EDIT 2:
class Product(models.Model):
category = models.ForeignKey(Category,
related_name='products',
on_delete=models.CASCADE)
meat_type = models.ForeignKey(MeatType,
on_delete=models.CASCADE)
name = models.CharField(max_length=150,
db_index=True)
slug = models.SlugField(max_length=150,
db_index=True)
image = models.ImageField(upload_to='products/%Y/%m/%d',
default='no-image.png')
description = models.TextField(blank=True)
price = models.DecimalField(max_digits=10, decimal_places=2)
available = models.BooleanField(default=True)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
class Meta:
ordering = ('price',)
index_together = (('id', 'slug'),)
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('shop:detail',
args=[self.category.slug, self.id, self.slug])
You are using the incorrect url ,you should use this url for your custom action:
/api/shop/get_products/
The url you are using i.e /api/shop/ will call the default list action of the viewset not your custom action and thats why you are getting 200 status code always
You can read more about viewset here:
ViewSets

Retrieving ID to use in a query, Django

I have a simple question I guess:
I am trying to query my data base in order to retrieve the number of team members linked to a specific team, linked to a specific project.
team_member_count = Project.objects.get(id = id).team_id.members.count()
The query is for the project detail view using a url like : localhost/website/project/141/
In the shell my query is Project.objects.get(id = 141).team_id.members.count()
but in the views I get :
TypeError: int() argument must be a string, a bytes-like object or a number, not 'builtin_function_or_method'
My view is the following (retrieving data for chart.js)
class ChartData(APIView):
authentication_classes = []
permission_classes = []
def get(self, request, format=None, *args, **kwargs):
user_count = MyUser.objects.all().count()
project_count = Project.objects.all().count()
team_member_count = Project.objects.get(id = id).team_id.members.count()
labels = ["Users", "Projects", "Team_number", "Green", "Purple", "Orange"]
default_items = [user_count, project_count,team_member_count,28,12,32]
data = {
"labels":labels,
"default":default_items,
}
return Response(data)
Models :
class Team(models.Model):
team_name = models.CharField(max_length=100, default = '')
team_hr_admin = models.ForeignKey(MyUser, blank=True, null=True)
members = models.ManyToManyField(MyUser, related_name="members")
def __str__(self):
return self.team_name
class Project(models.Model):
name = models.CharField(max_length=250)
team_id = models.ForeignKey(Team, blank=True, null=True)
project_hr_admin = models.ForeignKey('registration.MyUser', blank=True, null=True)
candidat_answers = models.ManyToManyField('survey.response')
def get_absolute_url(self):
return reverse('website:ProjectDetails', kwargs = {'pk' : self.pk})
def __str__(self):
return self.name
URL patterns:
app_name = 'website'
urlpatterns = [
url(r'^hr_index/$', views.HRIndex.as_view(), name='hr_index'),
url(r'^candidate_index/$', views.CandidateIndex.as_view(),name='candidate_index'),
url(r'^employee_index/$', views.EmployeeIndex.as_view(),name='employee_index'),
url(r'^addproject/$', views.ProjectCreate.as_view(), name='add_project'),
url(r'^addteam/$', views.TeamCreate.as_view(), name='add_team'),
url(r'^linkteam/$', views.LinkTeam.as_view(), name='link_team'),
url(r'^linkteam2/$', views.TeamSelect, name='team_select'),
url(r'^project/(?P<pk>[0-9]+)/$',views.ProjectDetailView.as_view(), name='ProjectDetails'),
url(r'^project/(?P<pk>[0-9]+)/api/chart/data/$', views.ChartData.as_view(), name='chartdata'),
]
You don't have a local variable called id in your get method; Python is assuming you're referring to the global built-in id() function, hence the error.
According to your URLs, you are capturing a keyword argument called pk. So you should get that from the kwargs dict:
Project.objects.get(id=kwargs['pk'])...