I am new to coding and especially new to working with Django. I want to build a small "forum" for me and the other students and it works pretty fine.
There is just one error I encounter over and over:
Exception Type: NoReverseMatch
Exception Value: Reverse for 'thread-create' with
arguments '('',)' not found. 1 pattern(s) tried: ['forum/(?P<pk>[0-9]+)/add/$']
I can work around it using functions instead of class based Views, but I doubt that's how it's supposed to be done.
I have the feeling I am missing something very important while working with class views.
I really would appreciate if someone could help me out :-)
It's the links that are not working:
{% url 'user-posts' thread.author.username %}
and more importantly:
{% url 'forum:thread-create' thread.id %}
What's also not working while using classes is:
{% for thread in thema.thread_set %} (works with the functions)
(I only want to see the threads that are bind to a certain thema. That also works pretty well with functions).
And you might also be asking why I don't just use the function based views:
I want to know what am I doing wrong
I want to be able to easy paginate my site.
Code:
# models.py
from django.db import models
from django.urls import reverse
from PIL import Image
from django.utils import timezone
from django.contrib.auth.models import User
class Thema(models.Model):
themengebiet = models.CharField(max_length=350)
beschreibung = models.TextField()
themen_logo = models.FileField(max_length=350, upload_to="logos", default='default.jpg')
erstellt_am = models.DateTimeField(default=timezone.now)
def __str__(self):
return self.themengebiet
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
img = Image.open(self.themen_logo.path)
if img.height > 300 or img.width > 300:
output_size = (300, 300)
img.thumbnail(output_size)
img.save(self.themen_logo.path)
class Thread(models.Model):
thema = models.ForeignKey(Thema, on_delete=models.CASCADE)
titel = models.CharField(max_length=350)
author = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True)
erstellt_am = models.DateTimeField(default=timezone.now)
thread_logo = models.ImageField(upload_to="logos", d efault='default.jpg')
def get_absolute_url(self):
return reverse('forum:thread-page', kwargs={'pk': self.thema.id})
def __str__(self):
return self.titel
class Posting(models.Model):
thread = models.ForeignKey(Thread, on_delete=models.CASCADE)
titel = models.CharField(max_length=350)
erstellt_am = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
inhalt = models.TextField()
def __str__(self):
return self.titel
views.py
from django.views import generic
from django.views.generic import CreateView, UpdateView, DeleteView, ListView
from .models import Thema, Thread, Posting
from django.shortcuts import render, get_object_or_404
from django.urls import reverse_lazy
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.auth.decorators import login_required
from django.http import Http404
from django.core.paginator import Paginator
class ThemenView(ListView):
template_name = 'forum/posts_original.html'
context_object_name = 'all_themen'
def get_queryset(self):
return Thema.objects.all()
class ThemaCreate(CreateView):
model = Thema
fields = ['themengebiet', 'beschreibung', 'themen_logo']
success_url = "/forum/"
class ThreadCreate(CreateView):
model = Thread
fields = ['thema', 'titel', 'erstellt_am']
success_url = reverse_lazy('forum:posts_original')
def get_object(self):
return Thread.objects.get(pk=self.kwargs['pk'])
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
class PostCreate(CreateView):
model = Posting
fields = ['thread', 'titel', 'inhalt', 'erstellt_am']
success_url = "/forum/"
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
class ThreadView(ListView):
model = Thread
context_object_name = 'threads'
template_name = 'forum/thread.html'
success_url = reverse_lazy('forum:posts_original')
def get_object(self):
return Thread.objects.get(pk=self.kwargs['pk'])
class PostView(ListView):
model = Posting
context_object_name = 'posts'
template_name = 'forum/posts.html'
urls.py
from django.urls import path
from . import views
app_name = 'forum'
urlpatterns = [
# /forum/
path('', views.ThemenView.as_view(), name='posts_original'),
# forum/id/
path('<int:pk>/', views.ThreadView.as_view(), name='thread-page'),
# forum/thread/add
#path('<int:pk>/add/', views.thread_create, name='thread-create'),
# forum/id//id
path('thread/<int:pk>/', views.PostView.as_view(), name='post-page'),
path('add/', views.ThemaCreate.as_view(), name='thema-create'),
path('<int:pk>/add/', views.ThreadCreate.as_view(), name='thread-create'),
path('thread/<int:pk>/add/', views.PostCreate.as_view(), name='post-create'),
]
'''
def thread(request, pk):
try:
thema = get_object_or_404(Thema, pk=pk)
except Thema.DoesNotExist:
raise Http404("Thema existitiert nicht")
return render(request, 'forum/thread.html', {'thema': thema})
def post(request, pk):
try:
thread = get_object_or_404(Thread, pk=pk)
except Thread.DoesNotExist:
raise Http404("Thema existitiert nicht!")
return render(request, 'forum/posts.html', {'thread': thread})
'''
{% extends "blog/base.html" %}
{{ threads }}
{% block content %}
Zurück zur Themenübersicht
{% for thread in threads %}
<article class="media content-section">
<img class="rounded-circle article-img" src= "{{ thread.thread_logo.url }}">
<div class="media-body">
<div class="article-metadata">
<a class="mr-2" href="{% url 'user-posts' thread.author.username %}">{{ thread.author }}</a>
<small class="text-muted">{{ thread.erstellt_am|date:"d. F Y" }}</small>
</div>
<h2><a class="article-title" href=" {% url 'forum:post-page' thread.id %}">{{ thread.titel }}</a></h2>
<p class="article-content">Thema: {{ thread.thema }}</p>
</div>
</article>
{% endfor %}
<form action="{% url 'forum:thread-create' thread.id %}" method="post" enctype="multipart/form-data" style="display: inline;">
{% csrf_token %}
Thread hinzufügen
</form>
{% endif %}
{% endblock content %}
Related
When I add a | slugify in the home.html I get this error if I don't add everything works fine.
Also when I enter a category, posts are not displayed in some categories, there is no post in this category is displayed. There are also critical errors constantly pop out, perhaps there is a bug somewhere or not the correct code, I still did not find the reason, I solve one second, an error pops out
models.py
from django.db import models
from django.contrib.auth.models import User
from django.urls import reverse
#from datetime import datetime, date
from django.utils import timezone
class Category(models.Model):
name=models.CharField(max_length=255)
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse('home')
class Post(models.Model):
title = models.CharField(max_length=200)
author = models.ForeignKey(User, on_delete=models.CASCADE)
body = models.TextField()
post_date = models.DateTimeField(auto_now_add=True)
category = models.CharField(max_length=200, default='разные')
def __str__(self):
return self.title + ' | ' + str(self.author)
def get_absolute_url(self):
return reverse('article_detail', args=[str(self.id)])
views.py
from django.shortcuts import render
from django.views.generic import ListView, DetailView, CreateView, UpdateView, DeleteView
from .models import Post, Category
from .forms import PostForm, EditForm
from django.urls import reverse_lazy
#def home(request):
# return render(request, 'home.html', {})
class HomeView(ListView):
model = Post
cats = Category.objects.all()
template_name = 'home.html'
ordering = ['-post_date']
def get_context_data(self, *args, **kwargs):
cat_menu = Category.objects.all()
context = super(HomeView,self).get_context_data(*args, **kwargs)
context["cat_menu"] = cat_menu
return context
def CategoryView(request, cats):
category_posts = Post.objects.filter (category = cats)
return render(request, 'categories.html', {'cats':cats.title(), 'category_posts':category_posts})
class ArticleDetailView(DetailView):
model = Post
template_name = 'post_detail.html'
class AddPostView(CreateView):
model = Post
form_class = PostForm
template_name= 'add_post.html'
#fields = '__all__'
class AddCategoryView(CreateView):
model = Category
template_name= 'add_category.html'
fields = '__all__'
class UpdatePostView(UpdateView):
model = Post
template_name = 'update_post.html'
form_class = EditForm
#fields = ['title', 'body']
class DeletePostView(DeleteView):
model = Post
template_name = 'delete_post.html'
success_url = reverse_lazy('home')
home.html
{% extends 'base.html' %}
{% block content %}
<h1>Articles</h1>
{% for post in object_list %}
<ul>
<li>
<h2><l1>{{ post.title }}</h2>
{{ post.category }}
| {{ post.author }}
{% if user.is_authenticated %}
|-<small>Редакт..)</small>
{% endif %}
<br/>{{ post.body|slice:":50"|safe }}
</l1>
</ul>
{% endfor %}
{% endblock %}
urls.py
from django.urls import path
from .views import HomeView, ArticleDetailView, AddPostView, UpdatePostView, DeletePostView, AddCategoryView, CategoryView
urlpatterns = [
path('', HomeView.as_view(), name='home'),
path('article/<int:pk>', ArticleDetailView.as_view(), name='article_detail'),
path('add_post/', AddPostView.as_view(), name='add_post'),
path('add_category/', AddCategoryView.as_view(), name='add_category'),
path('article/edit/<int:pk>', UpdatePostView.as_view(), name='update_post'),
path('article/<int:pk>/delete', DeletePostView.as_view(), name='delete_post'),
path('category/<str:cats>/', CategoryView, name='category'),
]
categories.py
{% extends 'base.html' %}
{% block content %}
{% if category_posts %}
<h1>{{cats}}</h1>
{% for post in category_posts %}
<ul>
<l1>{{ post.title }}
| {{ post.author }}
{% if user.is_authenticated %}
|-<small>Редакт..)</small>
{% endif %}
<br/>{{ post.body|slice:":50"|safe }}
</l1>
</ul>
{% endfor %}
{% else %}
<h1>So sorry</h1>
{% endif %}
{% endblock %}
Please help me on the map of my training and suggest a solution to my fatal errors
I'm trying to incorporate Select2 into my django form -- specifically ModelSelect2MultipleWidget -- so that the user can associate multiple event objects to another model (like CheckboxSelectMultiple). The associated models are:
from django.contrib.auth import get_user_model
from django.db import models
class F4Events(models.Model):
name = models.CharField(max_length=300)
handling_type = models.ManyToManyField(WaferHandlingType)
def __str__(self):
return self.name
class ToolPm(models.Model):
ceid = models.ForeignKey(CEID, on_delete=models.CASCADE)
name = models.CharField(max_length=250)
wafer_handling = models.BooleanField(default=True)
wafer_based = models.BooleanField(default=False)
frequency = models.FloatField(blank=True, null=True)
handling_type = models.ManyToManyField(WaferHandlingType, blank=True)
user_edited = models.BooleanField(default=False)
pm_f4_events = models.ManyToManyField('F4Events', blank=True)
def __str__(self):
return str(self.name) if self.name else ''
class Meta:
ordering = ('ceid', 'name')
My forms.py file is:
from django import forms
from .models import Entity, ToolPm, CEID, PDL, F4Events, WaferHandlingType
from django_select2 import forms as s2forms
class F4EventWidget(s2forms.ModelSelect2MultipleWidget):
search_fields = [
'name__icontains',
]
attrs = {'data-placeholder': 'Please Choose F4 Events'}
class PMForm(forms.ModelForm):
class Meta:
model = ToolPm
fields = ['wafer_handling', 'wafer_based', 'handling_type', 'pm_f4_events']
widgets = {'handling_type': forms.CheckboxSelectMultiple,
'pm_f4_events': F4EventWidget
}
my view.py is:
from datetime import datetime, timedelta
from django.db.models import Sum
from django.http import JsonResponse, HttpResponseRedirect
from django.http.response import HttpResponse
from django.shortcuts import render, get_object_or_404, redirect
from django.views import View
from django.views.generic import ListView
from django_filters.views import FilterView
from pages.filter import CeidFilter, PmRunDateFilter
from tools.forms import EntityForm, PMForm, CEIDForm, PDLAddForm
from tools.models import CEID, Entity, F4Events, ToolPm, WaferHandlingType, PmRunDate
from django.urls import reverse
class UserCeidPMUpdate(View):
template_name = 'tools/update_pm_attributes.html'
def get(self, request, username, pk, pm_id):
pm = ToolPm.objects.get(pk=pm_id)
form = PMForm(request.GET or None, instance=pm)
return render(request, self.template_name, {'form': form, 'pm': pm, })
def post(self, request, username, pk, pm_id):
pm = ToolPm.objects.get(pk=pm_id)
pm.user_edited = True
pm.save()
form = PMForm(request.POST or None, instance=pm)
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse('pm_view', kwargs={'username': username, 'pk': pm.ceid.id}))
return render(request, self.template_name, {'form': form, 'pm': pm, })
lastly, my .html file is:
{% extends 'base.html' %}
{% load crispy_forms_tags %}
{% block content %}
<form method="post">
<p>Process: {{ pm.ceid.process }}</p>
<p>CEID: {{ pm.ceid.ceid }}</p>
<p>Name: {{ pm.name }}</p>
<p>Frequency: {{ pm.frequency }}{% if pm.wafer_based %} wafers {% else %} days {% endif %}</p>
<p>Score: {{ pm.score }}</p>
{% csrf_token %}
{{ form }}
<input type="submit" class="btn btn-success" value="Update PM"><button type="button" class="btn btn-primary">Go Back</button>
</form>
{% endblock content %}
If I switch the pm_f4_events widget to a CheckboxSelectMultiple or a ModelSelect2Widget, the code works.
However, when I try to use a ModelSelect2MultipleWidget, the form continually tries to load but cannot and eventually just times out.
There are ~5000 items within the F4Events model, so that may have something to do with it. Any help to point me in the right direction would be greatly appreciated!
You can empty the pm_f4_events field's choices in the __init__ method:
class PMForm(forms.ModelForm):
class Meta:
model = ToolPm
fields = ['wafer_handling', 'wafer_based', 'handling_type', 'pm_f4_events']
widgets = {
'handling_type': forms.CheckboxSelectMultiple,
'pm_f4_events': s2forms.ModelSelect2MultipleWidget(
model=F4Events,
search_fields=["name__icontains",],
attrs = {'data-placeholder': 'Please Choose F4 Events'}
)
}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
choices_F4Events = []
pm_f4_events_field = self.fields["pm_f4_events"]
# selected values
selected_F4Events = self.data.getlist("pm_f4_events") or self.initial.get("pm_f4_events")
if selected_F4Events:
# check of selected values not object
if not isinstance(selected_F4Events[0], F4Events):
selected_F4Events = pm_f4_events_field.queryset.filter(pk__in=selected_F4Events)
choices_F4Events = [(item.pk, item.name) for item in selected_F4Events]
# assign selected values or empty list
pm_f4_events_field.choices = choices_F4Events
Has been tested on my server, works well.
Page not found (404)
Request Method: GET
Request URL: http://127.0.0.1:8000/detail/python
Raised by: main.views.blog_detail
No Blog matches the given query.
It says that the error is raised by "main.views.blog_detail", What am I missing or what could be the erroe?
This is my urls.py:
from django.urls import path
from . import views
app_name = 'main'
urlpatterns = [
path('' , views.test , name='test_view'),
path('blog/', views.blog_list, name='blog_list'),
path('<slug:category_slug>' , views.blog_list , name='blog_list'),
path('detail/<slug:blog_slug>' , views.blog_detail , name='blog_detail'),
]
This is my views.py file:
from django.shortcuts import render
from django.http import HttpResponse
from .models import Blog,BlogCategory
from django.shortcuts import get_object_or_404
# Create your views here.
def test(request):
template = 'base.html'
# context = {'product_list':productlist, 'category_list':categorylist, 'category':category}
return render(request, template)
def blog_list(request, category_slug=None):
category = None
bloglist = BlogCategory.objects.all()
if category_slug:
category = get_object_or_404(BlogCategory,slug=category_slug)
bloglist = bloglist.filter(category=category)
template = 'main/blog.html'
context = {'blog_list':bloglist}
return render(request, template, context)
def blog_detail(request, blog_slug):
print(blog_slug)
blogdetail = get_object_or_404(Blog, slug=blog_slug)
template = 'Main/blog_details.html'
context = {'blog_detail':blogdetail}
return render(request, template, context)
This is my models.py file:
from django.db import models
from datetime import datetime
from django.utils.text import slugify
# Create your models here.
class Blog(models.Model):
blog_title = models.CharField(max_length=200)
blog_content = models.TextField()
blog_published = models.DateTimeField('date published', default=datetime.now)
blog_category = models.ForeignKey('BlogCategory', on_delete=models.SET_NULL, null=True)
slug = models.SlugField(blank=True,null=True)
def save(self, *args, **kwargs):
if not self.slug and self.blog_title:
self.slug = slugify(self.blog_title)
super(Blog,self).save(*args, **kwargs)
def __str__(self):
return self.blog_title
class BlogCategory(models.Model):
blog_category = models.CharField(max_length=200)
blog_summary = models.CharField(max_length=200)
slug = models.SlugField(blank=True,null=True)
def save(self, *args, **kwargs):
if not self.slug and self.blog_category:
self.slug = slugify(self.blog_category)
super(BlogCategory,self).save(*args, **kwargs)
class Meta:
# Gives the proper plural name for admin
verbose_name_plural = "Categories"
def __str__(self):
return self.blog_category
This is my bloglist.html:
{% extends 'base.html' %}
{% block content %}
<div class="row">
{% for bl in blog_list %}
<div class="col s12 m6">
<a href="{% url 'main:blog_detail' bl.slug %}">
<div class="card hoverable">
<div class="card-content">
<span class="card-title">{{bl.blog_category}}</span>
<p style="font-size:70%">Published {{bl.blog_published}}</p>
<p>{{bl.blog_summary}}</p>
</div>
</div>
</div>
{% endfor %}
{% endblock %}
This is my blogdetails.html:
{% extends 'base.html' %}
{% block content %}
<div class="row">
<div class="col s12, m8, l8">
<h3>{{blog_detail.blog_title}}</h3>
<p style="font-size:70%">Published {{blog_detail.blog_published}}</p>
{{blog_detail.blog_content|safe}}
</div>
</div>
{% endblock %}
You have to just change a name of 'Main' to 'main' because your blog_details.html page was in main directory. And also check name of blog_details.html directory properly than integrate it properly with perfect name.
template = 'main/blog_details.html'
I'm trying to create a Class-based Detail View of an inventory app.
Problem is, when I search for the specific item I get back the following error from the browser:
Page not found (404)
Request Method: GET
Request URL: http://127.0.0.1:8000/equipment/57/
Raised by: equipment.views.EquipmentType_DetailView
No equipment item found matching the query
You're seeing this error because you have DEBUG = True in your Django settings file. Change that to False, and Django will display a standard 404 page.
The strange thing is that if try directly "http://127.0.0.1:8000/equipment/57/update/", the app works perfectly and I get redirected to the update page of the corresponding object.
But if I search "http://127.0.0.1:8000/equipment/57", I get the error
I'm struggling to understand this.
Here is my in app urls.py:
from django.urls import path
from .views import (
EquipmentType_ListView,
EquipmentType_CreateView,
EquipmentType_UpdateView,
EquipmentType_DetailView,)
urlpatterns=[
path('', EquipmentType_ListView.as_view(), name='equipmentType-home'),
path('<int:pk>/', EquipmentType_DetailView.as_view(), name='equipmentType-detail'),
path('new/', EquipmentType_CreateView.as_view(), name='equipmentType-create'),
path('<int:pk>/update/', EquipmentType_UpdateView.as_view(), name='equipmentType-update'),
]
my views.py:
from django.shortcuts import render, redirect, get_object_or_404
from django.contrib.auth.models import User
from django.views.generic import (
ListView,
DetailView,
CreateView,
UpdateView,
DeleteView
)
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from .models import EquipmentType, EquipmentItem
from django.contrib.messages.views import SuccessMessageMixin
# Create your views here.
class EquipmentType_ListView(LoginRequiredMixin, ListView):
model = EquipmentType
template_name = 'equipment/equipment_type.html' # default = <app>/<model>_<viewtype>.html
context_object_name = 'obj_list' #default = object_list
#ordering = ['date_posted'] #oldest to newest
#ordering = ['-date_posted'] #newest to oldest
ordering = ['type']
#paginate_by = 5
class EquipmentType_DetailView(LoginRequiredMixin, DetailView):
model = EquipmentItem
template_name = 'equipment/equipmenttype_detail.html'
class EquipmentType_CreateView(LoginRequiredMixin, SuccessMessageMixin, CreateView):
model = EquipmentType
template_name='equipment/equipmenttype_form.html'
fields = ['type', 'image']
success_message = "%(type)s creati"
def get_success_message(self, cleaned_data):
return self.success_message % dict(
cleaned_data,
type=self.object.type,
)
class EquipmentType_UpdateView(LoginRequiredMixin, SuccessMessageMixin, UpdateView):
model = EquipmentType
fields = ['type', 'image']
success_message = "%(type)s modificati"
def get_success_message(self, cleaned_data):
return self.success_message % dict(
cleaned_data,
type=self.object.type,
)
def test_func(self):
post = self.get_object()
if self.request.user == post.author:
return True
return False
here is my in app detail template:
{% extends 'equipment/0_base.html'%}
{% block content%}
<article class="media content-section">
<img class='rounded-circle article-img' src="{{ object.image.url }}" alt="">
<div class="media-body">
<div class="article-metadata">
<a class="mr-2" href="#">{{ object.type }}</a>
<!-- url 'user-posts' object.author.username %} -->
<small class="text-muted">{{ object.date_posted}}</small>
<!-- |date:'F d, Y' -->
<div class="">
<a href="{% url 'equipmentType-update' object.id %}" class='btn btn-warning btn-sm mt-1 mb-1'>Update</a>
</div>
</div>
</div>
</article>
{% endblock %}
and my model:
from django.db import models
from django.utils import timezone
from django.urls import reverse
from django.contrib.auth.models import User
from PIL import Image
# Create your models here.
class EquipmentType(models.Model):
type = models.CharField(max_length=100, unique=True)
date_posted = models.DateTimeField(auto_now_add=True)
# auto_now = timezone.now
image =models.ImageField(default='default.jpeg', upload_to='equipment/equipment_type')
def __str__(self):
return str(self.id) + ' - ' + self.type
def get_absolute_url(self):
return reverse('equipmentType-home')
# , kwargs={'pk': self.pk}
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
img = Image.open(self.image.path)
if img.height > 300 or img.width > 300:
output_size = (300, 300)
img.thumbnail(output_size)
img.save(self.image.path)
I have done a lot of experiments and very much feel out of my depth. I can't get existing comments to appear (I added some via the admin page) or the comment form. I have tried to Google the problem and rearrange my code. Unfortunately I don't have the foggiest idea what is causing the problem. So I don't know if any of my experiments were remotely along the right lines.
After posting the original question I tried using dispatch() in my code. I got error messages I tried to Google but I was just trying to apply band aid on top of band aid.
post_detail.html
{% extends "blog/base.html" %}
{% block content %}
<article class="media content-section">
<img class="rounded-circle article-img" src="{{ object.author.profile.image.url }}">
<div class="media-body">
<div class="article-metadata">
<a class="mr-2" href="#">{{ object.author }}</a>
<small class="text-muted">{{ object.date_posted|date:"F d, Y" }}</small>
{% if object.author == user %}
<div>
<a class="btn btn-secondary btn-sm mt-1 mb-1" href="{% url 'post-update' object.id %}">Update</a>
<a class="btn btn-danger btn-sm mt-1 mb-1" href="{% url 'post-delete' object.id %}">Delete</a>
</div>
{% endif %}
</div>
<h2 class="article-title">{{ object.title }}</h2>
<p class="article-content">{{ object.content }}</p>
</div>
</article>
<article class="media content-section">
<!-- comments -->
<h3>{{ comments.count }} Comments</h3>
{% for comment in comments %}
<div class="media-body">
<a class="mr-2" href="#">{{ comment.name }}</a>
<small class="text-muted">{{ comment.created_on|date:"F d, Y" }}</small>
</div>
<h2 class="article-title">{{ object.title }}</h2>
<p class="article-content">{{ comment.body | linebreaks }}</p>
{% endfor %}
</article>
{% endblock content %}
views.py
from django.shortcuts import render
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.views.generic import (
ListView,
DetailView,
CreateView,
UpdateView,
DeleteView
)
from .models import Post
from .forms import CommentForm
from django.shortcuts import render, get_object_or_404
def home(request):
context = {
'posts': Post.objects.all()
}
return render(request, 'blog/home.html', context)
class PostListView(ListView):
model = Post
template_name = 'blog/home.html' # <app>/<model>_<viewtype>.html
context_object_name = 'posts'
ordering = ['-date_posted']
#class PostDetailView(DetailView):
# model = Post
class PostDetailView(DetailView):
model = Post
def dispatch():
post = get_object_or_404(Post)
comments = post.comments.filter(active=True, slug=slug)
new_comment = None
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()
return render(request, post_detail.html, {'post': post,
'comments': comments,
'new_comment': new_comment,
'comment_form': comment_form})
class PostCreateView(LoginRequiredMixin, CreateView):
model = Post
fields = ['title', 'content']
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
class PostUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
model = Post
fields = ['title', 'content']
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
def test_func(self):
post = self.get_object()
if self.request.user == post.author:
return True
return False
class PostDeleteView(LoginRequiredMixin, UserPassesTestMixin, DeleteView):
model = Post
success_url = '/'
def test_func(self):
post = self.get_object()
if self.request.user == post.author:
return True
return False
def about(request):
return render(request, 'blog/about.html')
forms.py
from .models import Comment
from django import forms
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = ('name', 'email', 'body')
models.py
from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User
from django.urls import reverse
# Create your models here.
class Post(models.Model):
title = models.CharField(max_length=100)
content = models.TextField()
date_posted = models.DateTimeField(default=timezone.now())
author = models.ForeignKey(User, on_delete=models.CASCADE)
url= models.SlugField(max_length=500, unique=True, blank=True)
def save(self, *args, **kwargs):
self.url= slugify(self.title)
super().save(*args, **kwargs)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('article_detail', kwargs={'slug': self.slug})
class Comment(models.Model):
post = models.ForeignKey(Post,on_delete=models.CASCADE,related_name='comments')
name = models.CharField(max_length=80)
email = models.EmailField()
body = models.TextField()
created_on = models.DateTimeField(auto_now_add=True)
active = models.BooleanField(default=False)
class Meta:
ordering = ['created_on']
def __str__(self):
return 'Comment {} by {}'.format(self.body, self.name)
urls.py (in Blog app)
from django.urls import path
from .views import (
PostListView,
PostDetailView,
PostCreateView,
PostUpdateView,
PostDeleteView
)
from. import views
from django.views.generic import TemplateView
urlpatterns = [
path('', PostListView.as_view(), name='blog-home'),
path('post/<int:pk>/', PostDetailView.as_view(), name='post-detail'),
path('post/new/', PostCreateView.as_view(), name='post-create'),
path('post/<int:pk>/update/', PostUpdateView.as_view(), name='post-update'),
path('post/<int:pk>/delete/', PostDeleteView.as_view(), name='post-delete'),
path('about/', views.about, name='blog-about'),
path('facebook/',TemplateView.as_view(template_name='blog/index.html'), name="facebook")
]
signals.py (in Users app)
from django.db.models.signals import post_save
from django.contrib.auth.models import User
from django.dispatch import receiver
from .models import Profile
#reciever(post_save, sender=User)
def create_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
#reciever(post_save, sender=User)
def save_profile(sender, instance, created, **kwargs):
instance.profile.save()
correct your indentation of the code
class PostDetailView(DetailView):
model = Post
def post_detail(request, slug):
post = get_object_or_404(Post, slug=slug)
comments = post.comments.filter(active=True)
new_comment = None
# Comment posted
if request.method == 'POST':
comment_form = CommentForm(data=request.POST)
if comment_form.is_valid():
# Create Comment object but don't save to database yet
new_comment = comment_form.save(commit=False)
# Assign the current post to the comment
new_comment.post = post
# Save the comment to the database
new_comment.save()
else:
comment_form = CommentForm()
return render(request, template_name, {'post': post,
'comments': comments,
'new_comment': new_comment,
'comment_form': comment_form})