'CategoryDetail' object has no attribute '_state' - django

I want to get the properties by categories.
When I try to reach for example : http://127.0.0.1:8000/category/Berlin the following error comes:
'CategoryDetail' object has no attribute '_state'
What am I doing wrong?
Any help will be highly appreciated.
models.py
from django.db import models
from django.urls import reverse
# Create your models here.
class Property(models.Model):
title = models.CharField(max_length=140)
description = models.TextField()
rooms = models.PositiveIntegerField()
bed_rooms = models.PositiveIntegerField()
land_size = models.PositiveIntegerField()
slug = models.SlugField()
living_size = models.PositiveIntegerField()
build_year = models.PositiveIntegerField()
price = models.PositiveIntegerField()
category = models.ForeignKey(to='Category', null=True, related_name='categories', on_delete=models.SET_NULL,)
def get_absolute_url(self):
return reverse('properties:PropertyDetail', kwargs={'slug': self.slug})
def __str__(self):
return '{} - {}'.format(
self.title, self.build_year
)
class Category(models.Model):
name = models.CharField(max_length=150)
slug = models.SlugField()
def get_absolute_url(self):
return reverse('properties:CategoryDetail', kwargs={'slug': self.slug})
def __str__(self):
return '{}'.format(self.name)
views.py
from django.shortcuts import render
from .filters import PropertyFilter
# Create your views here.
from django.views.generic import (
TemplateView, DetailView, ListView
)
from .models import Property, Category
class HomePage(TemplateView):
template_name = 'home.html'
class PropertyList(ListView):
model = Property
class PropertyDetail(DetailView):
model = Property
class CategoryList(ListView):
model = Category
class CategoryDetail(ListView):
queryset = Category.categories
template_name = 'categorydetail.html'
def search(request):
property_list = Property.objects.all()
property_filter = PropertyFilter(request.GET, queryset=property_list)
return render(request, 'prop_list.html', {'filter': property_filter})
urls.py
from django.urls import path
from .views import (PropertyList, PropertyDetail, HomePage, CategoryList, CategoryDetail)
app_name = 'properties'
urlpatterns = [
path('', HomePage.as_view(), name='home'),
path('categories', CategoryList.as_view(), name='categories'),
path('category/<slug:slug>', CategoryDetail.as_view(), name='CategoryDetail'),
path('properties', PropertyList.as_view(), name='PropertyList'),
path('property/<slug:slug>', PropertyDetail.as_view(), name='PropertyDetail'),
]
project urls
"""config URL Configuration
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/2.1/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path, include
from realestate import views
urlpatterns = [
path('admin/', admin.site.urls),
path('search', views.search, name='search'),
path('', include('realestate.urls', namespace='properties')),
]

Please adapt the following line in the class Property:
category = models.ForeignKey(to='Category', null=True, related_name='categories', on_delete=models.SET_NULL,)
to this:
category = models.ForeignKey(
to='Category',
null=True,
related_name='properties',
on_delete=models.SET_NULL,
)
The change is in bold. The reason for the change is that you want to get properties for a given Category. Making a query like Category.categories is confusing for the reader.
The related_name which is now properties can be accessed from a Category object. The way how you do it in the class CategoryDetail:
queryset = Category.categories
even if adapted to:
queryset = Category.properties
can't work. It is because it would call the related descriptor ReverseManyToOneDescriptor which is of no use here.
You can call the properties for an object Category. An example would be:
Category.objects.get(pk=1).properties.all()
The first part Category.objects.get(pk=1) will return a single object Category and in the second part properties.all() you call the manager properties on the object Category. With the method all() you retrieve a QuerySet containing all properties for the given Category object.
Remember that using something like Category.objects.all().properties.all() won't work. Category.objects.all() will return a QuerySet which has no attribute properties.
With this in mind the best approach would be as suggested by #Alasdair to use DetailView. You want to list all Properties for a Category and that confuses you a little bit. However you're still displaying the details for a Category. Using a DetailView for the Category here is a much cleaner and nicer approach.
Having just simple:
class CategoryDetail(DetailView):
model = Category
will do the job. The default template name will be category_detail.html and you don't need to specify it explicitly. Just be consistent with the other classes.
The internal logic of the detail view will retrieve a single object Category and in the template you can access the properties for this object:
{% for property in object.properties.all %}
{{ property }}
{% endfor %}
Instead of object.properties.all you can use category.properties.all, which is more verbose and improves the readability.
Should you wish to change that, do this for example:
class CategoryDetail(DetailView):
model = Category
context_object_name = 'ctgr'
{% for property in ctgr.properties.all %}
I hope this can bring you forward.

First, change the related_name to properties as #cezar suggested, since it is used to get the related properties for a category.
category = models.ForeignKey(to='Category', null=True, related_name='categories', on_delete=models.SET_NULL,)
I suggest you use a DetailView for category,
class CategoryDetail(DetailView):
model = Category
template_name = 'categorydetail.html'
Then you can use the reverse relationship to access the properties in the template:
{% for property in category.properties.all %}
If you really want to use a list view for CategoryDetail, then you need to override get_queryset and use the slug. For example you could do:
from django.shortcuts import get_object_or_404
class PropertiesForCategory(ListView):
template_name = 'categorydetail.html'
def get_queryset(self):
category = get_object_or_404(Category, slug=self.kwargs['slug']
return category.properties.all()
Then in the template you would loop through the queryset with:
{% for property in object_list %}

Related

get request in django?

I have problem with django request.I dont know. I tried to do everything, but I got
'blog' object has no attribute 'get'. I want to do mini blog on my website,but it isnt working now. I would like to get all objects from database.(Sorry,If I did something wrong,I am beginner in django and tried to functions for my website) :)
models.py
from django.db import models
# Create your models here.
CHOOSE =[
('Usual','Обычный тариф'),
('Premium','Премиум тариф'),
('Prise','Аукционный')
]
class VDSTARIFS( models.Model):
id = models.CharField(max_length=40, primary_key= True,serialize=True)
name = models.CharField(max_length=20, verbose_name = 'Цены')
choosen = models.CharField(max_length= 20, choices = CHOOSE, verbose_name = 'Тариф', help_text='Выбор тарифного плана.')
title = models.CharField(max_length= 15)
def __str__(self):
return str(self.title)
class blog(models.Model):
id = models.CharField(max_length=40, primary_key= True,serialize=True)
message = models.TextField( verbose_name= 'Сообщение блога')
titleblog = models.CharField(max_length=50, verbose_name = 'Название')
img = models.ImageField(upload_to = 'admin/', verbose_name= 'Картинка' )
def __str__(self):
return str(self.titleblog)
def get_all_objects(self): ##maybe I have troubles with it.
queryset = self.__class__.objects.all()
blog.html
{% csrftoken %}
{% for item in message %}
{% endfor %}
views.py
from django.shortcuts import render
from django.http import HttpResponse
from django.shortcuts import render
from django.http import HttpResponseRedirect
import os
from polls.models import VDSTARIFS
from polls.models import blog
from django.template.loader import render_to_string
def index_view(request):
#return HttpResponse("<h1>Hello</h1>")
return render(request, "home.html", {})
def about(request):
return render(request, "about.html", {})
def minecraft(request):
return render(request, "minecraft.html",{})
def vds(request):
HTML_STRING = render_to_string("vds.html", context = context1)
return HttpResponse(HTML_STRING)
try:
VDS1 = VDSTARIFS.objects.get(id=0)
name = VDS1.name
except VDSTARIFS.DoesNotExist:
VDS1 = None
context1 = {
'name':name,
'prise':VDS1,
}
def messagesblog(request,self):
HTML_STRING = render_to_string('blog.html')
return HttpResponse(HTML_STRING)
urls.py
from django.contrib import admin
from django.urls import path
from polls import views
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
path('admin/', admin.site.urls),
path('', views.index_view, name='home'),
path('vds', views.vds, name='vds' ),
path('minecraft', views.minecraft, name='minecraft' ),
path('about', views.about, name='about'),
path('blog', views.blog, name='blog')
]
The actual error is probably caused by the wrong url pattern:
path('blog', views.blog, name='blog')
views.blog refers to the blog model due to:
from polls.models import blog
What you need here is the view not the model, so:
path('blog', views.messagesblog, name='blog')
Then, remove the "self" argument from your messagesblog function.
Use the "render" function from django.shortcuts and provide a context with the blog objects:
def messagesblog(request):
return render(request, "blog.html", {message: blog.objects.all()})
That might solve your problem.
Still, there are some things you could improve.
E.g.: Don't use "id" fields in your model definitions if you don't really, really have to, as this is usually an auto-generated number (BigInt) field.
That's only one tip from an old Django veteran happy to be finally heard. You'll find out much more yourself as you proceed.

In the process of categorising my blogs but keep hitting the wall "Page not found 404"

I am a complete beginner so I apologies for my noobiness explanation. I am in the process of categorising my blogs.
I created a model -> migrated it -> imported in view.py -> Imported the view that I created into urls.py -> and created URL for my new page but when I add the href to other pages (home) it takes me to the error.
My codes:
models.py
class Category(models.Model):
name = models.CharField(max_length=100)
def __str__(self):
return self.name
class Post(models.Model):
title = models.CharField(max_length=100)
content=models.TextField()
date_posted=models.DateTimeField(default=timezone.now)
author=models.ForeignKey(User, on_delete=models.CASCADE)
category = models.CharField(max_length=100, default='Engineering')
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('post-detail', kwargs={'pk': self.pk})
Views.py:
from .models import Post, Category
class CategoryListView(ListView):
model = Post
template_name= 'blog/category_posts.html'
context_object_name = 'posts'
ordering = ['-date_posted']
paginate_by = 3
urls.py:
from django.urls import path
from .views import (
PostListView,
PostDetailView,
PostCreateView,
PostUpdateView,
PostDeleteView,
UserPostListView,
CategoryListView)
path('category/<str:category>/', CategoryListView.as_view(), name='category-posts'),
home.html
{{ post.category }}
In addition to what Arun said.
I think you need to set url_patters in your urls.py. Something like this:
from django.urls import path
from .views import (
PostListView,
PostDetailView,
PostCreateView,
PostUpdateView,
PostDeleteView,
UserPostListView,
CategoryListView)
urlpatterns = [
path('category/<str:category>/', CategoryListView.as_view(), name='category-posts'),
]
You should also pass the category in your url, like this
{{ post.category }}
Because your url needs a str parameter category.

little bit confuse in dgetting absolute url in django

#project url
from django.conf import settings
from django.conf.urls import url
from django.conf.urls.static import static
from django.contrib import admin
from django.urls import path, include
import products
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('products.urls')),
url(r'^product/(?P<title>[\w-]+)/$', products.views.single,name='single')
]
# app url
from django.urls import path, include
import products
from . import views
urlpatterns = [
path('', views.home, name='home'),
]
#model
class products(models.Model):
title = models.CharField(max_length=120)
desc = models.TextField()
price = models.DecimalField(max_digits=10, decimal_places=2, default=29.99)
sales_price = models.DecimalField(max_digits=10, decimal_places=2, blank=False, null=False, default=0)
slug = models.SlugField(unique=True)
timestamp = models.DateTimeField(auto_now_add=True, auto_now=False)
update = models.DateTimeField(auto_now_add=False, auto_now=True)
active = models.BooleanField(default=True)
def __str__(self):
return self.title
def get_price(self):
return self.price
def get_absolute_url(self):
return reverse("single", kwargs={"title": self.title})
#views
def home(request):
product = products.objects.all()
template = 'home.html'
context = {'product': product}
return render(request, template, context)
def single(request,title):
try:
product = products.objects.get(title=title)
template = 'products.html'
context = {'product': product}
return render(request, template, context)
except:
raise Http404
plz view my code .. i m littlebit confuse in absolute url.. it returns title of the product after clicking some link but it doesnt give me the title if i change produc to other. for eg:http:/127.0.0.1:8000/product/T-shirt/ gives title but wheni hit http:/127.0.0.1:8000/productS/T-shirtgives eroror
It's hard to tell what your actual problem is from the way you've expressed your question, but there are several issues:
Models, unless a single entity represents a plurality of something, must be named in singular. Also, following Python practices, they should be capitalized.
class products(...) should be class Product(...).
Since title is not an unique field, as soon as you have multiple products named "T-shirt", your single view will crash, since .get() refuses to work if more than one object matches the query.
Rethink your URL scheme (to e.g. use that unique slug field you have).
The product/.../ URL should be in products/urls.py, not your project URLs.
Move it there.
Unless you're absolutely sure what you're doing, don't use a bare except:, since it will happily hide any exception. You're looking for except ObjectDoesNotExist:, probably.
You should consider using generic class-based views.

Django 2.0 NoReverseMatch: not a registered namespace

My goal is to Create hyperlinks which would toss a keyword into a views function which would then pull a query from my db onto the page.
GOAL: Press hyperlink which would give me query of a specific major.
I was attemping to use the converter,
So the goal was, 1 being the first step, 3 being final step.
Is this possible?
1) Click the hyperlink -> Major = Accounting
2)URL.py
path(<str:Accounting/, views.Major, name=Major)
3)Views.py
def Major(request, Accounting):
major_choice = professor.objects.filter(Major = Accounting)
return render(request, 'locate/major.html', {'major_choice': major_choice})
NOTE: I replaced variables with what I want it to contain "Accounting", you will notice inside the bottom views.py its called "Major".
Index.html
Accounting
major.html
<ul>
{% for major in major_choice %}
<li>{{major.ProfessorName}}</li>
{%endfor%}
</ul>
urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name='index'),
path('<str:Major/', views.Major, name='Major')
]
models.py
from django.db import models
class professor(models.Model):
ProfessorIDS = models.IntegerField()
ProfessorName = models.CharField(max_length=100)
ProfessorRating = models.DecimalField(decimal_places=2,max_digits=4)
NumberofRatings = models.CharField(max_length=50)
Major = models.CharField(max_length=50)
def __str__(self):
return self.ProfessorName
views.py
from django.http import HttpResponse
from django.shortcuts import render
from .models import professor
def index(request):
professors = professor.objects.all()
return render(request, 'locate/index.html', {'professors': professors})
def Major(request, major):
major_choice = professor.objects.filter(Major = major)
return render(request, 'locate/major.html', {'major_choice': major_choice})
Please update your url path to this:
path('<str:Major>/', views.Major, name='Major')
And in your html:
Accounting
in views:
def Major(request, Major):
....

Django: How to display all the products in a particular category

In my admin page I have 2 apps. One for the Category and the other is for the Products.
In the category I have PS3 and PS4, and in the products..well.. I have the products.
What I want to do is display all of the products for the category. How would I do this? On my html pages, I have a menu bar: Home, PS3 and PS4. When someone clicks on the PS3 or PS4 tab, I want it to display the products for each tab, instead of creating a seperate category page and details page.
In my database I have the following fields for Category: name. In the Products I have the following fields: title, description, image, price, stock.
I have all the pages working, but I just need to display the products. I hope I am clear. I cannot do this. I will show my code..
MODELS.PY..
from django.db import models
# Create your models here.
class Category(models.Model):
name = models.CharField(max_length=30)
class Meta:
ordering = ["name"]
def __str__(self):
return self.name
class Products(models.Model):
category = models.ForeignKey(Category)
title = models.CharField(max_length=128)
description = models.TextField()
stock = models.IntegerField()
price = models.DecimalField(max_digits=6, decimal_places=2)
image = models.ImageField(upload_to="product_images", blank=True)
class Meta:
ordering = ["title", "description", "image", "price", "stock"]
def __str__(self):
return self.title
IN MY VIEWS.PY...
from django.shortcuts import render, render_to_response, RequestContext
from django.http import HttpResponse
from category.models import *
def home(request):
return render_to_response("category/index.html",locals(),context_instance=RequestContext(request))
def ps3(request):
return render_to_response("category/ps3.html",locals(),context_instance=RequestContext(request))
def ps4(request):
return render_to_response("category/ps4.html",locals(),context_instance=RequestContext(request))
IN MY URLS.PY..
from django.conf.urls import patterns, include, url
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
url(r'^$', 'category.views.home', name='home'),
url('^ps3/', 'category.views.ps3', name ='ps3'),
url('^ps4/', 'category.views.ps4', name ='ps4'),
url(r'^admin/', include(admin.site.urls)),
)
The context_instance argument is the important part here, as you can see, it's a RequestContext class, this class takes a request as its first argument, and you can pass any data you want as a dictionary in the second argument:
c = RequestContext(request, {
'foo': 'bar',
})
You need to make use of this, to pass the data you want to use in your templates.
And please, learn to Don’t repeat yourself (DRY), and apply that in your URLs/Views.