little bit confuse in dgetting absolute url in django - 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.

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.

When I change the language of the website, the slug is not translated causing a 404 error

I'm new programming with Django. I'm currently using version 2.2 for my first project.
So far it's going well, my website consists of a landing page with a product catalog which has to work in two languages: English and Spanish.
My problem is that when I try to change a URL from English to Spanish or from Spanish to English, I get a 404 error because the product slug does not get translated.
Let me explain.
For a product, I have a URL structure in English:
mywebsite.com/products_en/item-name_en
In Spanish, it would be:
mywebsite.com/products_es/item-name_es
Both links work well, as long as the corresponding language is active. The problem is that, for example, if I am on the English product page and try to switch to the Spanish page, it tries to take me to mywebsite.com/products_es/item-name_en
I know this question has been already asked here on Stack Overflow but the answers didn't get me to the solution
How can I avoid this? Thank you in advance.
Here's my urls.py
from django.contrib import admin
from django.urls import include, path
urlpatterns = [
path('i18n/', include('django.conf.urls.i18n')),
path('',include('landing_page.urls')),
path('',include('products_catalog.urls')),
]
My products_catalog urls.py
from django.urls import include, path
from django.conf import settings
from django.conf.urls import url
from django.conf.urls.static import static
from django.utils.translation import gettext_lazy as _
from . import views
app_name = 'catalog'
urlpatterns = [
path(_('products'), views.products, name='products'),
path(_('products/<slug:product_slug>'), views.product_detail, name='product-detail'),
]+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
My products_catalog views.py
from django.shortcuts import get_object_or_404, render
from django.http import Http404
from .models import *
def products(request):
products_list = product.objects.all()
return render(request, 'products_catalog/products.html', {'products': products_list,})
def product_detail(request, product_slug):
product = get_object_or_404(product, slug=product_slug)
return render(request, 'products_catalog/product.html', {'product': product,} )
My product_catalog models.py
class product(models.Model):
name = models.CharField(_("Name"),max_length=100, unique=True)
description = models.TextField(_("Description"), max_length=2000)
features = models.TextField(_("Features"), max_length=10000, null=True, blank=True)
slug = models.SlugField("Slug", null=True, blank=True)
def save(self, *args, **kwargs):
if not self.id:
self.slug_es = slugify(self.name_es)
self.slug = slugify(self.name)
super(product, self).save(*args, **kwargs)
def __str__(self):
return self.name
class Meta:
verbose_name = _("Product")
verbose_name_plural = _("Products")
slug_es was automatically generated because I use django-modeltranslation
OK, #Lau, I think this article will help you to solve your issue:
Django modeltranslation slug problem. When i change language dont go right url
I also think the slug should be static and not translated as pointed out in a comment in above link.

'CategoryDetail' object has no attribute '_state'

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 %}

In Django app models, how to get the url prefix

I am writing a Django blog app named blogengine
in the root urls.py:
url(r'^blog/', include('blogengine.urls')),
In my blogengine/models.py
class Post(models.Model):
title = models.CharField(max_length=200)
pub_date = models.DateTimeField()
text = models.TextField()
def get_absolute_url(self):
return "/blog/post/%s/" % self.id
Here I defined a function get_absolute_url with a hard coding /blog/ prefix.
How could I prevent this hard code and using some way to get the prefix in ROOT_URLCONF
You can use reverse resolution of named url. Here is the link to the detail https://docs.djangoproject.com/en/1.8/topics/http/urls/#reverse-resolution-of-urls
Here is the example.
url(r'^post/(?P<id>\d+)/$', post_view, name='post_detail'),
This is the model.
from django.core
from django.core.urlresolvers import reverse
class Post(models.Model):
title = models.CharField(max_length=200)
pub_date = models.DateTimeField()
text = models.TextField()
def get_absolute_url(self):
return reverse('post_detail', kwargs={'id': self.id})
No, this is absolutely not the way to do it. Your model should not care at all about the prefix.
Instead you should use the provided reverse function to calculate the URL, whatever the prefix:
def get_absolute_url(self):
return reverse('blog-post', kwargs={'id': self.id})
get_absolute_url() is not necessary:
url(r'^blog/$', views.post_list, name='post_list'),
url(r'^blog/(?P<post_id>[\w+-]*)/$', views.post_detail, name='post_detail')

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.