Django: Problem with Getting The Right Objects - python

I am a beginner learning Django through a building an app, called PhoneReview. It will store reviews related to the latest mobile phone. It will also display phone brands, along with the associated phone models and their reviews.
Right now, I am facing a problem. I have added two phone brands, Samsung and Apple, through Django admin. They are being displayed at http://127.0.0.1:8000/index.
When I click on Samsung, I see three phone models, Galaxy S10, Galaxy Note 10 and iPhone 11, which have already been added through Django admin. However, iPhone 11 is not supposed to be displayed here, as its brand is Apple, not Samsung. So, basically, when I click on Samsung, only Galaxy S10 and Galaxy Note 10 are supposed to be displayed, not iPhone 11.
How can I fix the issue?
Here are my codes of models.py located inside PhoneReview folder:
from django.db import models
from django.template.defaultfilters import slugify
# Create your models here.
class Brand(models.Model):
brand_name = models.CharField(max_length=100)
origin = models.CharField(max_length=100)
manufacturing_since = models.CharField(max_length=100, null=True, blank=True)
def __str__(self):
return self.brand_name
def save(self, *args, **kwargs):
self.slug = slugify(self.brand_name)
super().save(*args, **kwargs)
class PhoneModel(models.Model):
brand = models.ForeignKey(Brand, on_delete=models.CASCADE)
model_name = models.CharField(max_length=100)
launch_date = models.CharField(max_length=100)
platform = models.CharField(max_length=100)
def __str__(self):
return self.model_name
class Review(models.Model):
phone_model = models.ManyToManyField(PhoneModel, related_name='reviews')
review_article = models.TextField()
date_published = models.DateField(auto_now=True)
# slug = models.SlugField(max_length=150, null=True, blank=True)
link = models.TextField(max_length=150, null=True, blank=True)
def __str__(self):
return self.review_article
Here are my codes of urls.py located inside PhoneReview folder:
from . import views
from django.urls import path
urlpatterns = [
path('index', views.BrandListView.as_view(), name='brandlist'),
path('phonemodel/<int:pk>/', views.ModelView.as_view(), name='modellist'),
path('details/<int:pk>/', views.ReviewView.as_view(), name='details'),
]
Here are my codes of views.py located inside PhoneReview folder:
from django.shortcuts import render
from django.views import generic
from .models import Brand, PhoneModel, Review
class BrandListView(generic.ListView):
template_name = 'PhoneReview/index.html'
context_object_name = 'all_brands'
def get_queryset(self):
return Brand.objects.all()
class ModelView(generic.ListView):
template_name = 'PhoneReview/phonemodel.html'
context_object_name = 'all_model_name'
def get_queryset(self):
return PhoneModel.objects.all()
class ReviewView(generic.DetailView):
model = Review
template_name = 'PhoneReview/details.html'
Here are my codes of apps.py located inside PhoneReview folder:
from django.apps import AppConfig
class PhonereviewConfig(AppConfig):
name = 'PhoneReview'
Here are my codes of index.html located inside templates folder:
{% extends 'PhoneReview/base.html' %}
{% load static %}
{% block title%}
Brand List
{% endblock %}
{% block content %}
<!--Page content-->
<h1>This is Brand List Page</h1>
<h2>Here is the list of the brands</h2>
<ul>
{% for brand in all_brands %}
<!-- <li>{{ brand.brand_name }}</li>-->
<li>{{ brand.brand_name }}</li>
{% endfor %}
</ul>
<img src="{% static "images/brandlist.jpg" %}" alt="Super Mario Odyssey" /> <!-- New line -->
{% endblock %}
Here are my codes of phonemodel.html located inside templates folder:
{% extends 'PhoneReview/base.html' %}
{% load static %}
{% block title%}
Phone Model Page
{% endblock %}
{% block content %}
<!--Page content-->
<h1>This is Phone Model Page</h1>
<h2>Here is the phone model</h2>
<ul>
{% for phonemodel in all_model_name %}
<li>{{ phonemodel.model_name }}</li>
{% endfor %}
</ul>
<img src="{% static "images/brandlist.jpg" %}" alt="Super Mario Odyssey" /> <!-- New line -->
{% endblock %}
Here are my codes of details.html located inside templates folder:
{% extends 'PhoneReview/base.html' %}
{% load static %}
<html>
<link rel="stylesheet" type="text/css" href="{% static "css/style.css" %}">
<html lang="en">
{% block title%}Details{% endblock %}
{% block content %}
<h1>This is the Details Page</h1>
<h2>Review:</h2>
<p>{{ review.review_article }}</p>
<h2>News Link:</h2>
<p>{{ review.link }}</p>
{% endblock %}
</html>
Have I done anything wrong in views.py?

