How can i do it so the user after editing the post doesn't get redirected to homepage but to the detail view of the post they just edited
My views.py
from . models import Post
from django.contrib.auth.decorators import login_required
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import DeleteView, UpdateView, CreateView
from django.urls import reverse_lazy
def home(request):
posts = Post.objects.all()
return render(request, 'pages/index.html', {'posts':posts})
def detail(request, slug):
post = Post.objects.get(slug=slug)
return render(request, 'pages/detail.html', {'post':post})
class edit(LoginRequiredMixin, UpdateView):
model = Post
template_name = 'pages/edit.html'
fields = ['title','image','body']
success_url = reverse_lazy('pages:homepage')
def dispatch(self, request, *args, **kwargs):
handler = super().dispatch(request, *args, **kwargs)
user = request.user
post = self.get_object()
if post.author != user:
raise PermissionDenied
return handler
my models.py
from django.db import models
from django.contrib.auth.models import User
from django.urls import reverse
from django.db.models.signals import pre_save
from A_Tech_Blog.utils import unique_slug_generator
class Post(models.Model):
title = models.CharField(max_length=300)
slug = models.SlugField(blank=True, null=True, max_length=300)
image = models.ImageField(upload_to='post_images', default='default.jpg')
time_created = models.DateTimeField(auto_now_add=True)
views = models.IntegerField(default=0)
body = models.TextField()
author = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
return f'{self.title} -- Author={str(self.author)}'
class Meta:
ordering = ['-time_created']
verbose_name_plural = 'Posts'
def get_absolute_url(self):
return reverse('pages:detail', args=(self.slug))
def slug_generator(sender, instance, *args, **kwargs):
if not instance.slug:
instance.slug = unique_slug_generator(instance)
pre_save.connect(slug_generator, sender=Post)
I want to be able to edit the post then get directed to the detail view of the post instead of being redirected to the web app homepage
You can override the get_success_url() method in your view
Something like this should work
class edit(LoginRequiredMixin, UpdateView):
...
# success_url = reverse_lazy('pages:homepage')
def get_success_url(self):
return reverse('pages:detail', args=[self.slug])
Related
I’m trying to create a category for each post.
I made another class with the same models.py and in the same class Post I made a category = models.ForeignKey
But it keeps showing me this error when I run the server:
(no such column: Blog_post.category_id)
Ps: I did run the makemigrations and the migrate command.
The tutorial I followed just added the model as it is in models.py but should I also make a function for the views.py or its just a model problem ?
models.py
class Category(models.Model):
name = models.CharField(max_length=100)
def __str__(self):
return self.name
class Post(models.Model):
category = models.ForeignKey(Category, on_delete=models.CASCADE, default="Some random thing")
werkstoffnummer = models.CharField(max_length=100)
def __str__(self):
return self.werkstoffnummer
def get_absolute_url(self):
return reverse("post-detail", kwargs={"pk": self.pk})
views.py
from random import choices
from unicodedata import category
from django import forms
from django.shortcuts import get_object_or_404, render, get_list_or_404, HttpResponse
from django.conf import settings
from django.http import HttpResponse, Http404
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.contrib.auth.models import User
from django.views.generic import (ListView, DetailView, CreateView, UpdateView, DeleteView)
from .models import Post, Category
from django.db.models import Q
import pandas as pd
import json
import os
def home(request):
context = {"posts": Post.objects.all()}
return render(request, "Blog/home.html", context)
def werkstoffdaten(request):
context = {"posts": Post.objects.all()}
return render(request, "Blog/werkstoffdaten.html", context)
class PostListView(ListView):
model = Post
template_name = "Blog/werkstoffdaten.html" # <app>/<model>_<viewtype>.html
context_object_name = "posts"
ordering = \["-date_posted"\]
paginate_by = 100
class PostListView(ListView):
model = Post
template_name = "Blog/home.html" # <app>/<model>_<viewtype>.html
context_object_name = "posts"
ordering = \["-date_posted"\]
paginate_by = 100
class UserPostListView(ListView):
model = Post
template_name = "Blog/user_posts.html" # <app>/<model>_<viewtype>.html
context_object_name = "posts"
paginate_by = 100
def get_queryset(self):
user = get_object_or_404(User, username=self.kwargs.get("username"))
return Post.objects.filter(author=user).order_by("-date_posted")
class PostDetailView(DetailView):
model = Post
class PostCreateView(LoginRequiredMixin, CreateView):
model = Post
fields = \[
"werkstoffnummer", "werkstoffbezeichnung",
\]
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
class PostUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
model = Post
fields = \[
"werkstoffnummer", "werkstoffbezeichnung",
\]
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 Periodic_Table(request):
return render(request, "Blog/Periodic_Table.html")
def user_manual(request):
return render(request, "Blog/user_manual.html")
def about(request):
return render(request, "Blog/about.html", {"title": "About"})
def search_post(request):
if request.method == "POST":
searched = request.POST.get("searched")
posts = Post.objects.filter(
Q(werkstoffnummer=searched) | Q(werkstoffbezeichnung=searched) | Q(gruppe=searched)
)
return render(
request, "Blog/search_post.html", {"searched": searched, "posts": posts}
)
else:
return render(request, "Blog/search_post.html", {})
def download(request, path):
file_path = os.path.join(settings.MEDIA_ROOT, path)
if os.path.exists(file_path):
with open(file_path, 'rb') as fh:
response = HttpResponse(fh.read(), content_type="application/vnd.ms-excel")
response\['Content-Disposition'\] = 'inline; filename=' + os.path.basename(file_path)
return response
raise Http404
OperationalError at /
https://imgur.com/a/lVDedeq
Delete default="Some random thing" in your category field, default value for foreign key of your Category model, must be a private key (pk (aka id (type == integer))), but not the string.
If you just delete this default value, it will work, or you can put default=1 as first object of your Category models would be default for your new Post objects
class Post(models.Model):
category = models.ForeignKey(Category, on_delete=models.CASCADE)
or
class Post(models.Model):
category = models.ForeignKey(Category, on_delete=models.CASCADE, default=1)
I am new on this field and i am currently learning django and i come up with this problem. I am working on a project which is a social clone project and this project you can only post when you are in a group and i've encountered this problem when i post. The first post is working fine but the second post i get this error message called IntegrityError i've tried to delete my migrations and database and migrate and makemigrations again but does not fix the problem and now i am stuck and i hope someone will help me. This is the actual error
Posts Models
##########################
## POSTS MODELS.PY FILE ##
##########################
from django.contrib.auth import get_user_model
from django.db import models
from groups.models import Group
from misaka import html
from django.urls import reverse
from django.conf import settings
User = get_user_model()
class Post(models.Model):
user = models.ForeignKey(User, related_name='posts', on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now=True)
message = models.TextField()
message_html = models.TextField(editable=False)
group = models.ForeignKey(Group, related_name='posts', null=True, blank=True, on_delete=models.CASCADE)
def __str__(self):
return self.message
def save(self, *args, **kwargs):
self.message_html = html(self.message)
super().save(*args, **kwargs)
def get_absolute_url(self):
return reverse(
'posts:single',
kwargs={
'username': self.user.username,
'pk': self.pk
}
)
class Meta:
ordering = ['-created_at']
unique_together = ['user', 'group']
Posts Views.py
#########################
## POSTS VIEWS.PY FILE ##
#########################
from django.contrib.auth import get_user_model
from braces.views import SelectRelatedMixin
from django.views import generic
from posts import models, forms
from django.http import Http404
from django.contrib.auth.mixins import LoginRequiredMixin
from django.urls import reverse_lazy
from django.contrib import messages
User = get_user_model()
class PostList(SelectRelatedMixin, generic.ListView):
model = models.Post
select_related = ('user', 'group')
class UserPost(generic.ListView):
model = models.Post
template_name = 'posts/user_post_list.html'
def get_queryset(self):
try:
self.post_user = User.objects.prefetch_related('posts').get(
username__iexact=self.kwargs.get('username')
)
except User.DoesNotExist:
raise Http404
else:
return self.post_user.posts.all()
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['post_user'] = self.post_user
return context
class PostDetail(SelectRelatedMixin, generic.DetailView):
model = models.Post
select_related = ('user', 'group')
def get_queryset(self):
queryset = super().get_queryset()
return queryset.filter(
user__username__iexact=self.kwargs.get('username')
)
class CreatePost(LoginRequiredMixin, SelectRelatedMixin, generic.CreateView):
model = models.Post
fields = ('message', 'group')
def form_valid(self, form):
self.object = form.save(commit=False)
self.object.user = self.request.user
self.object.save()
return super().form_valid(form)
class DeletePost(LoginRequiredMixin, SelectRelatedMixin, generic.DeleteView):
model = models.Post
select_related = ('user', 'group')
success_url = reverse_lazy('posts:all')
def get_queryset(self):
queryset = super().get_queryset()
return queryset.filter(user_id=self.request.user.id)
def delete(self, *args, **kwargs):
messages.success(self.request, ('Post Delete'))
return super().delete(*args, **kwargs)
Groups Models.py
##########################
## GROUPS VIEWS.PY FILE ##
##########################
from django.contrib.auth import get_user_model
from django import template
from django.db import models
from django.utils.text import slugify
from misaka import html
from django.urls import reverse
from django.conf import settings
User = get_user_model()
register = template.Library()
class Group(models.Model):
name = models.CharField(max_length=255, unique=True)
slug = models.SlugField(allow_unicode=True, unique=True)
description = models.TextField(blank=True, default='')
description_html = models.TextField(editable=False, blank=True, default='')
members = models.ManyToManyField(User, through='GroupMember')
def __str__(self):
return self.name
def save(self, *args, **kwargs):
self.slug = slugify(self.name)
self.description_html = html(self.description)
super().save(*args, **kwargs)
def get_absolute_url(self):
return reverse('groups:single', kwargs={'slug': self.slug})
class Meta:
ordering = ['name']
class GroupMember(models.Model):
group = models.ForeignKey(Group, related_name='memberships', on_delete=models.CASCADE)
user = models.ForeignKey(User, related_name='user_groups', on_delete=models.CASCADE)
def __str__(self):
return self.user.username
class Meta:
unique_together = ('group', 'user')
Groups Views.py
[![##########################
## GROUPS VIEWS.PY FILE ##
##########################
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views import generic
from groups.models import Group, GroupMember
from django.urls import reverse
from django.shortcuts import get_object_or_404
from django.db import IntegrityError
from django.contrib import messages
from groups import models
class CreateGroup(LoginRequiredMixin, generic.CreateView):
model = Group
fields = ('name', 'description')
class SingleGroup(generic.DetailView):
model = Group
class ListGroups(generic.ListView):
model = Group
class JoinGroup(LoginRequiredMixin, generic.RedirectView):
def get_redirect_url(self, *args, **kwargs):
return reverse('groups:single', kwargs={'slug': self.kwargs.get('slug')})
def get(self, request, *args, **kwargs):
group = get_object_or_404(Group, slug=self.kwargs.get('slug'))
try:
GroupMember.objects.create(user=self.request.user, group=group)
except IntegrityError:
messages.warning(self.request, (f'Warning, Already A Member Of {group.name}.'))
else:
messages.success(self.request, (f'You Are Now A Member Of {group.name} Group.'))
return super().get(request, *args, **kwargs)
class LeaveGroup(LoginRequiredMixin, generic.RedirectView):
def get_redirect_url(self, *args, **kwargs):
return reverse('groups:single', kwargs={'slug': self.kwargs.get('slug')})
def get(self, request, *args, **kwargs):
try:
membership = models.GroupMember.objects.filter(
user=self.request.user,
group__slug=self.kwargs.get('slug')
).get()
except models.GroupMember.DoesNotExist:
messages.warning(self.request, ("You Can't Leave This Group Because You Aren't In It."))
else:
membership.delete()
messages.success(self.request, ('You Have Successfully Left This Group.'))
return super().get(request, *args, **kwargs)
Remove unique_together from your Post model. It means that only one Post object can have that particular user and model combination, that is why you are getting the integrity error.
The error which you are getting is all about the unique constraint.
unique_together = ['user', 'group']
Since you have defined in your model the unique_together attribute, you need to have unique rows of the combination for user and group. One user can post only once in a group and you are trying to post in the same group by the same user, that's why you are getting a unique constraint failed error.
I have a django form which takes a paramater from the view to initialize the MultipleChoiceField based on the user instance.
The form is working fine when loading the template.
when i submit the form the init method in the form raising an error.
My Model models.py
from django.db import models
from django.contrib.auth.models import User
class Group(models.Model):
group_name = models.CharField('Group name', max_length=50)
def __str__(self):
return self.group_name
class GroupMembers(models.Model):
group_name = models.ManyToManyField(Group)
members = models.ForeignKey(User, on_delete=models.CASCADE)
class Transactions(models.Model):
bill_type = models.CharField('Bill type',max_length=200)
added_by = models.ForeignKey(GroupMembers, on_delete=models.CASCADE)
added_to = models.ForeignKey(Group, on_delete=models.CASCADE)
purchase_date = models.DateField(auto_now=True)
share_with = models.CharField('Share among',max_length=250)
amount = models.IntegerField(default=0)
def __str__(self):
return self.bill_type
forms forms.py
from django import forms
from .models import Transactions, GroupMembers
class Bill_CreateForm(forms.ModelForm):
def __init__(self, user_list, *args, **kwargs):
super(Bill_CreateForm, self).__init__(*args, **kwargs)
self.fields['share_with'] = forms.MultipleChoiceField(widget=forms.CheckboxSelectMultiple,choices=tuple([(name, name.members) for name in user_list]))
class Meta:
model = Transactions
fields = (
'bill_type',
'amount',
'added_by',
'added_to',
'share_with',
)
** RESOLVED MY ISSUE WITH THE HELP OF #Alasdair "
EDITED SOLUTION
views views.py
from django.shortcuts import render, redirect
from django.contrib.auth.models import User
from .models import Transactions, Group, GroupMembers
from .forms import Bill_CreateForm
from django.http import HttpResponse, HttpResponseRedirect
def add_bills_home(request, id=None):
user = User.objects.get(pk=id)
grpname = Group.objects.filter(groupmembers__members=user)
gm = GroupMembers.objects.filter(group_name__group_name=grpname[0])
users_list = [i for i in gm]
if request.method == 'POST':
form = Bill_CreateForm(users_list, request.POST)
if form.is_valid():
print(form.cleaned_data['share_with'])
form.save()
form = Bill_CreateForm(users_list)
return render(request, 'bills/create_bill.html', {'form':form})
else:
form = Bill_CreateForm(users_list)
return render(request, 'bills/create_bill.html', {'form':form})
The error is
After submiting the form with data
the request.POST method returning
below data
i don't know if the request.POST method re-initializes the form with the filled data and pass it to the init method in the form.py.
Please help me with this
i'm trying to restrict users to view only the todos they have created using the dispatch method but i tried te below approach but still i'm seeing all todos appear under a user that did not create them
custom user model
from django.db import models
from django.contrib.auth.models import AbstractUser
# Create your models here.
class CustomUser(AbstractUser):
profession = models.CharField(null=True, blank=True, max_length=30)
todo model
from django.db import models
from django.contrib.auth import get_user_model
from django.urls import reverse
# Create your models here.
class Todo(models.Model):
title = models.CharField(max_length=120)
description = models.TextField(max_length=320)
to_be_done = models.DateTimeField(null=False)
date_posted = models.DateTimeField(auto_now_add=True)
user = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('todo_detail', args=[str(self.id)])
listview for todos
class TodoListView(LoginRequiredMixin, ListView):
model = Todo
template_name = 'todo_list.html'
login_url = 'login'
def dispatch(self, request, *args, **kwargs):
objects = self.objects.filter(user=self.request.user)
for obj in objects:
if obj.user != self.request.user:
raise PermissionDenied
return super().dispatch(request, *args, **kwargs)
any ideas on how i can adjust to implement above said task
Try something like this:
class TodoListView(LoginRequiredMixin, ListView):
model = Todo
def get_queryset(self):
qs = Todo.objects.filter(user=self.request.user)
return qs
I'm creating a blog post right now and I'm new at Django. I have an avatar picture in another app(registration) and I'm trying to import and associate correctly to another app (pages). In other words, I need to recover, in the HTML, the exact avatar picture from the user who creates a post. Thanks!
models.py (registration)
from django.db import models
from django.contrib.auth.models import User
from django.dispatch import receiver
from django.db.models.signals import post_save
def custom_upload_to(instance, filename):
old_instance = Profile.objects.get(pk=instance.pk)
old_instance.avatar.delete()
return 'profiles/' + filename
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
avatar = models.ImageField(upload_to=custom_upload_to, null=True, blank=True)
bio = models.TextField(null=True, blank=True)
link = models.URLField(max_length=200, null=True, blank=True)
class Meta:
ordering = ['user__username']
#receiver(post_save, sender=User)
def ensure_profile_exists(sender, instance, **kwargs):
if kwargs.get('created', False):
Profile.objects.get_or_create(user=instance)
models.py (pages)
from django.db import models
from ckeditor.fields import RichTextField
from django.contrib.auth.models import User
from registration.models import Profile
class Page(models.Model):
title = models.CharField(verbose_name="Título", max_length=200) # Titulo
author = models.ForeignKey('auth.User', verbose_name="autor", on_delete=models.CASCADE, null = True)
content = RichTextField(verbose_name="Contenido") # Contenido
order = models.SmallIntegerField(verbose_name="Orden", default=0) # Orden de publicacion
created = models.DateTimeField(auto_now_add=True, verbose_name="Fecha de creación") # Fecha de creacion
updated = models.DateTimeField(auto_now=True, verbose_name="Fecha de edición") # Fecha de actualizacion
class Meta:
verbose_name = "página"
verbose_name_plural = "páginas"
ordering = ['order', 'title']
def __str__(self):
return self.title
views.py (pages)
from .models import Page
from django.views.generic.list import ListView
from django.views.generic.detail import DetailView
from django.views.generic.edit import CreateView
from django.views.generic.edit import UpdateView
from django.views.generic.edit import DeleteView
from django.urls import reverse, reverse_lazy
from .forms import PageForm
from django.shortcuts import redirect
from django.contrib.admin.views.decorators import staff_member_required
from registration.models import Profile
#Decoradores
from django.utils.decorators import method_decorator
from django.contrib.auth.decorators import login_required
# Create your views here.
class StaffRequiredMixin(object):
#method_decorator(staff_member_required)
def dispatch(self, request, *args, **kwargs):
return super(StaffRequiredMixin, self).dispatch(request, *args, **kwargs)
#method_decorator(login_required, name="dispatch")
class PageListView(ListView):
model = Page
#method_decorator(login_required, name="dispatch")
class PageDetailView(DetailView):
model = Page
# CRUD:
#method_decorator(staff_member_required, name='dispatch')
class PageCreate(CreateView):
model = Page
form_class = PageForm
success_url = reverse_lazy('pages:pages')
def form_valid(self, form):
self.post = form.save(commit=False)
self.post.author = self.request.user
self.post.save()
return super(PageCreate, self).form_valid(form)
#method_decorator(staff_member_required, name='dispatch')
class PageUpdate(UpdateView):
model = Page
form_class = PageForm
template_name_suffix = '_update_form'
def get_success_url(self):
return reverse_lazy('pages:update', args=[self.object.id]) + '?ok'
#method_decorator(staff_member_required, name='dispatch')
class PageDelete(DeleteView):
model = Page
success_url = reverse_lazy('pages:pages')
You will probably want to provide the data using get_context_data() in the PageListView or PageDetailView. Something like:
class PageDetailView(DetailView):
model = Page
def get_context_data(**kwargs):
context = super().get_context_data(**kwargs)
# Profile image has a url property, so in the template {{ profile_image.url }}
profile_image = self.object.author.user.profile.avatar
context['profile_image'] = profile_image
return context
Take care: An error can be raised if author.user.profile does not exist. You can test for the relationship with hasattr(author.user, "profile").