Django: child model edit comment not working - python

I got problem with my edit comments when i press the edit comment from the template i get no error but is redirected to the top of the same page. Anyone got any idea how i can get it to allow me to edit the comment?
This post is edited with only the code needed and i fixed the delete comment from before so that code is removed.
Here is my code:
views.py:
from django.shortcuts import render, redirect, reverse, get_object_or_404
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.db.models import Q
from django.db.models.functions import Lower
from .models import Product, Category, Review
from .forms import ProductForm, ReviewForm
def product_detail(request, product_id):
product = get_object_or_404(Product, pk=product_id)
if request.method == 'POST':
rating = request.POST.get('rating', 3)
content = request.POST.get('content', '')
Review.objects.create(
product=product,
rating=rating,
content=content,
created_by=request.user
)
# redirect to the same page
return redirect('product_detail', product_id=product_id)
reviews = Review.objects.filter(product=product)
context = {
'product': product,
'reviews': reviews
}
return render(request, 'products/product_detail.html', context)
#login_required
def edit_review(request, review_id):
"""
Saves review form edited by user
"""
review = get_object_or_404(Review, pk=review_id)
product = Product.objects.get(name=review.product)
if request.method == 'POST':
review_form = ReviewForm(request.POST or None, instance=review)
if review_form.is_valid():
review_form.save()
messages.success(request, 'Successfully updated product!')
return redirect(reverse('product_detail', args=[product.id]))
# Success message if added
messages.success(request, 'Thank You! Review was edited')
else:
# Error message if form was invalid
messages.error(request, 'Something went wrong. '
'Make sure the form is valid.')
form = ReviewForm(instance=review)
messages.info(request, f'You are editing {review_id}')
template = 'products/edit_review.html'
context = {
'form': form,
'product': review,
}
return redirect(reverse('product_detail', args=[product.id]))
models.py:
from django.db import models
from django.contrib.auth.models import User
class Review(models.Model):
product = models.ForeignKey(Product, related_name='reviews', on_delete=models.CASCADE)
rating = models.IntegerField(default=3)
content = models.TextField()
created_by = models.ForeignKey(User, related_name='reviews', on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return '%s - %s' % (self.product.name, self.created_by)
urls.py:
from django.urls import path
from . import views
urlpatterns = [
path('', views.all_products, name='products'),
path('<int:product_id>/', views.product_detail, name='product_detail'),
path('add/', views.add_product, name='add_product'),
path('edit/<int:product_id>/', views.edit_product, name='edit_product'),
path('delete/<int:product_id>/', views.delete_product, name='delete_product'),
path('delete_review/<int:review_id>/delete_review', views.delete_review, name='delete-review'),
path('edit_review/<review_id>', views.edit_review, name="edit_review"),
]
forms.py:
from django import forms
from .widgets import CustomClearableFileInput
from .models import Product, Category, Review
class ReviewForm(forms.ModelForm):
class Meta:
model = Review
fields = ('content', 'rating')
widgets = {
'content': forms.Textarea(attrs={'class': 'form-control'}),
'rating': forms.Select(attrs={'class': 'form-control'}),
}
edit_review.html template
{% extends "base.html" %}
{% load static %}
{% block content %}
<div class="overlay"></div>
<div class="container">
<div class="row">
<div class="col-12 col-md-6">
<hr>
<h2 class="logo-font mb-4">Reviews</h2>
<h5 class="text-muted">Edit you're Review</h5>
<hr>
</div>
</div>
<div class="row">
<div class="col-12 col-md-6">
<form method="POST" action="{% url 'edit_review' review.id %}" class="form mb-2" enctype="multipart/form-data">
{% csrf_token %}
{% for field in form %}
{% if field.name != 'image' %}
{{ field | as_crispy_field }}
{% else %}
{{ field }}
{% endif %}
{% endfor %}
<div class="text-right">
<a class="btn btn-outline-black rounded-0" href="{% url 'reviews' %}">Cancel</a>
<button class="btn btn-black rounded-0" type="submit">Update Review</button>
</div>
</form>
</div>
</div>
</div>
{% endblock %}

for the first problem in the delete view you must refer to the model with capital Review
#login_required
def delete_review(request, review_id):
review = Review.objects.filter(review_id).last()
For the second problem you can see detailed information about this error and how to handle it, from Here

Related

Unable to show user specific link to specific page in django

I would like to create user specific links. I mean, when user signed up and logged in, he has redirected to create/ page. In that page user fills out the form and after pressing button, user has to redirect to list/ page, where there are user specific links to specific page, which contain schedule. Schedul appered from data, which user provided in create/ form.
So my problem is, when I filled out the form and redirect to list/ page, there are no links.
My code:
models.py
from django.db import models
from django.contrib.auth.models import User
class File(models.Model):
file = models.OneToOneField(User, on_delete=models.CASCADE, null=True)
#Further, they are fileds, which is nececary to create schedule.
#title = models.CharField('Название Графика', max_length = 50)
#x_title = models.CharField('Название Оси Х', max_length = 50)
#y_title = models.CharField('Название Оси Y', max_length = 50)
#etc...
views.py:
def create(request):
error = ''
if request.method == 'POST':
form = FileForm(request.POST)
if form.is_valid():
form.save()
return redirect('grafic:list')
else:
error = 'Форма была неверной('
form = FileForm()
data = {
'form': form,
'error': error,
}
return render(request, 'graf/create.html', data)
def list(request):
qs = File.objects.filter(file=request.user)
context = {
'user': request.user,
'qs': qs,
}
return render(request, 'graf/list.html', context)
list.html
{% extends 'base.html' %}
{% block content %}
{% if user.is_authenticated %}
<h2>{% block title %} Profile {% endblock %}</h2>
<p>Username: {{ user }}</p>
{% for b in qs %}
<article class="card">
<div class="card_wrapper">
<figure class="card_feature">
</figure>
<div class="card_box">
<a href="{% url 'grafic:index' b.id %}">
<header class="card_item card_header">
<h6 class="card__item card__item--small card__label">Твой график</h6>
<a class="card__item card__item--small card__title" href="{% url 'grafic:index' b.id %}">
{{b.graf_title}}
</a>
</header>
<hr class="card__item card__divider">
</a>
</div>
</div>
</article>
{% endfor %}
{% endif %}
{% endblock %}
urls.py
from django.urls import path
from . import views
app_name = 'grafic'
urlpatterns = [
path('', views.first, name = 'first'),
path('create/', views.main, name = 'main'),
path('list/', views.list, name = 'list'),
path('files/<int:grafics>', views.index, name = 'index'),
path('login/', views.loginpage, name = 'loginpage'),
path('register/', views.registerpage, name = 'registerpage'),
]
That's all. Sorry if my code is such inconvenient. Thank you in advance for your cooperation)
enter image description here
That is my problem. In the 'file' field there are no user.

How do I use django formset_factories?

I am trying to work on a django-based project/website that logs who took out our dogs last. I am very new to django so please bear with lack of knowledge in the field. I currently have my project set up so that I have models based on users/family members, the families' dogs, posts (logs of when and who took out the dogs), and actions, which is a child class that uses the dog and post models as foreign keys to see if the dogs peed and or pooped when they were taken out. The part that I am stuck on is trying to figure out how I create the post form. Since we have two dogs I need the form/post page to display a set of check boxes (for peeing and pooping actions) for each dog model that exists. While I can successfully display one action set, I run into the difficulty of trying to display the correct number of action sets and also to post the set of actions and the post itself. I have been trying to work with the formset_factory function but I am confused as to how I get it to function properly. Can anyone help? I have been stuck on this problem for quite a while and any support would be greatly appreciated.
models.py:
from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User
from django.urls import reverse
class Dog(models.Model):
name = models.CharField(max_length = 20)
class Post(models.Model):
walker = models.ForeignKey(User, on_delete = models.CASCADE)
time_posted = models.DateTimeField(default = timezone.now)
issues = models.TextField(max_length = 300)
class Action(models.Model):
post = models.ForeignKey(Post, on_delete = models.CASCADE)
dog = models.ForeignKey(Dog, on_delete = models.CASCADE)
peed = models.BooleanField(default = False)
pooped = models.BooleanField(default = False)
forms.py:
from django import forms
from django.forms import formset_factory
from dog_log_app.models import *
class Log_Form(forms.ModelForm):
class Meta:
model = Post
fields = ("issues",)
class Action_Form(forms.Form):
peed = forms.BooleanField(initial = False, required = False)
pooped = forms.BooleanField(initial = False, required = False)
views.py:
from django.shortcuts import render
from django.forms import formset_factory, modelformset_factory
from .models import Post, Dog, Action
from dog_log_app.forms import *
from django.contrib.auth.models import User
from django.http import HttpResponse, HttpResponseRedirect
def home(request):
context = {
'posts': Post.objects.all().order_by('-time_posted'),
'actions': Action.objects.all(),
'dogs': Dog.objects.all()
}
return render(request, 'dog_log_app/home.html', context)
def post(request):
form_post = Log_Form(request.POST or None)
form_actions = modelformset_factory(Action, fields = ('peed', 'pooped'), extra = Dog.objects.count())
if request.method == 'POST':
form_post = Log_Form(request.POST)
if form_post.is_valid() and form_actions.is_valid():
post_save = form_post.save(commit = False)
post_save.walker = request.user
post_save.save()
form_actions.save()
return HttpResponseRedirect('..')
context = {
'post': form_post,
'action': formset_factory(Action_Form, extra = Dog.objects.count()),
'dogs': Dog.objects.all()
}
return render(request, 'dog_log_app/post_form.html', context)
post_form.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Post</title>
</head>
<body>
<div>
<form method="POST">
{% csrf_token %}
<fieldset>
<legend>Create Post</legend>
<h3>{{dogs.name}}</h3>
<p>{{action.as_p}}</p>
<p>{{post.as_p}}</p>
</fieldset>
<div>
<button type="submit" value="Ok">Post</button>
</div>
</form>
</div>
</body>
</html>
what you can try would be to use ajax to add the amount you want, what I usually do is use the form:
from django.forms import ModelForm
from django.forms.models import inlineformset_factory
class PostForm(ModelForm):
class Meta:
model = Post
fields = (
'issues',
)
class ActionForm(ModelForm):
class Meta:
model = Action
fields = (
'peed', 'pooped'
)
ActionFormSet = inlineformset_factory(
Post, Action, form=ActionForm,
fields = ['peed', 'pooped'], extra=1, can_delete=True,
)
With the forms created, we move on to the views, which will be class-based for convenience:
from django.db import transaction
from django.views.generic import CreateView, UpdateView
from .models import Post
from .forms import PostForm, ActionFormSet
class PostCreateView(CreateView):
template_name = 'your template'
form_class = PostForm
success_url = reverse_lazy('your url')
def get_context_data(self, **kwargs):
data = super().get_context_data(**kwargs)
if self.request.POST:
data['formset'] = ActionFormSet(self.request.POST)
else:
data['formset'] = ActionFormSet()
return data
def form_valid(self, form):
context = self.get_context_data()
formset = context['formset']
with transaction.atomic():
self.object = form.save()
if formset.is_valid():
formset.instance = self.object
formset.instance.walker = self.request.user
formset.save()
return super().form_valid(form)
class PostUpdateView(UpdateView):
template_name = 'your template'
form_class = PostForm
model = Post
success_url = reverse_lazy('your url')
def get_context_data(self, **kwargs):
data = super().get_context_data(**kwargs)
if self.request.POST:
data['formset'] = ActionFormSet(
self.request.POST, instance=self.object)
else:
data['formset'] = ActionFormSet(instance=self.object)
return data
def form_valid(self, form):
context = self.get_context_data()
formset = context['formset']
with transaction.atomic():
self.object = form.save()
if formset.is_valid():
formset.instance = self.object
formset.save()
return super().form_valid(form)
and to display the information you can use a jquery library for the dynamic information on saving:
enter link description here
With that the configuration is much easier
An example template would be:
{% extends "base.html" %}
{% load static %}
{% block content %}
<div class="container">
<div class="card">
<div class="card-content">
<h2>Agregar Proyecto</h2>
<div class="col-md-4">
<form id="form-container" method="post">
{% csrf_token %}
{{ form }}
<h2>Actions</h2>
<table>
{{ formset.management_form }}
{% for form in formset %}
{% if forloop.first %}
<thead>
<tr>
{% for field in form.visible_fields %}
<th>{{ field.label|capfirst }}</th>
{% endfor %}
</tr>
</thead>
{% endif %}
<tr id="projects_data">
{% for field in form.visible_fields %}
<td>
{# Include the hidden fields in the form #}
{% if forloop.first %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% endif %}
{{ field.errors.as_ul }}
{{ field }}
</td>
{% endfor %}
</tr>
{% endfor %}
</table>
<button type="submit" class="btn btn-success">{{ message }}</button>
Cancel
</form>
</div>
</div>
</div>
</div>
{% endblock %}
{% block script %}
<script type="text/javascript">
$(function () {
$('#projects_data').formset({
prefix: '{{ formset.prefix }}',
addText: 'create',
deleteText: 'remove',
});
})
</script>
{% endblock %}
and in that way add data dynamically.

How to add comments on django

I am trying to add a comment system to my project, all the code looks fine but I am getting this error "ValueError at /
The QuerySet value for an exact lookup must be limited to one result using slicing". I dont know what is wrong but the error might be on the views.py file.
views.py
def imagelist(request):
images = Post.objects.all()
post = get_object_or_404(Post)
comments = Comment.objects.filter(post=images)
if request.method == 'POST':
comment_form = CommentForm(request.POST or None)
if comment_form.is_valid():
contentt = request.POST.get('content')
comment = Comment.objects.create(post=images, user=request.user, content=content)
comment.save()
return HttpResponseRedirect(post.get_absolute_url())
else:
comment_form = CommentForm()
context2 = {
"images": images,
"comments": comments,
"comment_form": comment_form,
}
return render(request, 'imagelist.html', context2)
models.py
class Comment(models.Model):
post = models.ForeignKey(Post, on_delete=models.CASCADE)
user = models.ForeignKey(User, on_delete=models.CASCADE)
content = models.TextField(max_length=160)
timestamp = models.DateTimeField(auto_now_add=True)
def __str__(self):
return '{}-{}'.format(self.post.title.str(self.user.username))
class Post(models.Model):
text = models.CharField(max_length=200)
posti = models.ImageField(upload_to='media/images', null=True, blank="True")
video = models.FileField(upload_to='media/images', null=True, blank="True")
user = models.ForeignKey(User, related_name='imageuser', on_delete=models.CASCADE, default='username')
liked = models.ManyToManyField(User, default=None, blank=True, related_name='liked')
updated = models.DateTimeField(auto_now=True)
created =models.DateTimeField(auto_now_add=True)
def __str__(self):
return str(self.tittle)
forms.py
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = ('content',)
You need to pass to the create mathod of the comments a single Post since the corresponding fields is a ForeignKey and you're passing an entire queryset (Post.objects.all())
You need get just the post where the comment should live.
single_post = Post.objects.get(pk=the_post_pk)
comment = Comment.objects.create(post=single_post, user=request.user, content=content)
The problem is that you write:
images = Post.objects.all()
comments = Comment.objects.filter(post=images)
Here images is a set of Post objects, not a single Post object, hence you can not filter on that. But you actually do not need to do this anyway.
Furthermore there is also a small mistake in the __str__ of your Comment model:
class Comment(models.Model):
# …
def __str__(self):
return '{}-{}'.format(self.post.text, self.user.username)
But the view itself looks "odd", since you here write a list of Posts, but if you make a POST request, you will somehow need to know to what post you want to submit the Comment, therefore at least the view that accepts the POST request, will need to know the primary key of the Post to comment on. You can for example encode that in the urls.py:
# appname/urls.py
from django.urls import path
from app import views
urlpatterns = [
path('post/<int:pk>/', views.post_detail, name='post_detail'),
path('post/', views.post_list, name='post_detail')
]
In that view, we can then fetch the item, for example with get_object_or_404, and in case of a POST set the post and user objects in the view:
from django.shortcuts import redirect, get_object_or_404
from django.contrib.auth.decorators import login_required
#login_required
def post_detail(request, pk):
image = get_object_or_404(Post, pk=pk)
if request.method == 'POST':
comment_form = CommentForm(request.POST, request.FILES)
if comment_form.is_valid():
comment_form.instance.user = request.user
comment_form.instance.post = image
comment_form.save()
return redirect(post)
else:
comment_form = CommentForm()
context = {
'post': image,
'comment_form': comment_form,
}
return render(request, 'imagedetail.html', context)
In your template, you can render the comments of the post with:
{{ post }}
{% for comment in post.comment_set.all %}
{{ comment }}
{% endfor %}
<form method="post" action="{% url 'post_detail' pk=post.pk %}">
{% csrf_token %}
{{ comment_form }}
</form>
you can also make a view that renders a list:
#login_required
def post_list(request, pk):
images = Post.objects.prefetch_related('comment_set')
comment_form = CommentForm()
context = {
'image': images,
'comment_form': comment_form,
}
return render(request, 'imagelist.html', context)
in the template for the list, you can render it with:
{% for post in images %}
{{ post }}
{% for comment in post.comment_set.all %}
{{ comment }}
{% endfor %}
<form method="post" action="{% url 'post-detail' pk=post.pk %}">
{% csrf_token %}
{{ comment_form }}
</form>
{% endfor %}
here we thus make a POST request to the post-detail view.
After 4 hours of searching for answers, this is how I achieve it. All I did was add this new view, method, url and html. Hope this helps!
views.py
def imagedetail(request, pk):
post = get_object_or_404(Post, pk=pk)
comments = Comment.objects.filter(post=post)
if request.method == 'POST':
comment_form = CommentForm(request.POST or None)
if comment_form.is_valid():
content = request.POST.get('content')
comment = Comment.objects.create(post=post, user=request.user, content=content)
comment.save()
return HttpResponseRedirect(post.get_absolute_url())
else:
comment_form = CommentForm()
context2 = {
"comments": comments,
"comment_form": comment_form,
}
return render(request, 'imagedetail.html', context2)
models.py (on Post model)
def get_absolute_url(self):
return reverse('imagedetail', args=[self.id])
urls.py (for new view which is imagedetail)
path('imagedetail/<int:pk>/', views.imagedetail, name='imagedetail'),
imagelist.html (to redirect to imagedetail, btw it is a bootstrap button)
<a role="button" class="btn btn-primary" href="{% url 'imagedetail' pk=image.pk %}"></a>
imagedetail.html (it only shows comments)
<form method="post">
{% csrf_token %}
{{comment_form.as_p}}
{% if request.user.is_authenticated %}
<input type="submit" value="Submit" class="btn btn-outline-succes">
{% else %}
<input type="submit" value="Submit" class="btn btn-outline-succes" disabled>
{% endif %}
</form>
<div class="main-comment-section">
{{ comments.count }}
{% for comment in comments %}
<blockquote class="blockquote">
<p class="mb-0">{{ comment.content }}</p>
<footer class="blockquote-footer">by <cite title="Source Title">{{ comment.user }}</cite></footer>
</blockquote>
{% endfor %}
</div>
2 - forms.py icine elave ele:
from django import forms
from .models import Comment
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = ('name', 'body')
# overriding default form setting and adding bootstrap class
def __init__(self, *args, **kwargs):
super(CommentForm, self).__init__(*args, **kwargs)
self.fields['name'].widget.attrs = {'placeholder': 'Enter name', 'class': 'form-control'}
self.fields['body'].widget.attrs = {'placeholder': 'Comment here...', 'class': 'form-control', 'rows': '5'}
3 - models.py elave ele :
class Comment(models.Model):
post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name="comments")
name = models.CharField(max_length=50)
parent = models.ForeignKey("self", null=True, blank=True, on_delete=models.CASCADE)
body = models.TextField()
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
active = models.BooleanField(default=True)
class Meta:
ordering = ('created',)
def __str__(self):
return self.name
def get_comments(self):
return Comment.objects.filter(parent=self).filter(active=True)
4 - views.py post bele gorunmelidi :
def post (request,slug):
post = Post.objects.get(slug = slug)
latest = Post.objects.order_by('-timestamp')[:3]
comments = post.comments.filter(active=True)
new_comment = None
comment_form = CommentForm()
comment_form = CommentForm(data=request.POST)
if comment_form.is_valid():
new_comment = comment_form.save(commit=False)
new_comment.post = post
new_comment.save()
comment_form = CommentForm()
context = {
'post': post,
'latest': latest,
'comments': comments,
'comment_form': comment_form
}
return render(request, 'post.html', context)
5 - post.html de author altina divider den sonra elave ele :
<hr/>
<h3>Add Comment</h3>
<form method="post" action="">
{% csrf_token %}
{{ comment_form.as_p }}
<button type="submit" class="btn btn-primary">Comment</button>
</form>
{% with comments.count as total_comments %}
<h3 class="mt-5">
{{ total_comments }} comment{{ total_comments|pluralize }}
</h3>
{% endwith %}
{% if not post.comments.all %}
No comments yet
{% else %}
{% for comment in post.get_comments %}
{% include 'comment.html' with comment=comment %}
{% endfor %}
{% endif %}
</div>
6 - admin.py elave ele :
#admin.register(Comment)
class CommentAdmin(admin.ModelAdmin):
list_display=('name', 'post', 'created', 'active')
list_filter = ('active', 'created', 'updated')
search_fields = ('name', 'body')
7 - templates de comment.html yarat ve icine elave et :
<div class="border-0 border-start border-2 ps-2" id="{{comment.id}}">
<div class="mt-3">
<strong>{{comment.name}}</strong>
{% if comment.parent.name%} to <strong>{{comment.parent.name}}</strong>{% endif %}
<small class="text-muted">On {{ comment.created.date }}</small>
</div>
<div class="border p-2 rounded">
<p>{{comment.body}}</p>
<button class="btn btn-primary btn-sm" onclick="handleReply({{comment.id}})">Reply</button>
<div id="reply-form-container-{{comment.id}}" style="display:none">
</div>
</div>
{% for comment in comment.get_comments %}
{% include 'comment.html' with comment=comment %}
{% endfor %}
8 - models de post un altina elave ele
def get_comments(self):
return self.comments.filter(parent=None).filter(active=True)

Posts from admin panel on different subpages

I would like to add post list from main page to another subpages. (main page to subpage called "programowanie")
For example:
I have a website wwww.example.com. On this website I have a post list that is generated from admin panel (I can add, delete a posts using admin panel).
The problem is that when I try to copy templates from start page with post list to other subpage (called: www.example.com/programowanie) it doeasn't work (I see a template from main page but without post list)
I think the problem is in templates/blog/post/list.html in loop {% for post in posts %}
If I solve this problem I would like to add in admin panel different overlap to publish posts only in "programowanie" subpage.
This is my files:
blog/views.py
from django.shortcuts import render, get_object_or_404, HttpResponse
from .models import Post, Posta, Comment
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.views.generic import ListView
from .forms import EmailPostForm, CommentForm
from django.core.mail import send_mail
from taggit.models import Tag
from django.db.models import Count
def post_share(request, post_id):
# Pobranie posta na podstawie jego identyfikatora.
post = get_object_or_404(Post, id=post_id, status='published')
sent = False
if request.method == 'POST':
# Formularz został wysłany.
form = EmailPostForm(request.POST)
if form.is_valid():
# Weryfikacja pól formularza zakończyła się powodzeniem…
cd = form.cleaned_data
post_url = request.build_absolute_uri(
post.get_absolute_url())
subject = '{} ({}) zachęca do przeczytania "{}"'.format(cd['nick'], cd['email'], post.title)
message = 'Przeczytaj post "{}" na stronie {}\n\n Komentarz dodany przez {}: {}'.format(post.title, post_url, cd['nick'], cd['komentarz'])
send_mail(subject, message, 'admin#myblog.com', [cd['adresat']])
sent = True
else:
form = EmailPostForm()
return render(request, 'blog/post/share.html', {'post': post,
'form': form,
'sent': sent})
class PostListView(ListView):
queryset = Post.published.all()
context_object_name = 'posts'
paginate_by = 3
template_name = 'blog/post/list.html'
def post_list(request, tag_slug=None):
object_list = Post.published.all()
tag = None
if tag_slug:
tag = get_object_or_404(Tag, slug=tag_slug)
object_list = object_list.filter(tags__in=[tag])
paginator = Paginator(object_list, 3) # Trzy posty na każdej stronie.
page = request.GET.get('page')
try:
posts = paginator.page(page)
except PageNotAnInteger:
# Jeżeli zmienna page nie jest liczbą całkowitą,
# wówczas pobierana jest pierwsza strona wyników.
posts = paginator.page(1)
except EmptyPage:
# Jeżeli zmienna page ma wartość większą niż numer ostatniej strony
# wyników, wtedy pobierana jest ostatnia strona wyników.
posts = paginator.page(paginator.num_pages)
return render(request,
'blog/post/list.html',
{'page': page,
'posts': posts,
'tag': tag})
def post_detail(request, year, month, day, post):
post = get_object_or_404(Post, slug=post,
status='published',
publish__year=year,
publish__month=month,
publish__day=day)
comments = post.comments.filter(active=True)
if request.method == 'POST':
comment_form = CommentForm(data=request.POST)
if comment_form.is_valid():
new_comment = comment_form.save(commit=False)
new_comment.post = post
new_comment.save()
else:
comment_form = CommentForm()
# Lista podobnych postów.
post_tags_ids = post.tags.values_list('id', flat=True)
similar_posts = Post.published.filter(tags__in=post_tags_ids)\
.exclude(id=post.id)
similar_posts = similar_posts.annotate(same_tags=Count('tags'))\
.order_by('-same_tags','-publish')[:4]
return render(request,
'blog/post/detail.html',
{'post': post,
'comments': comments,
'comment_form': comment_form,
'similar_posts': similar_posts})
def programowanie(request):
return render(request, 'blog/post/base.html')
blog/models.py
# -*- coding: utf-8 -*-
from taggit.managers import TaggableManager
from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User
from django.core.urlresolvers import reverse
class PublishedManager(models.Manager):
def get_queryset(self):
return super(PublishedManager,
self).get_queryset()\
.filter(status='published')
class Post(models.Model):
STATUS_CHOICES = (
('draft', 'Roboczy'),
('published', 'Opublikowany'),
)
title = models.CharField(max_length=250)
slug = models.SlugField(max_length=250,
unique_for_date='publish')
author = models.ForeignKey(User,
related_name='blog_posts')
body = models.TextField()
publish = models.DateTimeField(default=timezone.now)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
status = models.CharField(max_length=10,
choices=STATUS_CHOICES,
default='draft')
objects = models.Manager() # Menedżer domyślny.
published = PublishedManager() # Menedżer niestandardowy.
tags = TaggableManager()
class Meta:
ordering = ('-publish',)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('blog:post_detail',
args=[self.publish.year,
self.publish.strftime('%m'),
self.publish.strftime('%d'),
self.slug])
class Comment(models.Model):
post = models.ForeignKey(Post, related_name='comments')
name = models.CharField(max_length=80)
email = models.EmailField()
komentarz = models.TextField()
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
active = models.BooleanField(default=True)
class Meta:
ordering = ('created',)
def __str__(self):
return 'Komentarz dodany przez {} dla posta {}'.format(self.name,
self.post)
blog/urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
# Widoki posta.
url(r'^$', views.post_list, name='post_list'),
url(r'^programowanie/$', views.programowanie, name='programowanie'),
#url(r'^$', views.PostListView.as_view(), name='post_list'),
url(r'^(?P<year>\d{4})/(?P<month>\d{2})/(?P<day>\d{2})/'\
r'(?P<post>[-\w]+)/$',
views.post_detail,
name='post_detail'),
url(r'^(?P<post_id>\d+)/share/$', views.post_share,
name='post_share'),
url(r'^tag/(?P<tag_slug>[-\w]+)/$', views.post_list,
name='post_list_by_tag'),
]
urls.py
from django.conf.urls import include, url
from django.contrib import admin
from blog import views
urlpatterns = [
url(r'^admin/', include(admin.site.urls)),
url(r'^about/', views.about, name="about"),
url(r'^programowanie/', views.programowanie, name="programowanie"),
url(r'^algorytmy/', views.algorytmy, name="algorytmy"),
url(r'^kontakt/', views.kontakt, name="kontakt"),
url(r'', include('blog.urls',
namespace='blog',
app_name='blog')),
]
blog/templates/base.html
{% load staticfiles %}
<!DOCTYPE html>
<html>
<head>
{% include "navbar.html" with page=posts %}
<title>{% block title %}{% endblock %}</title>
<link href="{% static "admin/css/blog.css" %}" rel="stylesheet">
</head>
<body>
<div id="content">
{% block content %}
{% endblock %}
</div>
<div id="sidebar">
<h2>Mój blog</h2>
<p>To jest mój blog.</p>
</div>
</body>
</html>
blog/templates/post/list.html
{% extends "blog/base.html" %}
{% block title %}Mój blog{% endblock %}
{% block content %}
<h1>Mój blog</h1>
{% if tag %}
<h2>Posty oznaczone tagiem "{{ tag.name }}"</h2>
{% endif %}
{% for post in posts %}
<h2>
<a href="{{ post.get_absolute_url }}">
{{ post.title }}
</a>
</h2>
<p class="tags">
Tagi:
{% for tag in post.tags.all %}
<a href="{% url "blog:post_list_by_tag" tag.slug %}">
{{ tag.name }}
</a>
{% if not forloop.last %}, {% endif %}
{% endfor %}
</p>
<p class="date">
Opublikowany {{ post.publish }} przez {{ post.author }}
</p>
{{ post.body|truncatewords_html:30|linebreaks }}
{% endfor %}
{% include "pagination.html" with page=posts %}
{% endblock %}
blog/templates/post/detail.html
{% extends "blog/base.html" %}
{% block title %}{{ post.title }}{% endblock %}
{% block content %}
<h1>{{ post.title }}</h1>
<p class="date">
Opublikowany {{ post.publish }} przez {{ post.author }}
</p>
{{ post.body|linebreaks }}
<p>
<a href="{% url "blog:post_share" post.id %}">
Udostępnij posta
</a>
</p>
<h2>Podobne posty</h2>
{% for post in similar_posts %}
<p>
{{ post.title }}
</p>
{% empty %}
Nie ma podobnych postów.
{% endfor %}
{% with comments.count as total_comments %}
<h2>
{{ total_comments }} komentarz{{ total_comments|pluralize:"y" }}
</h2>
{% endwith %}
{% for comment in comments %}
<div class="comment">
<p class="info">
Komentarz {{ forloop.counter }} dodany przez {{ comment.name }}
{{ comment.created }}
</p>
{{ comment.komentarz|linebreaks }}
</div>
{% empty %}
<p>Nie ma jeszcze żadnych komentarzy.</p>
{% endfor %}
{% if new_comment %}
<h2>Twój komentarz został dodany.</h2>
{% else %}
<h2>Dodaj nowy komentarz</h2>
<form action="." method="post">
{{ comment_form.as_p }}
{% csrf_token %}
<p><input type="submit" value="Dodaj komentarz"></p>
</form>
{% endif %}
{% endblock %}
Thanks for any help !! (I thinking about this third day )
The problem you have it's in the views.
Django template has to be rendered by a view, from this view is where you get the data to be rendered in the template. It doesn't matter which url you want to use and which template you are using in the views. What this means is that you can have different urls pointing to the same template (www.example.com/blog/ or www.example.com/programming/) and both render the same template.
If i understood you right, all you have to do is change this :
url(r'^$', views.post_list, name='post_list'),
url(r'^programowanie/$', views.programowanie, name='programowanie'),
To this:
url(r'^$', views.post_list, name='post_list'),
url(r'^programowanie/$', views.post_list, name='programowanie'),
You can refer to the official Django website in order to get more information about this : https://docs.djangoproject.com/en/2.0/intro/tutorial03/
Thanks for help :)
I solved this problem. There was a problem in urls.py file.