Change your list view see this
class ModelView(generic.ListView):
template_name = 'PhoneReview/phonemodel.html'
context_object_name = 'all_model_name'
def get_queryset(self):
self.brand = get_object_or_404(Brand, pk=self.kwargs['pk'])
return PhoneModel.objects.filter(brand=self.brand)

Related

How can I get my html to display my django model?

I'm trying to get my django model to be shown in the footer of my base.html but I can't get it to show up. I've looked at a few videos and I can't figure out where I'm going wrong. I know that the model works as I've made 4 entries in my database and I can view them on the admin page. The code also doesn't show any errors so I have nothing to go off of there. Here it is:
Models.py
class SocialMediaPlatform(models.Model):
name = models.CharField(max_length=50, blank=True, null=True)
font_awesome_class = models.CharField(max_length=50, blank=True, null=True)
base_url = models.CharField(max_length=50, blank=True, null=True,
default='https://instagram.com/ or https://tiktok.com/#')
def __str__(self):
return self.base_url
Views.py
def social_media_base_view(request):
context = {}
smbase = SocialMediaPlatform.objects.all()
context['smbase'] = smbase
return render(request, 'base.html', context)
Urls.py
urlpatterns = [
path('', views.social_media_base_view),
]
Admin.py
#admin.register(SocialMediaPlatform)
class SocialPlatformAdmin(admin.ModelAdmin):
list_display = ('name', 'font_awesome_class', 'base_url')
base.html
{% for smlink in smbase %}
<a href="{{ smlink.name }}">
<i class="{{ smlink.font_awesome_class }}">
</a>
{% endfor %}
Look what you are passing as context:
def social_media_base_view(request):
...
smbase = SocialMediaPlatform.objects.all()
context['smbase'] = smbase
return ...
It's QuerySet of SocialMediaPlatform objects. It means, that you can render them one by one with for loop:
{% for smlink in smbase %}
{{ smlink.name }}
{% endfor %}
You don't need to call SocialMediaPlatform model additionaly.
in your view you use:
return render(request, 'index.html', context)
i can not see, if you are defined index.html
Somethere in index you should have
{% extends base.htm %}
The second, i am agree with #Shabble:
{% for smlink in smbase %}
<a href="{{ smlink.name }}">
<i class="{{ smlink.font_awesome_class }}">
</a>
{% endfor %}
The last:
Try to use Django-GCBV TemplateView. Or ListView, in your case it is better:
somethere in views.py
Class MyListView(ListView):
model = SocialMediaPlatform
template_name = index.html
somethere in urls.py
urlpatterns = [
path('', MyListView.as_view()),
]
somethere in index.html
{% for smlink in object_list %}
<a href="{{ smlink.name }}">
<i class="{{ smlink.font_awesome_class }}">
</a>
{% endfor %}

How to use URL Python Django

