I make my own group permission page self with ListView to show Django Group list with a link to DetailView with pk and then give the change link to change the permissions with UpdateView.
I want to make the success_url of UpdateView to DetailView with pk, how to do this.
my code like:
views.py
class GroupCreation(PermissionRequiredMixin, CreateView):
permission_required = 'add_group'
model = Group
form_class = GroupCreateModelForm
success_url = reverse_lazy('account:group_list')
template_name = 'accounts/groups/group_creation.html'
class GroupsListView(PermissionRequiredMixin, ListView):
permission_required = 'view_group'
allow_empty = True
model = Group
ordering = 'name'
template_name = 'accounts/groups/groups_list.html'
form = GroupCreateModelForm
extra_context = {'form': form, }
class GroupDetailView(PermissionRequiredMixin, DetailView):
permission_required = 'view_group'
model = Group
template_name = 'accounts/groups/group_detail.html'
class GroupUpdateView(PermissionRequiredMixin, UpdateView):
permission_required = 'change_group'
model = Group
fields = ('permissions',)
template_name = 'accounts/groups/group_update.html'
success_url = reverse_lazy('account:group_detail')
urls.py
path('groups/', views.GroupsListView.as_view(), name='group_list'),
path('groups/<int:pk>/', views.GroupDetailView.as_view(), name='group_detail'),
path('groups/<int:pk>/change/', views.GroupUpdateView.as_view(), name='group_change'),
path('groups/create/', views.GroupCreation.as_view(), name='group_creation'),
You can use the get_success_url method in your UpdateView instead of success_url attribute; This way you can access the edited object's pk:
def get_success_url(self):
return reverse_lazy('account:group_detail', kwargs={'pk': self.object.pk})
Related
I have Django in Which there is app called Listing and it's model as follows but CreateView and UpdateView are not woking for model.
I am also using mixins but I have implemented Custom User , so is that cuases a problem?
getting error
in get_form return form_class(**self.get_form_kwargs())
TypeError: 'ListingForm' object is not callable
Any other user is updating listing of others, UserPassesTestMixin not working
import uuid
from django.db import models
from django.urls import reverse
from django.contrib.auth import get_user_model
User = get_user_model()
class Listing(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4)
owner = models.ForeignKey(User, on_delete=models.CASCADE)
...other fields
CreateView
class ListingCreateView(LoginRequiredMixin, CreateView):
model = Listing
form_class = ListingForm()
def form_valid(self, form):
form.instance.owner = self.request.user
return super().form_valid(form)
UpdateView
class ListingUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
model = Listing
form_class = ListingForm()
def form_valid(self, form):
form.instance.owner = self.request.user
return super().form_valid(form)
def test_func(self):
listing = self.get_object()
#print(self.request.user, listing.owner)
if(self.request.user == listing.owner):
return True
else:
return False
forms.py
from django import forms
from .models import Listing
class ListingForm(forms.ModelForm):
class Meta:
model = Listing
fields = ['price', 'sqft', 'acre', 'title', 'description', 'address', 'city', 'state',
'country', 'zipcode', 'photo_main', 'photo_1', 'photo_2', 'photo_3', 'photo_4', 'photo_5']
Tysm for solving in advance!
You are missing form_class in your update and create view. You need to be add your forms name.
CreateView
class ListingCreateView(LoginRequiredMixin, CreateView):
model = Listing
form_class = your form name
fields = blah blah blah
def form_valid(self, form):
form.instance.owner = self.request.user
return super().form_valid(form)
UpdateView
class ListingUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
model = Listing
form_class = your form name
def form_valid(self, form):
form.instance.owner = self.request.user
return super().form_valid(form)
def test_func(self):
listing = self.get_object()
#print(self.request.user, listing.owner)
if(self.request.user == listing.owner):
return True
else:
return False
I have a listview for my blog:
#views.py
class BlogListView(ListView):
model = Blog
template_name = 'blog/index.html'
context_object_name = 'blogs'
ordering = ['-date_posted']
paginate_by = 5
#urls.py
path('', BlogListView.as_view(), name='blog-index'),
In my model I have different type of blogs, such as video blog or text blog. my model is like this:
class Blog(models.Model):
TYPE = (
('Video', 'Video'),
('Text', 'Text'),
)
type = models.CharField(max_length=10, choices=TYPE, default='Text')
Now I want to use request.GET.get('type') to query different types. For example if I go to the url, 127.0.0.1:8000/?type=video I want only blog that are the type video to show. Is it possible to do this with only this listview, or do I have to create others. I need help with making of this feature.
Yes, you can implement this in the ListView by overriding the .get_queryset(…) method [Django-doc]:
class BlogListView(ListView):
model = Blog
template_name = 'blog/index.html'
context_object_name = 'blogs'
ordering = ['-date_posted']
paginate_by = 5
def get_queryset(self):
type = self.request.GET.get('type')
qs = super().get_queryset()
if type is not None:
return qs.filter(type__iexact=type)
return qs
I am struggling to work out how to achieve something and would appreciate someone suggesting the correct Django way to do it.
I have a custom user model which is fairly basic but includes a BooleanField which says whether they have filled out a voluntary equality and diversity form. There is a very basic model which holds the equality and diversity form data without any reference to the users which filled out each response. What I want is this, when a user fills out a valid equality and diversity form it puts True in the user model box to say they have filled out the form.
I would be massively appreciative if anyone knows the correct way to do this as I am tying myself up in knots and have got myself quite confused.
Here is a simplified version of the code:
users/models.py
class CustomUser(AbstractUser):
# Has the user completed the EDI form?
edi = models.BooleanField(default=False)
def get_absolute_url(self):
return reverse('profile', args=[str(self.username)])
equality_diversity/models.py
class EqualityDiversity(models.Model):
age = models.CharField(max_length=8, choices=AGE_CHOICES)
ethnicity = models.CharField(max_length=64, blank=True, null=True)
... (etc)
equality_diversity/views.py
class EqualityDiversityView(LoginRequiredMixin, CreateView):
model = EqualityDiversity
template_name = 'equality_diversity.html'
form_class = EqualityDiversityForm
login_url = 'login'
success_url = '/'
def form_valid(self, form):
return super().form_valid(form)
class EqualityDiversityView(LoginRequiredMixin, CreateView):
model = EqualityDiversity
template_name = 'equality_diversity.html'
form_class = EqualityDiversityForm
login_url = 'login'
success_url = '/'
def form_valid(self, form):
# this is a view, You have self.request
self.request.user.edi = True
# apply changes to db
self.request.user.save()
return super().form_valid(form) # redirects to success_url
or better
class EqualityDiversityView(LoginRequiredMixin, CreateView):
model = EqualityDiversity
template_name = 'equality_diversity.html'
form_class = EqualityDiversityForm
login_url = 'login'
success_url = '/'
def form_valid(self, form):
# form.instance is an instance of the model that the form defines in META
form.instance.edi = True
# apply changes to db
form.instance.save()
return super().form_valid(form) # redirects to success_url
I am trying to change all my class-based views to function-based views and I am having difficulty converting the following class:
class PostUpdateView(LoginRequiredMixin, UserPassesTestMixin, SuccessMessageMixin, UpdateView):
model = Post
fields = ['image', 'title', 'category', status', 'description']
template_name = 'blog/post-form.html'
success_message = 'Your post has been updated.'
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
def get_context_data(self, **kwargs):
context = super(PostUpdateView, self).get_context_data(**kwargs)
context['title'] = 'Update post'
context['submit'] = 'Update'
return context
def get_success_url(self):
author = self.object.author
return reverse_lazy( 'profile', kwargs={'author': author.username})
The function and form should do exactly what this class-based view does, so if anyone can help me out, please let me know.
You can specify a .form_class attribute [Django-doc] in an UpdateView (as well as in a CreateView). So we can create a form like:
# app/forms.py
from django import forms
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = ['image', 'title', 'category', 'status', 'description']
widgets = {
'image': …
}
Where you replace … with the widget you want to use for the image field.
Then you can plug in that form:
# app/views.py
from app.forms import PostForm
class PostUpdateView(LoginRequiredMixin, UserPassesTestMixin, SuccessMessageMixin, UpdateView):
model = Post
form_class = PostForm
template_name = 'blog/post-form.html'
success_message = 'Your post has been updated.'
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
def get_context_data(self, **kwargs):
context = super(PostUpdateView, self).get_context_data(**kwargs)
context['title'] = 'Update post'
context['submit'] = 'Update'
return context
def get_success_url(self):
author = self.object.author
return reverse_lazy( 'profile', kwargs={'author': author.username})
Behind the curtains, if you do not specify a form_class, Django will simply make one for you with the modelform_factory [Django-doc], so by using another ModelForm, we do not change the logic of using the form.
I'm trying to make inline forms with class based views, i followed the instrunctions from here. The only change i've made was to give self.request.user instead of self.object to instance:
models.py
class Client(models.Model):
user = models.OneToOneField(CustomUser)
translate = models.BooleanField(default=False)
class ClientData(models.Model):
client = models.ForeignKey(Client)
language = models.ForeignKey(Language)
forms.py
class ClientForm(ModelForm):
class Meta:
model = Client
fields = '__all__'
exclude = ['user', ]
class ClientDataForm(ModelForm):
class Meta:
model = ClientData
fields = '__all__'
exclude = ['client', ]
ClientFormSet = inlineformset_factory(Client, ClientData, form=ClientDataForm, extra=1)
views.py
class ClientView(LoginRequiredMixin, UpdateView):
model = Client
fields = '__all__'
success_url = reverse_lazy('core:index')
class ClientDataView(LoginRequiredMixin, UpdateView):
template_name = 'core/client_data.html'
model = ClientData
form_class = ClientDataForm
success_url = reverse_lazy('core:index')
def get_object(self, queryset=None):
profile = get_object_or_404(ClientData, client__user=self.request.user)
return profile
def get_context_data(self, **kwargs):
context = super(ClientDataView, self).get_context_data(**kwargs)
if self.request.POST:
context['client_data'] = ClientFormSet(self.request.POST, instance=self.get_object())
else:
context['client_data'] = ClientFormSet(instance=self.get_object())
return context
def form_valid(self, form):
context = self.get_context_data()
client_data = context['client_data']
with transaction.atomic():
self.object = form.save()
if client_data.is_valid():
client_data.instance = self.object
return super(ClientDataView, self).form_valid(form)
Whenever i try to enter the page i get:
ValueError: Cannot query "asd#gmail.com": Must be "Client" instance.
[13/Dec/2017 15:48:36] "GET /client-data/ HTTP/1.1" 500 143759
for this line:
context['client_data'] = ClientFormSet(instance=self.get_object())
Your get_object is returning a ClientData instance.
def get_object(self, queryset=None):
profile = get_object_or_404(ClientData, client__user=self.request.user)
return profile
However, as the error suggests, the instance should be a Client instance, for example:
def get_object(self, queryset=None):
profile = get_object_or_404(Client, user=self.request.user)
return profile
Or you can simply follow the one-to-one relation backwards:
def get_object(self, queryset=None):
return self.request.user.client