I try to create a link between lista_libri.html and lista_generi.html, using get_absolute_url. I've create already a link between autore.html and lista_libri.html and it runs well.
But if I active a link between lista_libri.html and lista_generi.html, it results blank.
Below I share the code strings that define model, view and templates.
models.py
from django.db import models
from django.urls import reverse
class Genere(models.Model):
nome = models.CharField(max_length=20)
def __str__(self):
return self.nome
def get_absolute_url(self):
return reverse("libri_genere", kwargs={"pk": self.pk})
class Meta:
verbose_name = "Genere"
verbose_name_plural = "Generi"
class Autore(models.Model):
nome = models.CharField(max_length=20)
cognome = models.CharField(max_length=20)
nazione = models.CharField(max_length=20)
def __str__(self):
return self.nome + " " + self.cognome
def get_absolute_url(self):
return reverse("profilo_autore", kwargs={"pk": self.pk})
class Meta:
verbose_name = "Autore"
verbose_name_plural = "Autori"
class Libro(models.Model):
titolo = models.CharField(max_length=100)
isbn = models.CharField(max_length=13)
autore = models.ForeignKey(Autore, on_delete=models.CASCADE, related_name="libri")
genere = models.ManyToManyField(Genere, related_name="generi")
def __str__(self):
return self.titolo
class Meta:
verbose_name = "Libro"
verbose_name_plural = "Libri"
views.py
from django.views.generic.detail import DetailView
from django.views.generic.list import ListView
from .models import Autore, Libro, Genere
class AutoreDCBV(DetailView):
model = Autore
template_name = "autore.html"
class LibroLCBV(ListView):
model = Libro
template_name = "lista_libri.html"
class GenereDCBV(DetailView):
model = Genere
template_name = "lista_generi.html"
urls.py
from django.urls import path
from .views import LibroLCBV, AutoreDCBV, GenereDCBV
urlpatterns = [
path('', LibroLCBV.as_view(), name='lista_libri'),
path('autore/<int:pk>/', AutoreDCBV.as_view(), name='profilo_autore'),
path('genere/<int:pk>/', GenereDCBV.as_view(), name='libri_genere'),
]
lista_generi.html
{% extends 'base.html' %}
{% block head_title %}{{ block.super }} | {{ genere }}{% endblock head_title %}
{% block content %}
<h1>Genere: {{ nome }}</h1>
<br>
{% for gen in genere.generi.all %}
<h4><strong>Titolo: </strong> {{ gen.titolo }} </h4>
<h5><strong>Autore: </strong> {{ gen.autore }} </h5>
<p><strong>ISBN: </strong> {{ gen.isbn }} </p>
<hr>
{% endfor %}
{% endblock content %}
lista_libri.html
{% extends 'base.html' %}
{% block head_title %}{{ block.super }} | Libreria{% endblock head_title %}
{% block content %}
<h1>La nostra libreria:</h1>
<br>
{% for libro in object_list %}
<h4><strong>Titolo: </strong> {{ libro.titolo }} </h4>
<h5><strong>Autore: </strong> {{ libro.autore }} </h5>
<h6><strong>Genere </strong></h6>
{% for genere in libro.genere.all %}
{{ genere }}
{% endfor %}
<p><strong>ISBN: </strong> {{ libro.isbn }} </p>
<hr>
{% endfor %}
{% endblock content %}
What is wrong?
{{ libro.genere.get_absolute_url }}
libro.genere is not a Genere instance. It is a ManyRelatedManager which you can use to access related instance. Since libro.genere does not have a get_absolute_url method, it is evaluated as the empty string '' in the rendered template.
You are already looping through {% for genere in libro.genere.all %}, therefore you should use {{ genere.get_absolute_url }}.
{% for genere in libro.genere.all %}
{{ genere }}
{% endfor %}
Related
I have to do wishlist, I have done wishlist page, model and html.bBut when I click on the button bellow my post, I'm redirected to wishlist page and post didnt saved in my wishlist.So thats my code:
models.py
class Wishlist(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL,
on_delete=models.CASCADE)
wished_item = models.ForeignKey(Posts, on_delete=models.CASCADE)
def __str__(self):
return self.wished_item.title
class Posts(models.Model):
TYPE = Choices(
('private', _('private')),
('business', _('business')),
)
STATUS = Choices(
('active', _('active')),
('deactivated', _('deactivated'))
)
owner = models.ForeignKey(settings.AUTH_USER_MODEL, blank=True, null=True, related_name='posts',
on_delete=models.CASCADE, verbose_name='owner')
phone_number = PhoneNumberField(verbose_name=_('Phone_number'), null=False, blank=False, unique=True)
title = models.CharField(verbose_name=_('Title'), max_length=100)
text = RichTextField(verbose_name=_('Text'))
image = models.ImageField(upload_to='images/%Y/%m/%d/', null=True, blank=True, validators=[file_size])
price = models.DecimalField(verbose_name=_('Price'), decimal_places=2, max_digits=9)
status = models.CharField(choices=STATUS, max_length=50)
created = models.DateTimeField(auto_now=True)
type = models.CharField(choices=TYPE, max_length=50)
def __str__(self):
return self.title
views.py
class WishListView(generic.View):
def get(self, *args, **kwargs):
wish_items = Wishlist.objects.filter(user=self.request.user)
context = {
'wish_items': wish_items
}
return render(self.request, 'wishlist/wishlist.html', context=context)
def addToWishList(request):
if request.method == 'POST':
post_var_id = request.POST.get('object-id')
post_var = Posts.objects.get(id=post_var_id)
print(post_var)
try:
wish_item = Wishlist.objects.get(user=request.user, post=post_var)
if wish_item:
wish_item.save()
except:
Wishlist.objects.create(user=request.user, post=post_var)
finally:
return HttpResponseRedirect(reverse('wishlist'))
wishlist.html
{% extends 'posts/base.html' %}
{% load thumbnail %}
{% block content %}
<div>
{% for item in wish_items %}
{% if item.wished_item.image1 %}
<img src="{{item.wished_item.image.url}}" alt="">
{% endif %}
</div>
<div>
<li>{{item.wished_item.title}}</li>
<li>{{item.wished_item.text}}</li>
<li>{{item.wished_item.price}}</li>
<li>{{item.wished_item.phone_number}}</li>
{% if item.wished_item.image %}
<img src="{% thumbnail item.wished_item.image 200x200 crop %}" alt="" />
<p></p>
{% endif %}
</div>
{% endfor %}
{% endblock %}
urls.py
urlpatterns = [
path("wishlist/", WishListView.as_view(), name='wishlist'),
path("add-to-wishlist", addToWishList, name='add-to-wishlist'),
]
and all posts template with add to wishlist button.
<ul>
{% for object in object_list %}
<li>Owner: {{ object.owner }}</li>
<li>Phone: {{ object.phone_number }}</li>
<li>Title: {{ object.title }}</li>
<li>Text: {{ object.text }}</li>
<li>Type: {{ object.type }}</li>
<li>Price: {{ object.price }}</li>
<li>Date: {{ object.created }}</li>
<p>
{% if object.image %}
<img src="{% thumbnail object.image 200x200 crop %}" alt="" />
{% endif %}
</p>
<form action="{% url 'add-to-wishlist' %}" method="POST">
{%csrf_token%}
<input type="hidden" name="object-id" value="{{object.id}}">
<input type="submit" value="Add to Wishlist">
</form>
<hr/>
Probably problem with posts Id, but I'm not sure in that.
You can use get_or_create instead of the if else statement for if exist or not. And use get_object_or_404 to make code more clear.
from django.shortcuts import get_object_or_404
def addToWishList(request):
if request.method == 'POST':
post_obj = get_object_or_404(Post, pk=request.POST.get('object-id'))
Wishlist.objects.get_or_create(user=request.user, post=post_obj)
return HttpResponseRedirect(reverse('wishlist'))
In your views.py try to replace these lines:
try:
wish_item = Wishlist.objects.get(user=request.user, post=post_var)
if wish_item:
wish_item.save()
except:
Wishlist.objects.create(user=request.user, post=post_var)
with
wish_item, was_created = Wishlist.objects.get_or_create(user=request.user, post=post_var)
# for debugging
if was_created:
print(f"{wish_item} was created")
else:
print(f"{wish_item} already exists")
what is the output?
The code looks OK for me. You might add a trailing / in your urls.py after the path("add-to-wishlist/" ... but I can't spot anything wrong in the first place.
I have made a comment system under my books where only the authenticated user can comment. When I use the form to add a comment, it doesn't work! why ?
here is my models
models.py
class Books(models.Model):
author = models.ManyToManyField(Authors)
title = models.CharField(max_length=250)
number_of_pages = models.PositiveIntegerField(validators=[MaxValueValidator(99999999999)])
date_added = models.DateField(auto_now_add=True)
updated = models.DateField(auto_now=True)
publication_date = models.PositiveIntegerField(default=current_year(), validators=[MinValueValidator(300),
max_value_current_year])
cover = models.ImageField(upload_to='pics/covers/', default='pics/default-cover.jpg')
pdf_file = models.FileField(upload_to='pdfs/books/', default='pdfs/default-pdf.pdf')
category = models.ForeignKey(Categories, on_delete=models.CASCADE)
def __str__(self):
return self.title
class Comments(models.Model):
book = models.ForeignKey(Books, on_delete=models.CASCADE)
user = models.ForeignKey(User, on_delete=models.CASCADE)
body = models.TextField()
date = models.DateTimeField(auto_now_add=True)
def __str__(self):
return '{} - {}'.format(self.livre.title, self.user)
here is my forms
forms.py
class BookForm(ModelForm):
class Meta:
model = Books
fields = '__all__'
class CommentForm(ModelForm):
class Meta:
model = Comments
fields = ['body']
here is my views
views.py
#login_required(login_url='login')
def book_detail_view(request, book_id):
books = get_object_or_404(Books, pk=book_id)
context = {'books': books,}
return render(request, 'book_detail.html', context)
#login_required(login_url='login')
def add_comment(request, comment_id):
form = CommentForm()
books = get_object_or_404(Books, pk=comment_id)
user = request.user
if request.method == "POST":
form = CommentForm(request.POST, instance=books)
if form.is_valid():
comment = form.save(commit=False)
comment.user = user
comment.books = books
comment.save()
return redirect('book_detail', books.id)
context = {'form': form}
return render(request, 'comment_form.html', context)
here is my book detail page
book_detail.html
{% extends 'base.html' %}
{% block title %} {{ books.title }} {% endblock %}
{% block content %}
<div class="row">
<div class="col-lg-4">
<p><img src="{{ books.cover.url }}"></p>
</div>
<div class="col-lg-8">
<h2>{{ books.title }}</h2>
<b>Author : </b>
{% for author in books.author.all %}
{{ author.name }}
{% if not forloop.last %},{% endif %}
{% endfor %}<br/>
<b>Catégory : </b>{{ books.category }}<br/>
<b>Pages : </b>{{ books.number_of_pages }}<br/>
<b>Publication : </b>{{ books.publication_date }}<br/>
<b>Date added : </b>{{ books.date_added }}<br/>
<b>Updated : </b>{{ books.updated }}<br/>
</div>
</div>
<div class="row">
<div class="col-lg-12">
<p><button class="btn btn-outline-dark btn-sm"><i class="far fa-eye"></i> Read</button></p>
</div>
</div>
<hr/>
<div class="container-fluid">
<h2>Comments</h2>
</div>
<div class="container-fluid">
{% if not books.comments.all %}
<p>No comments yet ! <a class="text-primary" href="{% url 'add_comment' books.id %}">Add comment...</a></p>
{% else %}
<a class="text-primary" href="{% url 'add_comment' books.id %}">Add comment !</a><br/><br/>
{% for comment in books.comments.all%}
<b>{{ comment.user }}</b> - <span class="text-muted" style="font-size: 13px;">{{ comment.date }}</span>
<p>{{ comment.body }}</p>
{% endfor %}
{% endif %}
</div>
{% endblock %}
here is my form for comment model
comment_form.html
{% extends 'base.html' %}
{% block title %} Add a comment {% endblock %}
{% block content %}
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Add this comment</button>
</form>
{% endblock %}
here is my urls
urls.py
urlpatterns = [
# BOOKS
path('book/<int:book_id>/', views.book_detail_view, name='book_detail'),
# COMMENTS
path('book/<int:comment_id>/comment/', views.add_comment, name='add_comment'),
]
Your form is currently set to edit the book, not the comment, you should remove the instance=books:
if request.method == "POST":
# no instance=books ↓
form = CommentForm(request.POST)
If you use instance=books, the form will set attributes to the Books object, and then the comment = form.save(commit=False) will result in the fact that comment is a Books object that is already saved and thus updated in the database.
You also made a typo when setting the book of a Comments object: it is book, not books:
if form.is_valid():
comment = form.save(commit=False)
comment.user = user
comment.book = books # ← .book, not .books
comment.save()
Note: normally a Django model is given a singular name, so Book instead of Books.
I'm new to Django and I'ma building a basic blog application.
I cant show manytomany field (in tags) and a foreignkey field (comments) in my details page.
models.py
class BlogContent(models.Model):
title = models.CharField(max_length=200)
author = models.CharField(max_length=200)
content = models.TextField()
date_published = models.DateField(auto_now=True)
image = models.ImageField(upload_to='media/')
def __str__(self):
return self.title
class TagName(models.Model):
tag = models.ManyToManyField(BlogContent, null=True)
name = models.CharField(max_length=100, blank=True, null=True)
def __str__(self):
return self.name
class Comment(models.Model):
comt_text = models.TextField()
comments = models.ForeignKey(BlogContent, on_delete=models.CASCADE)
date_published = models.DateField(auto_now=True)
name = models.CharField(max_length=200, blank=True, null=True)
def __str__(self):
return self.name
views.py
def details(request, blogcontent_id):
data_blog = get_object_or_404(BlogContent, pk=blogcontent_id)
data_tag = get_object_or_404(TagName, pk=blogcontent_id)
data_comment = Comment.objects.select_related()
return render(request, 'details.html',
{'data_blog': data_blog, 'data_tag':data_tag, 'data_comment':data_comment})
details.html
{% extends 'base.html' %}
{% block body_base %}
<img class="card-img-top img-responsive" src={{ data_blog.image.url }} alt="Card image cap">
<h2 class="blog-post-title">{{ data_blog.title }}</h2>
<p class="blog-post-meta">{{ data_blog.date_published }} {{ data_blog.author }}</p>
<p>{{ data_blog.content }}</p>
{% endblock %}
how do i show foreignkey and manaytomany fieds after this?
TBH this is much easier if you use class based views.
The view would simply be:
class BlogContentDetail (DetailView):
model = BlogContent
The url call would be url(r'^blog-detail/(?P<pk>\d+)/$, BlogContentDetail.as_view(), name="blog_detail")
Your html file should be called blogcontent_detail.html and held within the app subfolder in the templates folder
The template would then be:
{% extends 'base.html' %}
{% block body_base %}
<img class="card-img-top img-responsive" src={{ object.image.url }} alt="Card image cap">
<h2 class="blog-post-title">{{ object.title }}</h2>
<p class="blog-post-meta">{{ object.date_published }} {{ object.author }}</p>
<p>{{ object.content }}</p>
{% for tag in object.tags_set.all %}{{ tag }}{% endfor %}
{% endblock %}
You can iterate the ManyToMany Field in this way
{% for tags in data_tag.tag.all %}
<p > {{tags}} </ p>
{% endfor %}
For foreign key
{{data_comment.comments}}
When I send
menus = Menu.objects.all()
through render
render(request, 'index.html', {'menus': menus})
it did not show me anything, just empty page
But other variables like
info = Info.objects.last()
is working properly
this is view.py
'''some code here'''
def home(request):
slides = Slide.objects.order_by('created')[:3]
main_articles = MainArticle.objects.order_by('created')[:5]
last_news = News.objects.all()[:4]
info = OtherInfo.objects.last()
promo = Promo.objects.last()
menus = Menu.objects.all()
return render(request, 'index.html', {'slides': slides,
'main_articles': main_articles,
'last_news': last_news,
'info': info,
'promo': promo,
'menus': menus
})
This is models.py
class Menu(models.Model):
name = models.CharField(max_length=100)
created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.name
class Meta:
ordering = ('created',)
class SubMenu(models.Model):
menu = models.ForeignKey(Menu, related_name='sub_menu')
name = models.CharField(max_length=100)
created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return '{} -> {}'.format(self.menu, self.name)
class Meta:
ordering = ('created',)
'''some other models here'''
this is index.html
{% extends 'base.html' %}
{% block nav_bar %}
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
{% for m in menus.all %}
{% if m.sub_menu %}
<li class="dropdown">
{{ m.name }}<span class="caret"></span>
<ul class="dropdown-menu">
{% for sub in m.sub_menu.all %}
<li>{{ sub.name }}</li>
{% endfor %}
</ul>
</li>
{% else %}
<li>
{{ m.name }}
</li>
{% endif %}
{% endfor %}
</ul>
</div><!-- /.navbar-collapse -->
{% endblock %}
If you pass:
menus = Menu.objects.all()
you can use in your template:
{% for menu in menus %}
...
{% if menu.sub_menu.exists %}
{% for submenu in menu.sub_menu.all %}
....
You did already call .all() in your view.
I have a gallery (app in django 1.8), to which they are plugged in images. My problem is that create a link to the images in each category. I do not know how to do it on the side of the template and URL addresses are correct.
Models
class Gallery(models.Model):
title = models.CharField(max_length=200)
description = models.TextField()
image = ThumbnailerImageField(upload_to='paint/%Y/%m/%d')
class Meta:
verbose_name = "Gallery"
verbose_name_plural = " Galleries"
def __unicode__(self):
return self.title
class Paint(models.Model):
AVAILABLE = "Available"
NOT_AVAILABLE = "Not available"
STATUS_PAINT = (
(AVAILABLE, u"Dostępny"),
(NOT_AVAILABLE, u"Nie dostępny")
)
title = models.CharField(max_length=200)
gallery = models.ForeignKey(Gallery)
paint = ThumbnailerImageField(upload_to='paint/%Y/%m/%d')
price = models.CharField(max_length=50, blank=True, null=True)
status = models.CharField(choices=STATUS_PAINT, default=AVAILABLE, max_length=50)
class Meta:
verbose_name = "Picture"
verbose_name_plural = "Images"
def __unicode__(self):
return self.title
Views
class GalleryView(generic.ListView):
model = Paint
template_name = "www/gallery_list.html"
context_object_name = "gallery"
def get_queryset(self):
return Paint.objects.all()
class GalleryDetailsView(generic.ListView):
model = Gallery
context_object_name = "images"
template_name = "www/gallery_details.html"
urls
urlpatterns = [
url(r'^$', MainPage.as_view(), name='mainpage'),
url(r'^about/$', AboutMe.as_view(), name="about"),
url(r'^gallery/$', GalleryView.as_view(), name="gallery"),
url(r'^gallery1/$', GalleryDetailsView.as_view(), name="gallery_details"),
url(r'^contact/$', contact, name="contact"),
]
Template gallery list - main section
{% extends "base.html" %}
{% load thumbnail %}
{% block content %}
{% for i in images %}
<div class="row">
<div class="col-md-5">
<img src="{{ i.image|thumbnail_url:'avatar1' }}"/>
</div>
<div class="col-md-7">
<h3>{{ i.title }}</h3>
<p>{{ i.description }}</p>
</div>
</div>
<hr>
{% endfor %}
{% endblock %}
{% block content_bottom %}{% endblock content_bottom %}
Template gallery details with images of gallery
{% extends "base.html" %}
{% load thumbnail %}
{% block content %}
<table class="center-table">
<tbody>
{% for image in gallery %}
{% if forloop.counter0|divisibleby:3 %}<tr>{% endif %}
<td style="padding-left:50px;padding-right:50px;color:grey">
<a data-lightbox="roadtrip" href="{{ image.paint.url }}"><img src="{{ image.paint|thumbnail_url:'avatar' }}" class="img-thumbnail img-responsive" /></a><br>
<div style="padding-top:8px;padding-bottom:20px;">
<b>Tytuł:</b> {{ image.title }}<br>
<b>Status: </b>{{ image.status }}<br>
<b>Cena: </b>{{ image.price }}<br>
</div>
</td>
{% if forloop.counter|divisibleby:3 or forloop.last %}</tr>{% endif %}
{% endfor %}
</tbody>
</table>
{% endblock %}
{% block content_bottom %}{% endblock content_bottom %}