I'm trying to learn Python Django with book "Example_Build_powerful_and_reliable_Python_web_applications" by Antonio Mele.
Really sorry for probably stupid questions, but i'm very new.
And sorry for my English, it isn't my native language.
Have some problem with one of the example from the book.
Do the same things as in the book, but URL's dont work.
MODELS.PY
from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User
from django.urls import reverse
class PublishedManager(models.Manager):
def get_queryset(self):
return super(PublishedManager, self).get_queryset().filter(status='published')
class Post(models.Model):
STATUS_CHOICES = (
('draft', 'draft'),
('published', 'published')
)
title = models.CharField(max_length=250)
slug = models.SlugField(max_length=250,
unique_for_date='publish')
body = models.TextField()
publish = models.DateTimeField(default=timezone.now)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
status = models.CharField(max_length=10,
choices=STATUS_CHOICES,
default='draft')
objects = models.Manager()
published = PublishedManager()
class Meta:
ordering = ('-publish',)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('blog:post_detail',
args=[self.publish.year,
self.publish.month,
self.day, self.slug])
VIEWS.PY
from django.shortcuts import render, get_object_or_404
from .models import Post
def post_list(request):
posts = Post.published.all
return render(request,
'blog/post/list.html',
{'posts': posts})
def post_detail(request, post):
post = get_object_or_404(Post, slug = post)
return render(request, 'blog/post/detail.html', {'post': post})
URLS.PY
from django.urls import path
from . import views
app_name ='blog'
urlpatterns = [
path('', views.post_list, name='post_list'),
path('<int:year>/<int:month>/<int:day>/<slug:post>/',
views.post_detail,
name='post_detail'),
]
BASE.HTML
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>{% block title %} {% endblock %}</title>
</head>
<body>
<div id="content">
{% block content %}
{% endblock %}
</div>
<div id="sidebar">
<h2>My Blog</h2>
<p>This is my blog</p>
</div>
</body>
</html>
LIST.HTML
{% extends "blog/base.html" %}
{% block title %}My blog{% endblock%}
{% block content %}
<h1>My Blog</h1>
{% for post in posts %}
<h2>
<a href="{{ post.get_absolute_url }}">
{{post.title}}
</a>
</h2>
<p class="date">
Published {{ post.publish }} by {{ post.author }}
</p>
{{ post.body|truncatewords:30|linebreaks }}
{% endfor %}
{% endblock %}
DETAIL.HTML
{% extends "blog/base.html" %}
{% block title %} {{ post.title }} {% endblock %}
{% block content %}
<h1> {{ post.title }} </h1>
<p class = "date">
Published {{ post.publish }} by {{ post.author }}
</p>
{{ post.body|linebreaks }}
{% endblock %}
Also add my urls to URLS here:
enter image description here
The problem is: when i click on posts on the page BASE.HTML i dont see correct URL and nothing is happening:
enter image description here
Really break my brain.
Thanks in advance for help.
Your VIEWS.py should contain the methods post(self,request) OR get(self,request) to be callable from the rendered HTML. The methods post_list(..) OR post_detail(..) are not callable on the Django framework.
Oh my f...ng god.
If somebody will face with the same problem..
In MODELS.PY just need to move Class Meta and 2 defs:
from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User
from django.urls import reverse
class PublishedManager(models.Manager):
def get_queryset(self):
return super(PublishedManager, self).get_queryset().filter(status='published')
class Post(models.Model):
STATUS_CHOICES = (
('draft', 'draft'),
('published', 'published')
)
title = models.CharField(max_length=250)
slug = models.SlugField(max_length=250,
unique_for_date='publish')
body = models.TextField()
publish = models.DateTimeField(default=timezone.now)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
status = models.CharField(max_length=10,
choices=STATUS_CHOICES,
default='draft')
objects = models.Manager()
published = PublishedManager()
class Meta:
ordering = ('-publish',)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('blog:post_detail',
args=[self.publish.year,
self.publish.month,
self.day, self.slug])
And then in will work good.
Very stupid mistake, so hard to find this..

Django: Problem with Using Slug in Templates

