I want to add permissions for users who are in the Employee group that in order to be able to see the view, but do not add. When I go to view with decorator I get a blank page and the code 403.
I use django-guardian.
MODEL
class MyModel(models.Model):
name = models.CharField(max_length=255, blank=True, null=True, help_text=_('Please enter name'))
date_from = models.DateField(help_text=_('Please specify start date'))
date_to = models.DateField(help_text=_('Please specify end date'))
class Meta:
verbose_name = _('MyModel')
verbose_name_plural = _('MyModels')
permissions = (
('can_view', _('Can view')),
('can_add', _('Can add')),
)
def __unicode__(self):
return self.free_day_type
VIEW
class Add(CreateView):
template_name = "myapp/add.html"
model = MyModel
form_class = MyModelInputForm
success_url = reverse_lazy('myapp:add')
#method_decorator(permission_required_or_403('myapp.can_view'))
#method_decorator(permission_required_or_403('myapp.can_add_holidays'))
def dispatch(self, *args, **kwargs):
return super(Add, self).dispatch(*args, **kwargs)
ADMIN
from django.contrib import admin
from .models import MyModel
from guardian.admin import GuardedModelAdmin
class MyModelAdmin(GuardedModelAdmin):
pass
admin.site.register(MyModel, MyModelAdmin)
Related
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'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 learning in DJango and I have learned alot of stuff from the documentation and also in StackOverflow. Right now, I'm kinda stuck and I just want to know who can I check in a class based view, if the user is in the manager column in job model/ It can also be in the manager model that's fine too.
I tried using UserPassesTestMixinin order to check if user is part of it but I'm getting an error of Generic detail view createjob must be called with either an object pk or a slug in the URLconf.
I just need someone to point me to the right direction or give me a hint.I also tried, this:
class createjob (LoginRequiredMixin,CreateView):
model = Job
fields = ['member','title', 'description', 'file']
def form_valid(self,form):
form.instance.manager=self.request.user
return super().form_valid(form)
But it's giving me an error of Cannot assign "<SimpleLazyObject: <User: edlabra>>": "Job.manager" must be a "Manager" instance.
Here's my views.py:
from django.shortcuts import render
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.views.generic import ListView, CreateView
from .models import Job, Member
from profiles.models import User
from django.contrib.auth.decorators import login_required
# Create your views here.
class jobs(LoginRequiredMixin,ListView):
model = Job
template_name = 'users/user_jobs.html'
context_object_name = 'jobs'
def get_queryset(self):
return Job.objects.filter(member__member=self.request.user)
class createdjobs(LoginRequiredMixin,ListView):
model = Job
template_name = 'users/manager_jobs.html'
context_object_name = 'jobs'
def get_queryset(self):
return Job.objects.filter(manager__manager=self.request.user)
class teamview(LoginRequiredMixin,ListView):
model = Member
template_name = 'users/manage_team.html'
context_object_name = 'members'
def get_queryset(self):
return Member.objects.filter(manager__manager=self.request.user)
class createjob (LoginRequiredMixin,UserPassesTestMixin,CreateView):
model = Job
fields = ['member','title', 'description', 'file']
def test_func(self):
job=self.get_object()
if self.request.user == Job.manager:
return True
return False
Models.py:
from django.db import models
from profiles.models import User
# Create your models here.
class Points (models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
points = models.IntegerField(default=0, null=False)
def __str__(self):
return self.user.username
class Profile (models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
image = models.ImageField(default='default.png',upload_to='profile_pics')
def __str__(self):
return f'{self.user.username}Profile'
class Manager (models.Model):
name = models.CharField(max_length=30, blank=True, null=True)
manager = models.ForeignKey(User,on_delete=models.CASCADE)
def __str__(self):
return self.name
class Member (models.Model):
name = models.CharField(max_length=30, blank=True, null=True)
manager = models.ForeignKey(Manager, on_delete=models.CASCADE)
member = models.ForeignKey(User,on_delete=models.CASCADE)
def __str__(self):
return self.name
class Job (models.Model):
manager = models.ForeignKey(Manager, on_delete=models.CASCADE)
member = models.ForeignKey(Member, on_delete=models.CASCADE)
title = models.CharField(max_length=30, blank=False, null=False)
description = models.TextField()
datePosted = models.DateTimeField (auto_now = True)
file = models.FileField(null=True, blank=True,upload_to='job_files')
def __str__(self):
return self.title
assign user from manager table.
def form_valid(self,form):
form.instance.manager=Manager.objects.get(manager=self.request.user)
return super().form_valid(form)
I am a beginner in Django. Right now, I am working with the APIs. I am facing a problem. I can't view one of the fields, called label, at http://127.0.0.1:8000/gameapi/. Here is the screenshot:
Here are my codes of serializers.py located inside gamreview folder.
from rest_framework import serializers
from .models import Game, Tags
class TagSerializer(serializers.ModelSerializer):
class Meta:
model = Tags
fields = ['label']
class GameSerializer(serializers.ModelSerializer):
# label_tag = TagSerializer(many=True)
class Meta:
model = Game
fields = ['id', 'title', 'developer', 'platform']
fields = ['id', 'title', 'developer', 'platform','label_tag']
def create(self, validated_data):
label_tag_data = validated_data.pop('label_tag')
game = Game.objects.create(**validated_data)
for tags_data in label_tag_data:
Tags.objects.create(game=game, **tags_data)
return Game.objects.create(**validated_data)
def update(self, instance, validated_data):
instance.title = validated_data.get('title', instance.title)
instance.developer = validated_data.get('developer', instance.developer)
instance.platform = validated_data.get('platform', instance.platform)
instance.tag = TagSerializer(read_only=True, many=True)
instance.save()
return instance
Here are my codes of models.py under gamreview folder:
from django.db import models
from django.template.defaultfilters import slugify
# Create your models here.
class Tags(models.Model):
label = models.CharField(max_length=20)
def __str__(self):
return self.label
class Game(models.Model):
title = models.CharField(max_length=100)
developer = models.CharField(max_length=100)
platform = models.CharField(max_length=50, default='null')
label_tag = models.ManyToManyField(Tags)
slug = models.SlugField(max_length=150, default='null')
def __str__(self):
return self.title
def save(self, *args, **kwargs):
self.slug = slugify(self.title)
super().save(*args, **kwargs)
class Review(models.Model):
game = models.ForeignKey(Game, on_delete=models.CASCADE)
review = models.CharField(max_length=1000)
date = models.DateField(auto_now=True)
slug = models.SlugField(max_length=150, default='null')
def __str__(self):
return self.game
Here are my codes of views.py under gamreview folder:
from django.views import generic
from .models import Game
from rest_framework import generics
from .serializers import GameSerializer
# Create your views here.
class GameListView(generic.ListView):
template_name = 'gamereview/gamelist.html'
context_object_name = 'all_games'
def get_queryset(self):
return Game.objects.all()
class ReviewView(generic.DetailView):
model = Game
template_name = 'gamereview/review.html'
# class GameApiView(generics.ListAPIView):
class GameApiView(generics.ListCreateAPIView):
queryset = Game.objects.all()
serializer_class = GameSerializer
class GameDetailApiView(generics.RetrieveUpdateDestroyAPIView):
queryset = Game.objects.all()
serializer_class = GameSerializer
Here are my codes of urls.py under gamreview folder:
from . import views
from django.urls import path
app_name = 'gamereview'
urlpatterns = [
path('gamereview/', views.GameListView.as_view(), name='gamelist'),
path('gamereview/<slug:slug>/', views.ReviewView.as_view(), name='review'),
path('gameapi/', views.GameApiView.as_view(), name='gamelistapi'),
path('gameapi/<int:pk>/', views.GameDetailApiView.as_view()),
]
I don't get any error while running the server. However, the label field is not showing up.
How can I fix the issue?
You have declared fields twice in GameSerializer- Meta class. Delete the first one.
class GameSerializer(serializers.ModelSerializer):
# label_tag = TagSerializer(many=True)
class Meta:
model = Game
fields = ['id', 'title', 'developer', 'platform'] --> delete this
fields = ['id', 'title', 'developer', 'platform','label_tag']
Django rest framework relies on related_name attribute to the resolve foreign key fields.
I think just changing your Game model so would do it
label_tag = models.ManyToManyField(Tags, related_name="label")
I am using django-filter to filter my data. The issue is both the available options of the filters and the results are based on all the data, not only on the curent user.
models.py
class Product(models.Model):
title = models.CharField(max_length=264)
description = models.CharField(max_length=264)
date_added = models.DateField(auto_now_add=True)
time_added = models.TimeField(auto_now_add=True)
user = models.ForeignKey(User, default=1, on_delete=models.CASCADE)
I used the code below to filter the results only on the current user:
filters.py
class ProductFilter(django_filters.FilterSet):
class Meta:
model = Product
#property
def qs(self):
parent = super(ProductFilter, self).qs
user = getattr(self.request, "user", None)
return parent.filter(user=user).order_by("-timestamp")
In my views.py I tried to pass the queryset, but nothing changed:
class ProductsFilterView(LoginRequiredMixin, FilterView):
model = Product
filterset_class = ProductFilter
def get_queryset(self, **kwargs):
return self.model.objects.filter(user=self.request.user)
I am not sure how to limit the available filter options only on the current user's data.
So, summarizing how can I pass into the filterset just the current user's data and not pass the whole data into the filterset and then filter them on current user's data.
filters.py
class ProductFilter(django_filters.FilterSet):
class Meta:
title = django_filters.CharFilter(lookup_expr='icontains')
# And you can also do "lookup_expr='year__gt' and also 'year__lt'"
date_added = django_filters.NumberFilter(name='date_added', lookup_expr='year')
class Meta:
model = Product
fields = [] #You can add fields that wants to be displayed
views.py
from django.contrib.auth.decorators import login_required
from django.shortcuts import render
from .filters import ProductFilter
# Function Base View
#login_required
def productfilter(request):
user = request.user
product_list = Product.objects.filter(user=user)
product_filter = ProductFilter(request.GET, queryset=product_list)
return render(request, "template_name.html", {'products': product_list})
#Class Based View
class ProductsFilterView(LoginRequiredMixin, FilterView):
context_object_name = 'products'
template_name = 'template_name.html'
filter_set = ProductFilter
def get_queryset(self):
return Product.objects.filter(user=self.request.user)
I hope this was helpful.