How to create individual product page using Django? - python

I'm trying to create an individual page for each of my products. I found a solution online so I did this:
models.py:
#IMPORTS
from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User
from django.urls import reverse
from multiselectfield import MultiSelectField
import uuid
class Product(models.Model):
product_id=models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
product_title=models.CharField(max_length=100)
product_price=models.FloatField(default=1.00)
image_one = models.ImageField(upload_to='media', default='def.jpg')
image_two = models.ImageField(upload_to='media', default='def.jpg')
image_three = models.ImageField(upload_to='media', default='def.jpg')
product_description = models.TextField()
#Toys
class Toy(Product):
CATS = (
("BT", "Boy Toys"),
("GT", "Girl toys"),
("BbyT", "Baby toys")
)
Category=models.CharField(max_length=10, choices=CATS)
views.py:
class ProductList(ListView):
model = Product
def Productdetail(request,pk):
product= Product.objects.get(id=id)
context = {'product': product}
return render(request, 'ecomm/product.html', context)
.
.
.
my urls.py:
from django.urls import path
from . import views
from .views import ProductList, Productdetail
urlpatterns = [
path('', views.home, name='ecomm-home'),
path('products/', ProductList.as_view()),
path('products/<int:pk>/', Productdetail, name='product_detail'),
....
product_detail.html:
{% extends "base.html" %}
{% block content %}
<h2>Product</h2>
{{product.product_title}}
{% endblock %}
girls_toys.html:
{% extends "ecomm/base.html" %}
{% block content %}
<style>
.prod{
text-align:center;
padding-left:50px;
width:500px;
display:block;
float:left;
padding-top:50px;
}
.header{
font-size:40px;
font-family:serif;
}
</style>
<center><h class="header"> Shop girl toys </h></center>
<br>
{% for t in toys %}
{% if t.Category == 'GT' %}
<div class="prod">
<img src="{{t.image_one.url}}" height="200px" width="250px">
<p> {{t.product_title}}</p>
<p> {{t.product_price}} EGP</p>
</div>
{% endif %}
{% endfor %}
{% endblock %}
I get this error:
Reverse for 'product_detail' with arguments '('',)' not found. 1 pattern(s) tried: ['products/(?P<pk>[0-9]+)/$']
I think the issue is with the t.id or the <pk>, I'm not sure how to fix it tho. Any suggestions?

In views.py, product= Product.objects.get(id=pk), you are passing the value pk, so id=pk, not id=id

Related

Reverse for 'topic' with arguments '('',)' not found. 1 pattern(s) tried: ['topic/(?P<name>[^/]+)$']

My question is about redirection again to a /topics/ page where all entries for topic are located. When I end an entry this code and reload tab than showing this error is occured as below:
Reverse for 'topic' with arguments '('',)' not found. 1 pattern(s) tried: ['topic/(?P[^/]+)$']
how can i solved this?
at views.py
from django.shortcuts import render, HttpResponse
from django.views.generic.base import View
from .models import author, catagory, article
# Create your views here.
class HomeView(View):
def get(self, request, *args, **kwargs):
post = article.objects.all()
context = {
"post":post
}
return render (request, 'index.html', context)
def getauthor(request, name):
return render (request, 'profile.html')
def getsingle(request, id):
return render (request, 'single.html')
def getTopic(request, name):
return render (request, 'category.html')
at urls.py
from django.urls import path
from .import views
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
path('', views.HomeView.as_view(), name = 'home'),
#path('about/', views.AboutView.as_view(), name = 'about'),
path('author/<name>', views.getauthor, name = 'author'),
path('article/<int:id>', views.getsingle, name = 'single_post'),
path('topic/<name>/', views.getTopic, name = 'topic'),
]
urlpatterns+= static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
at index.html
{% extends "base.html" %}
{% load static %}
{% block title %} Welcome to my django templates {% endblock %}
{% block content %}
{% for p in post %}
<article class="col-lg-3 col-md-3 col-sm-3 col-xs-6 col-xxs-12 animate-box">
<figure>
<img src="{{ p.image.url }}" alt="Image" class="img-responsive">
</figure>
<span class="fh5co-meta">{{ p.category.name }}</span>
<h2 class="fh5co-article-title">{{ p.title }}</h2>
<span class="fh5co-meta fh5co-date">{{ p.posted_on }}</span>
</article>
{% endfor %}
{% endblock %}
Modles.py are
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class author(models.Model):
name = models.ForeignKey(User, on_delete = models.CASCADE, related_name='blog_posts')
details = models.TextField()
def __str__(self):
return self.name.username
class catagory(models.Model):
name = models.CharField(max_length=100)
def __str__(self):
return self.name
class article(models.Model):
article_author = models.ForeignKey(author, on_delete = models.CASCADE, related_name='blog_posts')
title = models.CharField(max_length=200)
body = models.TextField()
image = models.FileField()
posted_on = models.DateTimeField (auto_now= False, auto_now_add= True)
updated_on = models.DateTimeField (auto_now= True, auto_now_add= False)
catagory = models.ForeignKey(catagory, on_delete = models.CASCADE)
def __str__(self):
return self.title