I am a beginner in Django. I am building a Django app, named PhoneReview. It will store reviews related to the latest mobile phone. It will also display phone brands, along with the associated phone models.
I have already created models, views and the template files. Now, I am facing a problem. I can't use slug in URLs. Right now, it looks like this:
Here are my codes of models.py located inside PhoneReview folder:
from django.db import models
from django.template.defaultfilters import slugify
# Create your models here.
class Brand(models.Model):
brand_name = models.CharField(max_length=100)
origin = models.CharField(max_length=100)
manufacturing_since = models.CharField(max_length=100, null=True, blank=True)
slug = models.SlugField(max_length=150, null=True, blank=True)
def __str__(self):
return self.brand_name
def save(self, *args, **kwargs):
self.slug = slugify(self.brand_name)
super().save(*args, **kwargs)
class PhoneModel(models.Model):
brand = models.ForeignKey(Brand, on_delete=models.CASCADE)
model_name = models.CharField(max_length=100)
launch_date = models.CharField(max_length=100)
platform = models.CharField(max_length=100)
slug = models.SlugField(max_length=150, null=True, blank=True)
def __str__(self):
return self.model_name
def save(self, *args, **kwargs):
self.slug = slugify(self.model_name)
super().save(*args, **kwargs)
class Review(models.Model):
phone_model = models.ManyToManyField(PhoneModel, related_name='reviews')
review_article = models.TextField()
date_published = models.DateField(auto_now=True)
# slug = models.SlugField(max_length=150, null=True, blank=True)
link = models.TextField(max_length=150, null=True, blank=True)
def __str__(self):
return self.review_article
Here are my codes of urls.py located inside PhoneReview folder:
from . import views
from django.urls import path
urlpatterns = [
path('index', views.BrandListView.as_view(), name='brandlist'),
path('phonemodel/<int:pk>/', views.ModelView.as_view(), name='modellist'),
path('details/<int:pk>/', views.ReviewView.as_view(), name='details'),
]
Here are my codes of views.py located inside PhoneReview folder:
from django.views import generic
from .models import Brand, PhoneModel, Review
class BrandListView(generic.ListView):
template_name = 'PhoneReview/index.html'
context_object_name = 'all_brands'
def get_queryset(self):
return Brand.objects.all()
class ModelView(generic.DetailView):
model = PhoneModel
template_name = 'PhoneReview/phonemodel.html'
class ReviewView(generic.DetailView):
model = Review
template_name = 'PhoneReview/details.html'
Here are my codes of apps.py located inside PhoneReview folder:
from django.apps import AppConfig
class PhonereviewConfig(AppConfig):
name = 'PhoneReview'
Here are my codes of index.html located inside templates folder:
{% extends 'PhoneReview/base.html' %}
{% load static %}
{% block title%}
Brand List
{% endblock %}
{% block content %}
<!--Page content-->
<h1>This is Brand List Page</h1>
<h2>Here is the list of the brands</h2>
<ul>
{% for brand in all_brands %}
<!-- <li>{{ brand.brand_name }}</li>-->
<li>{{ brand.brand_name }}</li>
{% endfor %}
</ul>
<img src="{% static "images/brandlist.jpg" %}" alt="Super Mario Odyssey" /> <!-- New line -->
{% endblock %}
Here are my codes of phonemodel.html located inside templates folder:
{% extends 'PhoneReview/base.html' %}
{% load static %}
{% block title%}
Phone Model Page
{% endblock %}
{% block content %}
<!--Page content-->
<h1>This is Phone Model Page</h1>
<h2>Here is the phone model</h2>
<ul>
<li>{{ phonemodel.model_name }}</li>
</ul>
<img src="{% static "images/brandlist.jpg" %}" alt="Super Mario Odyssey" /> <!-- New line -->
{% endblock %}
In index.html, I tried to replace <li>{{ phonemodel.model_name }}</li> with <li>{{ phonemodel.model_name }}</li>. But I get error.
How can I fix the issue?
Update: I added the codes provided by #arjun. However, I am getting an error. It says the following
OperationalError at /index
no such table: PhoneReview_brand
You need to pass slug instead of pk through your url if you want to use slug
path('phonemodel/<slug:slug>/', views.ModelView.as_view(), name='modellist'),
path('details/<slug:slug>/', views.ReviewView.as_view(), name='details'),
Now in template instead of id
<li>{{ phonemodel.model_name }}</li>
And it's better to have unique slug field
slug = models.SlugField(max_length=150, unique=True)
Also I will suggest you to use the django-autoslug. It is a reusable Django library that provides an improved slug field which can automatically populate itself from another field.
EDIT:You haven't passed context_object_name in your detail view so provide the context here
class ModelView(generic.DetailView):
model = PhoneModel
template_name = 'PhoneReview/phonemodel.html'
context_object_name= 'phonemodel'

