I have a table on my webpage that I want to iterate product information into and it worked up until I tried adding a paginator. The server runs fine and the rest of the website is functional.
Here are my files:
shop/products.html
{% extends 'base.html' %}
{% block content %}
<h1>On sale here</h1>
<div class="col-sm-3">
<h4>Categories</h4>
<ul class="list-group">
All Categories
{% for c in countcat %}
<a href="{{ c.get_absolute_url }}" class="list-group-item catheight">{{c.name}}
<span class="badge">{{c.num_products}}</span>
</a>
{% endfor %}
</ul>
</div>
<div class="col-sm-9">
<h4>Note that all products are second hand, unless otherwise stated.</h4>
<form class="form-inline my-2 my-lg-0" action="{% url 'search_result' %}" method="get">
{% csrf_token %}
<input class="form-control mr-sm-2" type="search" placeholder="Search" aria-label="Search" name="q">
<button class="glyphicon glyphicon-search h-100" type="submit"></button>
</form>
<table class="table table-bordered table-hover table-condensed">
<thead>
<!-- The header row-->
<tr>
<th>ID</th>
<th>Name</th>
<th>Image</th>
<th>Category</th>
<th>Description</th>
<th>Stock</th>
<th>Price</th>
<th>Buy</th>
</tr>
</thead>
<tbody>
<!-- Product row(s) -->
{% for product in products %}
<tr>
<td>{{product.id}}</td>
<td>{{product.name}}</td>
{% if product.image %}
<td><img src="{{product.image.url}}"></td>
{% endif %}
<td>{{product.category}}</td>
<td>{{product.description}}</td>
<td>{{product.stock}}</td>
<td>€{{product.price}}</td>
{% if product.stock > 0 %}
<td><a href="{% url 'add_cart' product.id %}" class="btn btn-default btn-xs"><span
class="glyphicon glyphicon-shopping-cart"></span></a></td>
{% else %}
<td><a href="" class="btn btn-default btn-xs"><span
class="glyphicon glyphicon-warning-sign red"></span></a></td>
{% endif %}
</tr>
{% endfor %}
</tbody>
</table>
<hr>
<div class="text-center">
{% for pg in products.paginator.page_range %}
<a href="?page={{pg}}" class="btn btn-light btn-sm
{% if products.number == pg %}
active
{% endif %}">{{pg}}</a>
{% endfor %}
</div>
</div>
{% endblock content %}
shop/models.py
from django.db import models
from django.urls import reverse
class Category(models.Model):
name = models.TextField()
products = models.ManyToManyField('Product')
def get_products(self):
return Product.objects.filter(category=self)
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('product_list_by_category',args=[self.id])
class Product(models.Model):
name = models.TextField()
description = models.TextField()
stock = models.IntegerField()
price = models.DecimalField(max_digits=10,decimal_places=2)
image = models.ImageField(upload_to='images/', blank=True)
def __str__(self):
return self.name
shop/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.product_list,
name='products'),
path('<int:category_id>/', views.product_list,
name='product_list_by_category'),
]
shop/views.py
from django.shortcuts import render, get_object_or_404, redirect
from .models import Category, Product
from django.db.models import Count
from django.contrib.auth.models import Group, User
from .forms import SignUpForm
from django.contrib.auth.forms import AuthenticationForm
from django.contrib.auth import login, authenticate, logout
from django.core.paginator import Paginator, EmptyPage, InvalidPage
def product_list(request, category_id=None):
category = None
products = Product.objects.all()
ccat = Category.objects.annotate(num_products=Count('products'))
if category_id :
category = get_object_or_404(Category, id=category_id)
products = products.filter(category=category)
paginator = Paginator('products', 3)
try:
page = int(request.GET.get('page', 1))
except:
page = 1
try:
products = paginator.page(page)
except(EmptyPage, InvalidPage):
products = paginator.page(paginator.num_pages)
return render(request, 'products.html',
{'products': products,
'countcat':ccat})
def signupView(request):
if request.method == 'POST':
form = SignUpForm(request.POST)
if form.is_valid():
form.save()
username = form.cleaned_data.get("username")
signup_user = User.objects.get(username=username)
customer_group = Group.objects.get(name= 'Customer')
customer_group.user_set.add(signup_user)
else:
form = SignUpForm()
return render(request, 'accounts/signup.html', {'form':form})
def signinView(request):
if request.method == 'POST':
form = AuthenticationForm(data=request.POST)
if form.is_valid():
username = request.POST['username']
password = request.POST['password']
user = authenticate(username=username, password=password)
if user is not None:
login(request, user)
return redirect('products')
else:
return redirect('signup')
else:
form = AuthenticationForm()
return render(request, 'accounts/signin.html', {'form':form})
def signoutView(request):
logout(request)
return redirect('signin')
I'm sort of a django noob so any help would be greatly appreciated, thanks :)
You are passing a string to Paginator here:
paginator = Paginator('products', 3)
You should pass an object_list:
paginator = Paginator(products, 3)
Related
I need some fresh eyes, what am I missing here? In my Post Model imageField is defined as "picture" to be uploaded on the site, I seed it on my admin panel, it gets uploaded just fine but I can't seem to make it appear on the page: http://127.0.0.1:8000/posts/. I get ValueError at /posts/
The 'picture' attribute has no file associated with it. Highlited line is line 257, in post_comment_create_view
return render(request, 'network/posts.html', context)
Model:
class Post(models.Model):
# id is created automatically by Django
picture = models.ImageField(upload_to='images', blank=True, validators=[FileExtensionValidator(['png', 'jpg', 'jpeg'])])
content = models.TextField()
liked = models.ManyToManyField(Profile, blank=True, related_name="likes")
author = models.ForeignKey(Profile, on_delete=models.CASCADE, null=True)
updated = models.DateTimeField(auto_now=True)
created = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ('-created',)
def __str__ (self):
return str(self.content[:20])
Forms:
class PostModelForm(forms.ModelForm):
content = forms.CharField(widget=forms.Textarea(attrs={'rows':2}))
class Meta:
model = Post
fields = ('content', 'picture')
Views:
#login_required
def post_comment_create_view(request):
qs = Post.objects.all()
profile = Profile.objects.get(user=request.user)
#Setting up pagination
p = Paginator(qs, 5)
page = request.GET.get('page')
post_list = p.get_page(page)
#Post form, comment form
p_form = PostModelForm()
c_form = CommentModelForm()
post_added = False
profile = Profile.objects.get(user=request.user)
if 'submit_pForm' in request.POST:
print(request.POST)
p_form = PostModelForm(request.POST, request.FILES)
if p_form.is_valid():
instance = p_form.save(commit=False)
instance.author = profile
instance.save()
p_form = PostModelForm()
post_added = True
if 'submit_cForm' in request.POST:
c_form = CommentModelForm(request.POST)
if c_form.is_valid():
instance = c_form.save(commit=False)
instance.user = profile
instance.post = Post.objects.get(id=request.POST.get('post_id'))
instance.save()
c_form = CommentModelForm()
context = {
'qs': qs,
'profile': profile,
'p_form': p_form,
'c_form': c_form,
'post_added': post_added,
'post_list': post_list,
}
return render(request, 'network/posts.html', context)
HTML:
{% block body %}
<div>
<div class="border border-light rounded" style="width: 25rem;">
{% if post_added %}
<div id="alertFade" class="alert alert-success" role="alert">Post added!</div>
{% endif %}
<form action="" method="POST" enctype="multipart/form-data" class="form-group">
{% csrf_token %}
{{p_form}}
<button type="submit" class="btn btn-sm btn-success" name="submit_pForm">Send Post</button>
</form>
</div>
{% for obj in post_list %}
<div class="card center" style="width: 30rem;">
<div class="card-head" style="background-color: #d0e2bc;">
<img width="50px" class="avatar img-thumbnail rounded-circle z-depth-2 ml-1" src={{obj.author.avatar.url}}> {{ obj.author.user }} - {{ obj.created|naturaltime }}
{% if request.user == obj.author.user %}
<button class="btn btn-sm btn-success float-right mt-2 mr-1">Delete</button>
<button class="btn btn-sm btn-success float-right mr-1 mt-2">Edit</button>
{% endif %}
</div>
<div class="card-body">
<img src={{obj.picture.url}}> <br>
<p class="card-text">{{obj.content|safe}}</p>
<hr>
</div>
<button class="cmt_btn ui button mb-5">show / hide comments</button>
<div class="comment-box">
{% if obj.comment_set.all %}
{% for c in obj.comment_set.all %}
<img width="20px" class="avatar img-thumbnail rounded-circle"src={{c.user.avatar.url}} alt="">
<span>{{ c.user }}</span>
<div class="mt-2">{{ c.body }}</div>
{% endfor %}
{% endif %}
There should be quotes around the src:
<img src={{obj.picture.url}}> <!-- will not work -->
Should be:
<img src="{{obj.picture.url}}"> <!-- works -->
This is for the tag attributes. For content within the tag, what you have is fine, no quotes. This is good:
<span>{{ c.user }}</span> <!-- works -->
I solved it, the solution is that I had to check if the img exists:
{% if obj.picture %}
<img src="{{obj.picture.url}}"> <br/>
{% endif %}
Hi I have created a address model and link that model to the forms and created the view. but that form does save any data but that data does not show to me. Although it show me that data in the terminal .
this is my address model:
from django.db import models
from billing.models import BillingProfile
# Create your models here.
ADDRESS_TYPES = (
('billing' , 'Billing'),
('shipping' , 'Shipping'),
)
class Address(models.Model):
billing_profile = models.ForeignKey(BillingProfile , on_delete=models.CASCADE)
addresss_type = models.CharField(max_length=120 , choices=ADDRESS_TYPES)
address_line_1 = models.CharField(max_length=120)
address_line_2 = models.CharField(max_length=120 , null=True , blank= True)
city = models.CharField(max_length=120)
country = models.CharField(max_length=120 ,default='Pakistan')
postal_code = models.CharField(max_length=120)
def __str__(self):
return str(self.billing_profile)
since I connect address model with billingprofile so the billing model is:
class BillingProfile(models.Model):
user = models.OneToOneField(User ,null=True , blank=True , on_delete=models.CASCADE)
email = models.EmailField()
active =models.BooleanField(default=True)
update = models.DateTimeField(auto_now=True)
time_stamp = models.DateTimeField(auto_now_add=True)
objects = BillingProfileManager()
def __str__(self):
return self.email
and I call my address model into form
forms.py/address
from django import forms
from .models import Address
class AddressForm(forms.ModelForm):
class Meta:
model = Address
fields = ['address_line_1','address_line_2','city','country','postal_code']
and my address/views.py is:
from django.shortcuts import render , redirect
from django.utils.http import is_safe_url
# Create your views here.
from billing.models import BillingProfile
from .forms import AddressForm
def checkout_address_create_view(request):
form = AddressForm(request.POST or None)
context = {
'form':form
}
next_ = request.GET.get('next')
next_post = request.POST.get('next')
redirect_path = next_ or next_post or None
if form.is_valid():
print(request.POST)
instance = form.save(commit=False)
billing_profile , billing_profile_created = BillingProfile.objects.new_or_get(request)
if billing_profile is not None:
instance.billing_profile = billing_profile
instance.address_type = request.POST.get('address_type','shipping')
instance.save()
else:
print("Error Here")
return redirect("cart:checkout")
if is_safe_url(redirect_path , request.get_host()):
return redirect(redirect_path)
else:
return redirect("cart:checkout")
return redirect("cart:checkout")
and my address/form.html is:
now my form.html is:
<form method="POST" action="{% if action_url%}{{ action_url }} {% else %}{% url 'login' %}{% endif %}">
{% csrf_token %}
{% if next_url %}
<input type="hidden" name="next" value="{{ next_url }}"/>
{% endif %}
{% if address_type %}
<input type="hidden" name="address_type" value="{{ address_type }}"/>
{% endif %}
{{form.as_p}}
<button type="submit" class="btn btn-secondary">Submit</button>
</form>
and this form is shown on cart home so the cart view is:
def checkout_home(request):
cart_obj , cart_created = Cart.objects.new_or_get(request)
order_obj = None
if cart_created or cart_obj.products.count() ==0:
return redirect("cart:home")
login_form = LoginForm()
guest_form = GuestForm()
address_form =AddressForm()
billing_address_form = AddressForm()
billing_profile, billing_profile_created = BillingProfile.objects.new_or_get(request)
if billing_profile is not None:
order_obj , order_obj_created = Order.objects.new_or_get(billing_profile , cart_obj)
context= {
"object" : order_obj,
"billing_profile" : billing_profile,
"login_form" : login_form,
"guest_form" :guest_form,
"address_form" :address_form,
"billing_address_form" : billing_address_form,
}
return render(request , "carts/checkout.html" , context)
and my checkout html is:
{% extends 'base.html' %}
{% block content %}
{{object.order_id}} -- {{object.cart}}
{% if not billing_profile %}
<div class="row text-center">
<div class="col-12 col-md-6">
<p class="lead">Login</p>
{% include 'accounts/snippets/form.html' with form=login_form next_url=request.build_absolute_uri %}
</div>
<div class="col-12 col-md-6">
<p class="lead">Continue as guest</p>
{% url "guest_register" as guest_register_url %}
{% include 'accounts/snippets/form.html' with form=guest_form next_url=request.build_absolute_uri action_url=guest_register_url %}
</div>
</div>
{% else %}
{% if not object.shipping_address %}
<div class="row">
<div class="col-md-6 mx-auto col-10">
<p class="lead">Shipping Address</p>
{% url "checkout_address_create" as checkout_address_create %}
{% include 'addresses/form.html' with form=address_form next_url=request.build_absolute_uri action_url=checkout_address_create address_type='shipping' %}
</div>
</div>
{% elif not object.billing_address%}
<div class="row">
<div class="col-md-6 mx-auto col-10">
<p class="lead">Billing Address</p>
{% url "checkout_address_create" as checkout_address_create %}
{% include 'addresses/form.html' with form=address_form next_url=request.build_absolute_uri action_url=checkout_address_create address_type='billing' %}
</div>
</div>
{% else %}
<h1>Finalize Checkout</h1>
<p>Cart_total:{{object.cart.total}}</p>
<p>Shipping Total:{{object.shipping_total}}</p>
<p>Order Total:{{object.total}}</p>
<button>Checkout</button>
{% endif %}
{% endif %}
{% endblock %}
I've created a django subscription form. I want to show a 'Thank You' message below the form after submitting but if I submit the form, email field is still showing the value. I've tried HttpResponseRedirect('/') but doing so doesn't show 'Thank You' message.
#Views.py
global categories
categories = ['Development','Technology','Science','Lifestyle','Other']
class IndexView(TemplateView):
model = Post
template_name = 'blog/index.html'
def post(self,request,*args,**kwargs):
context = self.get_context_data()
if request.method == 'POST':
form = SubscriberForm(request.POST)
if context["form"].is_valid():
context["email"] = request.POST.get('email')
form.save()
form = SubscriberForm()
return render(request, 'blog/index.html', context=context)
else:
form = SubscriberForm()
def get_context_data(self, **kwargs):
# Call the base implementation first to get a context
context = super(IndexView,self).get_context_data(**kwargs)
# Add in a QuerySet of all the books
context['post_list'] = Post.objects.all()
context["categories"] = categories
form = SubscriberForm(self.request.POST or None) # instance= None
context["form"] = form
return context
#sidebar.html
<div class="subscribe">
<form class="" action="" method="post">
{% csrf_token %}
{{ form.as_p }}
<button id="subscribe-button" type="submit" name="button"><i class="fa fa-paper-plane" aria-hidden="true"></i></button>
</form>
{% if email %}
<h6>Thank you for Subscribing!</h6>
{% endif %}
<!-- <i class="fa fa-paper-plane" aria-hidden="true"></i> -->
</div>
#models.py
class Subscribe(models.Model):
email = models.EmailField()
subscribed_on = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ('-subscribed_on',)
def __str__(self):
return 'Subscribed by {} on {}'.format(self.email, self.subscribed_on)
#forms.py
class Subscribe(models.Model):
email = models.EmailField()
subscribed_on = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ('-subscribed_on',)
def __str__(self):
return 'Subscribed by {} on {}'.format(self.email, self.subscribed_on)
Instead of rendering the template you can redirect() after saving the form.
And to render the success message you can use the django messaging framework.
def post(self,request,*args,**kwargs):
context = self.get_context_data()
if request.method == 'POST':
form = SubscriberForm(request.POST)
if context["form"].is_valid():
context["email"] = request.POST.get('email')
form.save()
messages.success(request, 'Thank you for subscribing')
return redirect('/')
else:
form = SubscriberForm()
return render(request, 'blog/index.html', context=context)
Now in the template you can render the messages like this.
<div class="subscribe">
<form class="" action="" method="post">
{% csrf_token %}
{{ form.as_p }}
<button id="subscribe-button" type="submit" name="button"><i class="fa fa-paper-plane" aria-hidden="true"></i></button>
</form>
{% if messages %}
<ul class="messages">
{% for message in messages %}
<li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
<!-- <i class="fa fa-paper-plane" aria-hidden="true"></i> -->
</div>
So sorry probably this is very easy but i learn django and have a problem. My navbar working on index page is perfectly. but when i go contact form or another post url, navbar links disappear.
When i go some post page or my contact form page
1- {{ article.title }} and href links are disappear
Can i ask help ?
my navbar.html
{% load i18n %}
<!-- Menu -->
<div class="menu-wrapper center-relative">
<nav id="header-main-menu">
<div class="mob-menu">Menu</div>
<ul class="main-menu sm sm-clean">
<li>{% trans "HomePage" %}</li>
<li>{% trans "Services" %}</li>
<li>
{% for article in articles %}
{% if article.slug == 'about_us' %}
<a href="{% url 'article:detail' slug=article.slug %}">
{{ article.title }}</a>
{% endif %}
{% endfor %}
</li>
<li>{% trans "HELLO WORLD" %}</li>
<li class="menu-item menu-item-type-post_type menu-item-object-page menu-item-has-children menu-item-1643 dropdown">
<a title="" href="">{% trans "Producs" %}</a>
<ul role="menu" class=" dropdown-menu">
<li class="menu-item menu-item-type-post_type menu-item-object-page menu-item-has-children menu-item-1644 dropdown">
<a title="Level 2" href="">{% trans "Consult" %}</a>
<ul role="menu" class=" dropdown-menu">
<li >
{% for category in category %}
{% if category.name == 'consult' %}
{% for article in category.get_article %}
<a title="{{ article.title }}" href="{% url 'article:detail' slug=article.slug %}"> <p> {{ article.title }}</p></a>
{% endfor %}
{% endif %}
{% endfor %}</li>
</ul>
</li>
<li>
{% for category in category %}
{% if category.name == 'header' %}
{% for article in category.get_article %}
<a title="{{ article.title }}" href="{% url 'article:detail' slug=article.slug %}"> <p> {{ article.title }}</p></a>
{% endfor %}
{% endif %}
{% endfor %}
</li>
</ul>
</li>
<li>{% trans "İletişim" %}</li>
</ul>
</nav>
</div>
article/views.py
from django.shortcuts import render, get_object_or_404
from .models import Article, Category
from django.core.paginator import Paginator
from django.utils.translation import gettext as _
# Create your views here.
def articles(request):
keyword = request.GET.get("keyword")
if keyword:
articles = Article.objects.filter(title__contains=keyword)
paginator = Paginator(articles, 1)
page = request.GET.get('page')
articles = paginator.get_page(page)
return render(request,"articles.html",{"articles":articles})
articles = Article.objects.all()
paginator = Paginator(articles, 10)
page = request.GET.get('page')
articles = paginator.get_page(page)
return render(request, "articles.html", {"articles":articles})
def index(request):
articles = Article.objects.all()
category = Category.objects.all()
context = {
"articles": articles,
"category": category,
}
return render(request, 'index.html', context)
def detail(request,slug):
# article = Article.objects.filter (id = id).first()
article = get_object_or_404(Article, slug = slug)
category = Category.objects.all()
return render(request, "detail.html", {"article":article, "category":category,})
def category_detail(request,slug):
template = "category_detail.html"
category=get_object_or_404(Category,slug=slug)
article=Article.objects.filter(category=category)
context = {
'category' : category,
'article' : article,
}
return render(request,template,context)
def category_page(request):
object_list = Category.objects.all()
context = {'object_list': object_list,}
return render(request, 'detail.html', context)
contact_form/views.py
from django.views.generic.edit import FormView
from .forms import ContactForm
try:
from django.urls import reverse
except ImportError: # pragma: no cover
from django.core.urlresolvers import reverse # pragma: no cover
class ContactFormView(FormView):
form_class = ContactForm
recipient_list = None
template_name = 'contact_form/contact_form.html'
def form_valid(self, form):
form.save()
return super(ContactFormView, self).form_valid(form)
def get_form_kwargs(self):
if self.recipient_list is not None:
kwargs.update({'recipient_list': self.recipient_list})
return kwargs
def get_success_url(self):
return reverse('contact_form_sent')
I'm creating a page where my users can edit their articles but there is one problem, my form is not saving the modifications when I submit my form. Let's have a look:
views.py
def edit(request, id=None, template_name='article_edit.html'):
if id:
article = get_object_or_404(Article, id=id)
if article.user != request.user:
return HttpResponseForbidden()
else:
article = Article(user=request.user)
if request.POST:
form = ArticleForm(request.POST, instance=article)
if form.is_valid():
save_it = form.save()
save_it.save()
form.save_m2m()
return HttpResponseRedirect("/")
else:
form = ArticleForm(instance=article)
context = {'form': form}
populateContext(request, context)
return render(request, template_name, context)
line 3 to 8 : Is to check if it's your own articles there is no problem with that.
line 10 to 18 : There is a problem between these lines, my form is not saving when I submit my form
forms.py (ModelForm)
class ArticleForm(forms.ModelForm):
class Meta:
model = Article
exclude = ['date', 'rating', 'user']
form = ArticleForm()
(Line 4 : I'm excluding the date, the ratings and the username when saved so that the user can not change these informations.)
I don't have any problem in my template.html and the urls.py don't bother with that I checked over 10 times :)
Any help would be great, I'm blocked on this problem since over 1 month...
******* EDIT *******
Models.py
class Article(models.Model):
user = models.ForeignKey(User)
titre = models.CharField(max_length=100, unique=True)
summary = RichTextField(null=True, max_length=140)
contenu = RichTextField(null=True)
date = models.DateTimeField(auto_now_add=True, auto_now=False, verbose_name="Date de parution")
image = models.ImageField(upload_to='article', default='article/amazarashi.jpeg')
rating = RatingField(can_change_vote=True)
tags = TaggableManager(through=TaggedItem, blank=True)
def __str__(self):
return self.titre
Template.html
{% block body %}
{% if user.is_authenticated %}
<p>Authentificated as <strong>{{ user.username }}</strong></p>
{% else %}
<p>NOT Authentificated</p>
{% endif %}
<h1>Edit this {{ article.titre }}</h1>
<br>
<div class="col-xs-12 col-sm-8 col-md-8 col-lg-8">
<form enctype='multipart/form-data' action="{% url "article.views.index" %}" method="post" class="form" autocomplete="off" autocorrect="off">
{% csrf_token %}
<div class="form-group">TITRE
{{ form.titre.errors }}
{{ form.titre }}
</div>
<div class="form-group">SUMMARY
{{ form.media }}
{{ form.summary.errors }}
{{ form.summary }}
</div>
<div class="form-group">CONTENU
{{ form.media }}
{{ form.contenu.errors }}
{{ form.contenu }}
</div>
<div class="form-group">
{{ form.image.errors }}
{{ form.image }}
</div>
<div class="form-group">TAGS
{{ form.tags.errors }}
{{ form.tags }}
</div>
<input type="submit" class="btn btn-default" value="Submit"/>
</div>
</form>
{% endblock %}
According to your error message.. Modify your form in templates:
<form enctype='multipart/form-data' ...>
Add request.FILES to your Form creation:
if request.POST:
form = ArticleForm(request.POST, request.FILES, instance=article)
UPDATE:
You have strange url tag parameter. Are you sure you have defined your url like: ('...', your_view, name='article.views.index')? I am in doubt cause url tag takes url name as parameter but not view path and nobody usually uses url names like this.