Django Website - TemplateDoesNotExist at /edit/117/

I'm using UpdateView to edit data using forms.
After cliking the Edit button a modal is being popped up with a few forms that can be edited and then after I edit and click confirm I get an error:
TemplateDoesNotExist at /edit/117/ (or other pk...)
DevOpsWeb/serverlist_form.html
Request Method: POST
Request URL: http://devopsweb:8000/edit/117/
Django Version: 1.11.6
Exception Type: TemplateDoesNotExist
Exception Value:
DevOpsWeb/serverlist_form.html
Why do I get this error?
Why when I get the modal the information of the PK is blank...?
Does anyone know any of these questions? I'm really stuck :(
Thank you!
view.py-
from django.shortcuts import render_to_response
from django.shortcuts import get_object_or_404
from django.shortcuts import render, redirect
from django.template import RequestContext
from django.views.generic import TemplateView, UpdateView, DeleteView, CreateView
from DevOpsWeb.forms import HomeForm
from DevOpsWeb.models import serverlist
from django.core.urlresolvers import reverse_lazy
from simple_search import search_filter
from django.db.models import Q
class HomeView(TemplateView):
template_name = 'serverlist.html'
def get(self, request):
form = HomeForm()
query = request.GET.get("q")
posts = serverlist.objects.all()
if query:
posts = serverlist.objects.filter(Q(ServerName__icontains=query) | Q(Owner__icontains=query) | Q(Project__icontains=query) | Q(Description__icontains=query) | Q(IP__icontains=query) | Q(ILO__icontains=query) | Q(Rack__icontains=query))
else:
posts = serverlist.objects.all()
args = {'form' : form, 'posts' : posts}
return render(request, self.template_name, args)
def post(self,request):
form = HomeForm(request.POST)
posts = serverlist.objects.all()
if form.is_valid(): # Checks if validation of the forms passed
post = form.save(commit=False)
#if not form.cleaned_data['ServerName']:
#post.servername = " "
post.save()
#text = form.cleaned_data['ServerName']
form = HomeForm()
return redirect('serverlist')
args = {'form': form, 'text' : text}
return render(request, self.template_name,args)
class PostDelete(DeleteView):
model = serverlist
success_url = reverse_lazy('serverlist')
class PostEdit(UpdateView):
model = serverlist
#post = serverlist.objetcs.get(server_id=server_id)
fields = ['ServerName','Owner','Project','Description','IP','ILO','Rack','Status']
success_url=reverse_lazy('serverlist')
urls.py -
from django.conf.urls import url, include
from DevOpsWeb.views import HomeView
from DevOpsWeb.views import PostDelete
from DevOpsWeb.views import PostEdit
from django.contrib import admin
admin.autodiscover()
urlpatterns = [
# Examples:
url(r'^$', HomeView.as_view(), name='serverlist'),
url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
#DevOpsWeb:8000/Delete/
url(r'^delete/(?P<pk>\d+)/$', PostDelete.as_view(), name="delete_post"),
url(r'^django_popup_view_field/', include('django_popup_view_field.urls', namespace="django_popup_view_field")),
url(r'^admin/', include(admin.site.urls)),
#DevOpsWeb:8000/edit/
url(r'^edit/(?P<pk>\d+)/$', PostEdit.as_view(), name="edit_post"),
]
forms.py -
from django import forms
from DevOpsWeb.models import serverlist
class HomeForm(forms.ModelForm):
ServerName = forms.CharField(widget=forms.TextInput,max_length = 30,required=False)
Owner = forms.CharField(max_length = 50,required=False)
Project = forms.CharField(max_length = 30,required=False)
Description = forms.CharField(max_length = 255,required=False)
IP = forms.CharField(max_length = 30,required=False)
ILO = forms.CharField(max_length = 30,required=False)
Rack = forms.CharField(max_length = 30,required=False)
Status = forms.CharField(max_length = 30,required=False)
class Meta:
model = serverlist
fields = ('ServerName' ,'Owner','Project','Description','IP','ILO','Rack','Status',)
class AutoCompleteModelChoiceField(forms.ModelChoiceField):
widget = forms.TextInput
def clean(self, value):
value = super(AutoCompleteModelChoiceField, self).clean(value)
return value
class serverForm(forms.ModelForm):
hotel = AutoCompleteModelChoiceField(queryset=serverlist.objects.all())
index.html (The part with the edit button)-
<div class="modal fade bd-example-modal-sm" id="Edit{{server.id}}" tabindex="-1" role="dialog" aria-labelledby="mySmallModalLabel" aria-hidden="true">
<div class="modal-dialog modal-sm">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Edit Server <b>{{ server.ServerName }}</b> </h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<form action="{% url 'edit_post' server.id %}" method="post"> {% csrf_token %}
<!--<center> {{ form.as_p }} </center> -->
{% for field in form %}
<div class="fieldWrapper">
{{ field.errors }}
<!-- {{ field.label_tag }} -->
<small><b>{{ field.html_name }}<p align="left"></b> {{ field }}</small> </p>
{% if field.help_text %}
<p class="help">{{ field.help_text|safe }}</p>
{% endif %}
</div>
{% endfor %}
</div>
<div class="wrapper">
&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp
<h2><button type="submit" class="save btn btn-success btn-lg">Confirm</button></h2>&nbsp&nbsp&nbsp
<h2><button type="submit" class="btn btn-secondary btn-lg" data-dismiss="modal">Cancel</button></h2>
</div>
</form>
</td>
</div>
</tr>
{% endfor %}
Since you are not overriding one of UpdateView attributes, template_name_suffix, template_name or get_templates_names(), default template name that your view would be looking is <model_name>_form.html. And you don't have that template

Categories

Resources