Django: Problem with Adding Clickable Link in the Second Template

I am a beginner in Django. I am building a Django app, named PhoneReview. It will store reviews related to the latest mobile phone. It will also display phone brands, along with the associated phone models.
I have already created models and views. I have also managed to add clickable link in the first template (brandlist.html). In the first template, when you click on the brand name, like Samsung, you will be taken to the page of the phone model, like Galaxy S10.
Here is the screenshot of the first template:
When you click the link, you will be taken to the second template (phonemodel.html). But now, I am facing an issue. There is no clickable link on the phone model ("Galaxy S10") that will direct you to details.html. Here is the screenshot.
Here are the codes of models.py inside the "PhoneReview" folder:
from django.db import models
from django.template.defaultfilters import slugify
# Create your models here.
class Brand(models.Model):
brand_name = models.CharField(max_length=100)
origin = models.CharField(max_length=100)
manufacturing_since = models.CharField(max_length=100, null=True, blank=True)
def __str__(self):
return self.brand_name
def save(self, *args, **kwargs):
self.slug = slugify(self.brand_name)
super().save(*args, **kwargs)
class PhoneModel(models.Model):
brand = models.ForeignKey(Brand, on_delete=models.CASCADE)
model_name = models.CharField(max_length=100)
launch_date = models.CharField(max_length=100)
platform = models.CharField(max_length=100)
def __str__(self):
return self.model_name
class Review(models.Model):
phone_model = models.ManyToManyField(PhoneModel, related_name='reviews')
review_article = models.TextField()
date_published = models.DateField(auto_now=True)
slug = models.SlugField(max_length=150, null=True, blank=True)
def __str__(self):
return self.review_article
Here are the codes of urls.py inside the "PhoneReview" folder:
from . import views
from django.urls import path
urlpatterns = [
path('index', views.BrandListView.as_view(), name='brandlist'),
path('phonemodel/<int:pk>/', views.ModelView.as_view(), name='modellist'),
path('details/<int:pk>/', views.ReviewView.as_view(), name='details'),
]
Here are the codes of views.py inside the "PhoneReview" folder:
from django.views import generic
from .models import Brand, PhoneModel, Review
class BrandListView(generic.ListView):
template_name = 'PhoneReview/brandlist.html'
context_object_name = 'all_brands'
def get_queryset(self):
return Brand.objects.all()
class ModelView(generic.DetailView):
model = PhoneModel
template_name = 'PhoneReview/phonemodel.html'
class ReviewView(generic.DetailView):
model = Review
template_name = 'PhoneReview/details.html'
Here are the codes of apps.py inside the "PhoneReview" folder:
from django.apps import AppConfig
class PhonereviewConfig(AppConfig):
name = 'PhoneReview'
Here are the codes of details.html inside the "templates" folder:
{% extends 'PhoneReview/base.html' %}
{% load static %}
<html>
<link rel="stylesheet" type="text/css" href="{% static "css/style.css" %}">
<html lang="en">
{% block title%}Details{% endblock %}
{% block content %}
<h1>This is the Details Page</h1>
<h2>Review:</h2>
<p>{{ review.review_article }}</p>
<h2>News Link:</h2>
<p>{{ review.slug }}</p>
{% endblock %}
</html>
Here are the codes of phonemodel.html inside the "templates" folder:
{% extends 'PhoneReview/base.html' %}
{% load static %}
{% block title%}
Phone Model Page
{% endblock %}
{% block content %}
<!--Page content-->
<h1>This is Phone Model Page</h1>
<h2>Here is the phone model</h2>
<ul>
<li>{{ phonemodel.model_name }}</li>
</ul>
<img src="{% static "images/brandlist.jpg" %}" alt="Super Mario Odyssey" /> <!-- New line -->
{% endblock %}
I tried replacing <li>{{ phonemodel.model_name }}</li> with <li>{{ phonemodel.model_name }}</li>. But I get an error, which looks like this:
NoReverseMatch at /phonemodel/1/
Reverse for 'details' with arguments '('',)' not found. 1 pattern(s) tried: ['details/(?P<pk>[0-9]+)/$']
How can I fix the issue?
There is no context variable named brand and you don't need it anyway. You should use the id of the phonemodel:
<li>
<a href = "{% url 'details' phonemodel.id %}">
{{ phonemodel.model_name }}
</a>
</li>