problem with get_absolute_url django python

I used get_absolute_url in my app but it works only on admin site (by button view on site). On my website, the hyperlink is not responding. I've checked every line of code a couple of times and it seems like everything's fine. Does anyone know why it doesn't works?
models.py
class CrashReport(models.Model):
number_id = models.AutoField(primary_key=True)
date_notice = models.DateField(auto_now=False, auto_now_add=False)
SHIFT_NUMBER = (
('I', 'Zmiana I (6:00 - 14:00)'),
('II', 'Zmiana II (14:00 - 22:00)'),
('III', 'Zmiana III (22:00 - 06:00)'),
)
which_shift = models.CharField(
max_length=3,
choices=SHIFT_NUMBER,
blank=True,
default='I',
help_text='Zmiana.'
)
who_notice = models.ManyToManyField(Author, help_text='Select a occupation for this employee')
description = models.TextField(max_length=1000, help_text='Please type what happened')
which_stuff = models.ManyToManyField(Device, help_text='Select a exactly devices')
PROCESSING_STATUS = (
('o', 'Otwarty'),
('p', 'Przetwarzanie'),
('z', 'Zakonczony'),
)
status_notice = models.CharField(
max_length=1,
choices=PROCESSING_STATUS,
blank=True,
default='o',
help_text='Status dokumentu.'
)
def __str__(self):
return f'ZGL /{self.number_id} / {self.which_stuff.all()} / {self.date_notice}'
def get_absolute_url(self):
return reverse('crashreport-detail', args=[str(self.number_id)])
views.py
from django.shortcuts import render
from django.views import generic
from .models import CrashReport
def index(request):
"""View function for home page of site."""
# Generate counts of some of the main objects
num_crashreports = CrashReport.objects.all().count()
# num_instances = BookInstance.objects.all().count()
# Opens Crashreports (status = 'o')
# num_crashreport_open = CrashReport.objects.filter(status__exact='o').count()
context = {
'num_crashreports': num_crashreports,
# 'num_crashreports_processing': num_crashreports_processing,
# 'num_crashreports_open': num_crashreports_open,
}
# Render the HTML template index.html with the data in the context variable
return render(request, 'dokumenty/index.html', context=context)
class CrashReportsListView(generic.ListView):
model = CrashReport
context_object_name = 'crash_reports_list' # your own name for the list as a template variable
queryset = CrashReport.objects.filter()[:5] # Get 5 crash reports
class CrashReportsDetailView(generic.DetailView):
model = CrashReport
urls.py
from django.urls import path, reverse
from . import views
urlpatterns = [
path('', views.index, name='index'),
path('crashreports/', views.CrashReportsListView.as_view(), name='crashreports'),
path('crashreport/<int:pk>', views.CrashReportsDetailView.as_view(), name='crashreport-detail'),
crashreport_list.html
{% extends 'baza.html' %}
{% block content %}
<h>Witam w Systemie Ewidencji Maria Awaria Service - Raporty</h>
<h1>Zgłoszenia</h1>
{% if crash_reports_list %}
<ul>
{% for crashreports in crash_reports_list %}
<li>
ZGL /{{ crashreports.number_id }} / {{ crashreports.which_stuff.all|join:", " }} / {{crashreports.date_notice}},
</li>
{% endfor %}
</ul>
{% else %}
<p>There are no crash reports in the system.</p>
{% endif %}
{% endblock %}
It should be
....
not href="{{ crashreport.get_absolute_url }}" because you are using crashreports when iterating in for loop:
{% for crashreports in crash_reports_list %}
^^^^^^^^^^^^

How do I get annotate variable in view to display data on django template?

How do I get annotate to display data on django template when I load the pastry_list.html page? I have a variable set to the annotate line in views.py. I have a for loop running through the variable in template. Am I missing something or doing something wrong? For some reason it seems that the template is not recognizing the views.py variable. Thanks.
from django.db import models
from django.utils import timezone
from django.urls import reverse
from collections import OrderedDict
class IntegerRangeField(models.IntegerField):
def __init__(self, verbose_name=None, name=None, min_value=None,
max_value=None, **kwargs):
self.min_value, self.max_value = min_value, max_value
models.IntegerField.__init__(self, verbose_name, name, **kwargs)
def formfield(self, **kwargs):
defaults = {'min_value': self.min_value,
'max_value':self.max_value}
defaults.update(kwargs)
return super(IntegerRangeField, self).formfield(**defaults)
class Pastry(models.Model):
CHOICES_DICT = OrderedDict((
("Muffin", "Muffin"),
("Cupcake", "Cupcake"),
("Brownie", "Brownie"),
("Cake", "Cake"),
("Fruit Tart", "Fruit Tart")
))
pastry = models.CharField(max_length=20, default="muffin",
choices=CHOICES_DICT.items())
vote = IntegerRangeField(default=1, min_value=1, max_value=1)
def get_absolute_url(self):
return reverse("pastry_detail", kwargs={'pk': self.pk})
def __str__(self):
return self.pastry
VIEWS.PY
from django.shortcuts import render
from django.views.generic import (TemplateView,ListView,
DetailView,CreateView,
UpdateView,DeleteView)
from django.urls import reverse_lazy
from myapp.models import Pastry
from myapp.forms import PastryForm
from django.db.models import F
ps = Pastry.objects.values('pastry').annotate(total=Count('pastry'))
class PollsListView(ListView):
model = Pastry
def get_queryset(self):
return Pastry.objects.all()
class PollsDetailView(DetailView):
model = Pastry
class PollsCreateView(CreateView):
success_url = reverse_lazy('pastry_list')
form_class = PastryForm
model = Pastry
class PollsUpdateView(UpdateView):
success_url = reverse_lazy('pastry_list')
form_class = PastryForm
model = Pastry
class PollsDeleteView(DeleteView):
model = Pastry
success_url = reverse_lazy('pastry_list')
pastry_list.html (template)
{% extends "base.html" %}
{% block content %}
<div class="jumbotron">
New Poll
<h1>Voting for the favorite pastry</h1>
{% for p in ps %}
{% for k, v in p.items %}
{{v}}
{% endfor %}
{% endfor %}
{% for pastry in pastry_list %}
<div class="pastry">
<h3><a href="{% url 'pastry_detail' pk=pastry.pk %}">
{{ pastry.pastry }}</a></h3>
</div>
{% endfor %}
</div>
{% endblock %}
FORMS.PY
from django import forms
from myapp.models import Pastry
from django.forms import ModelForm
class PastryForm(ModelForm):
class Meta():
model = Pastry
fields = ['pastry', 'vote']
PASTRY_FORM.HTML
{% extends "base.html" %}
{% load widget_tweaks %}
{% block content %}
<div class="jumbotron">
<h1>New Poll</h1>
<form class="post-form" method="POST">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="save btn btn-default">Save</button>
</form>
</div>
{% endblock %}
</body>
</html>

How do you display a views.py's variable linked to annotated queryset in a django template?

How do you display a views.py's variable linked to annotated queryset in a django template? I know the annotated queryset returns correct data when I printed it out, but somehow the template for loop is not retrieving the data on the html page. Can someone please advise me on how to fix this issue? Thanks.
VIEWS.PY
from django.shortcuts import render
from django.views.generic import (TemplateView,ListView,
DetailView,CreateView,
UpdateView,DeleteView)
from django.urls import reverse_lazy
from myapp.models import Pastry
from myapp.forms import PastryForm
from django.db.models import F
This line ps = Pastry.objects.values('pastry').annotate(total=Count('pastry')) returns correct data:
{'pastry': 'Brownie', 'total': 1}
{'pastry': 'Cake', 'total': 1}
{'pastry': 'Cupcake', 'total': 1}
{'pastry': 'Fruit Tart', 'total': 1}
{'pastry': 'Muffin', 'total': 2}
class PollsListView(ListView):
model = Pastry
def get_queryset(self):
return Pastry.objects.all()
class PollsDetailView(DetailView):
model = Pastry
class PollsCreateView(CreateView):
success_url = reverse_lazy('pastry_list')
form_class = PastryForm
model = Pastry
class PollsUpdateView(UpdateView):
success_url = reverse_lazy('pastry_list')
form_class = PastryForm
model = Pastry
class PollsDeleteView(DeleteView):
model = Pastry
success_url = reverse_lazy('pastry_list')
pastry_list.html (template)
{% extends "base.html" %}
{% block content %}
<div class="jumbotron">
New Poll
<h1>Voting for the favorite pastry</h1>
Somehow this code here is not displaying any data.
{% for p in ps %}
{% for k, v in p.items %}
{{k}}{{v}}
{% endfor %}
{% endfor %}
{% for pastry in pastry_list %}
<div class="pastry">
<h3><a href="{% url 'pastry_detail' pk=pastry.pk %}">
{{ pastry.pastry }}</a></h3>
</div>
{% endfor %}
</div>
{% endblock %}
More info can be found in the Documentation
Basically, you can send more variables to template via get_context_data() method
Sample:
class PollsListView(ListView):
model = Pastry
def get_queryset(self):
return Pastry.objects.all()
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['ps'] = = Pastry.objects.values('pastry').annotate(total=Count('pastry'))
return context
With get_context-data(), your variable ps is available in the template pastry_list.html

post_detail() view missing required positional arguments:

I'm beginner to django . I am facing this problem that I can't get the post detail view with year , month and post .
Error is post_detail() missing 4 required positional arguments: 'year', 'month', 'day', and 'post'.
this is models.py
from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User
from django.core.urlresolvers import reverse
class Post(models.Model):
STAUTS_CHOICE = ( ('draft','Draft'),('published','Published'),)
title =models.CharField(max_length =250)
slug = models.SlugField(max_length =250)
author = models.ForeignKey(User,related_name='blog_post')
body = models.TextField()
publish =models.DateTimeField(default = timezone.now)
created = models.DateTimeField(auto_now_add=True)
udated = models.DateTimeField(auto_now=True)
status = models.CharField(max_length =250 ,
choices = STAUTS_CHOICE , default = 'draft')
class Meta:
ordering = ('-publish',)
def get_absolute_url(self):
return reverse('blog:post_detail', args = [self.slug, self.publish.year , self.publish.strftime('%m'), self.publish.strftime('%d')]])
def __str__(self):
return self.title
______________________________________________________________
this is views.py
from django.shortcuts import render , get_object_or_404
from .models import Post
def post_list(request):
post = Post.objects.all()
return render(request,'blog/post/list.html',{'post':post})
def post_detail(request,slug,year, month,day,post):
post = get_object_or_404(Post, slug = slug , status = 'published' ,publish_year = year, publish_month = month , publish_day = day)
return render(request,'blog/post/detail.html',{'post':post})
this is urls.py
from django.conf.urls import url
from .import views
urlpatterns = [
url(r'^post_list',views.post_list,name ='post_list'),
url(r'^(?P<year>\d{4})/(?P<month>\d{2})/(?P<day>\d{2})/'r'(?P<slug>[-\w]+)/$',views.post_detail,name='post_detail'),
this is post_detail.html page
{% extends 'blog/base.html' %}
{% block title %}Post details{% endblock %}
{% block content %}
<h2><a>{{post.title}}</a></h2>
<p class="date">published {{ post.published}} by {{ post.author}}</p>
{{ post.body|linebreaks }}
{% endblock %}
this is list.html page :
{% extends 'blog/base.html' %} {% block head_title %}Posts list{% endblock %}
{% block content %}
<h1>My Blog</h1>
{% for x in posts %}
<h2>
{{x.title}}
</h2>
<p class="date">published {{ x.published}} by {{ x.author}}</p>
{{ x.body|truncatewords:30|linebreaks }} {% endfor %} {% endblock %}
this is base.html
{% load staticfiles %}
<!DOCTYPE html>
<head>
<title>{% block head_title %}Welcome to my blog{% endblock %}</title>
<!-- <link rel="stylesheet" href=""> -->
</head>
<body>
<div id="sidebar">
<h1></h1>
</div>
<div id="content">
{% block content %} {% endblock %}</div>
</body>
</html>
So far I guessed you want to resolve domain/year/month/day/slug URL.
The following changes will make it work.
views.py
def post_detail(request,slug,year, month,day):
post = get_object_or_404(Post, slug = slug , status = 'published' ,publish__year = year, publish__month = month , publish__day = day)
return render(request,'blog/post/detail.html',{'post':post})
urls.py
urlpatterns = [
url(r'^post_list',views.post_list,name ='post_list'),
url(r'^(?P<year>\d{4})/(?P<month>\d{2})/(?P<day>\d{2})/(?P<slug>[-\w]+)/$',views.post_detail,name='post_detail'),
]
remove post parameter from post_detail view. and remove third url for same view. Now your requested url should be:
localhost:8000/2017/12/16/my-post

Categories