ImproperlyConfigured at /app/category/Python/

I wanna make a page which shows POST's models' contents is shown each category.For example, when I put Python link in in detail.html,only POST's models' contents with Python's category is shown in category.html.When I put Python link in category.html,I got an error,ImproperlyConfigured at /app/category/Python/ CategoryView is missing a QuerySet. Define CategoryView.model, CategoryView.queryset, or override CategoryView.get_queryset(). I wrote codes in views.py
def top(request):
content = POST.objects.order_by('-created_at')[:5]
category_content = Category.objects.order_by('-created_at')[:5]
page = _get_page(blog_content, request.GET.get('page'))
return render(request, 'top.html',{'content':content,'category_content':category_content,"page":page})
class CategoryView(BaseListView):
template_name = 'category.html'
def get_queryset(self):
category_name = self.kwargs['category']
self.category = Category.objects.get(name=category_name)
queryset = super().get_queryset().filter(category=self.category)
return queryset
def get_context_data(self, *args, **kwargs):
context = super().get_context_data(*args, **kwargs)
context['category'] = self.category
return context
in urls.py
urlpatterns = [
path('top/', views.top, name='top'),
path('category/<str:category>/',views.CategoryView.as_view(), name='category'),
]
in models.py
class Category(models.Model):
name = models.CharField(max_length=100)
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.name
class POST(models.Model):
title = models.CharField(max_length=100)
created_at = models.DateTimeField(auto_now_add=True)
category = models.ForeignKey(Category, on_delete=models.CASCADE)
def __str__(self):
return self.title
in top.html
<div class="list-group">
<a href="#">
Category
</a>
<div>
{% for category in category_content %}
<a href="{% url 'category' category.name %}">
{{ category.name }}
</a>
{% endfor %}
</div>
</div>
in category.html
{% load static %}
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Category</title>
</head>
<body>
<div>
{% for content in queryset %}
<h2>{{ content.title }}</h2>
<img src="content.image.url" />
<a class="btn btn-outline-primary btn-lg btn-block" href="{% url 'detail' content.pk %}">SHOW DETAIL</a>
{% endfor %}
</div>
<div>
<a href="#" class="list-group-item active">
Category
</a>
<div>
{% for category in category_content %}
<a class="list-group-item justify-content-between" href="{% url 'category' category.name %}">
{{ category.name }}
</a>
{% endfor %}
</div>
</div>
</body>
</html>
I really cannot understand why ImproperlyConfigured which means settings.py is wrong.When I changed BaseListView into ListView,same error happens.I wrote get_queryset in CategoryView's class so I cannot understand codes needs QuerySet. How should I fix this?What is wrong in my codes?
One issue is that you're calling super().get_queryset(), which expects your class to define a queryset or a model. Adding model = Category will fix that error.
It looks like you're returning a queryset with just one entry, though. If you only want to get the one category, it would be simpler to use a DetailView:
from django.views.generic import DetailView
from .models import Category # or wherever it is
class CategoryView(DetailView):
model = Category
template_name = 'category.html'
def get_object(self):
category_name = self.kwargs['category']
return Category.objects.get(name=category_name)
Note that your template would need to be updated to reference category or object instead of looping through the queryset.

Categories