Django restricting access to view for certain objects - python

I have some page that displays various players of a team. In the configuration you can switch between the teams, so if you put TEAM_NAME = 'test' it loads the test team obviously. The problem is, that if you put TEAM_NAME = 'test2', it starts it up for that team, but I can still change the URL to switch between teams (while I should only be able to view the team I selected)
The URL looks like this:
http://127.0.0.1:8000/team/1/player/, where 1 would be the first created team, which is test.
When I load the view, I would like to have some permission checks to see if the current view's team is the same as the team in the configuration.
This is the view:
class PlayerList(ListView):
model = player_model
template_name = 'player_list.html'
def get_team(self):
if not hasattr(self, '_team'):
team_id = self.kwargs.get('team_id')
self._team = team_model.objects.get(pk=self.kwargs.get('team_id'))
return self._team
def get_context_data(self, *args, **kwargs):
context = super().get_context_data(*args, **kwargs)
context['team'] = self.get_team()
return context
def get_queryset(self, *args, **kwargs):
queryset = super().get_queryset(*args, **kwargs)
return queryset.filter(team_id=self.kwargs.get('team_id'))
def get(self, request, *args, **kwargs):
return super(PlayerList, self).get(request, *args, **kwargs)

You could do that in get method to block/allow access:
from django.core.exceptions import PermissionDenied
def get(self, request, *args, **kwargs):
team_id = self.kwargs.get('team_id')
team = team_model.objects.get(pk=team_id)
if team.name != TEAM_NAME:
raise PermissionDenied
else:
return super(PlayerList, self).get(request, *args, **kwargs)

Related

How to get data from forms?

How can I get data from a form (ProductCreateForm)?
If I write form = self.get_form(), then I just get a form template, where some data is selected, and some are not (select especially).
If I write form = ProductCreateForm(request.POST), then I get an error saying that the request was not found. Perhaps this is due to the fact that I set the request in get_context_data() and work with them in the __init__ method in the forms.py.
I process the data in the clean method in the forms.py.
I have the following view
class ProductsCreate(CreateView):
model = Product
form_class = ProductCreateForm
http_method_names = ['get', 'post']
def get_initial(self):
initial = super(ProductsCreate, self).get_initial()
initial['request'] = self.request
return initial
​
def get_context_data(self, *args, **kwargs):
ctx=super(ProductsCreate, self).get_context_data(*args, **kwargs)
ctx['special_form'] = SpeciallyPriceForm()
return ctx
​
def get(self, request, *args, **kwargs):
self.object = None
if kwargs.get('slug'):
category = Category.objects.filter(slug=kwargs.get('slug')).first()
self.initial.update({'category': category})
return self.render_to_response(self.get_context_data())
def post(self, request, *args, **kwargs):
self.object = None
form = ProductCreateForm(request.POST) #What here?
special_form = SpeciallyPriceForm(self.request.POST)
​
if form.is_valid() and special_form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
forms
class ProductCreateForm(forms.ModelForm):
#....
​
def __init__(self, *args, **kwargs):
self.request = kwargs.pop('initial').get('request')
super(ProductCreateForm, self).__init__(*args, **kwargs)
#...
user = self.request.user
provider = Provider.objects.filter(user=user.id).last()
self.fields['category'] = ModelMultipleChoiceField(queryset=provider.category.all())
#...
def clean(self):
cleaned_data = super(ProductCreateForm, self).clean()
cd_category = cleaned_data.get('category')
#...
​
​
class SpeciallyPriceForm(forms.ModelForm):
class Meta:
model = SpeciallyPrice
fields = ['adittional_specially_price', 'adittional_specially_number']
1.try pass request in that way
def get_initial(self):
"""
Returns the initial data to use for forms on this view.
"""
initial = super(ProductsCreate, self).get_initial()
initial['request'] = self.request
return initial
then in forms.py
def __init__(self):
kwargs.pop('initial').get('request')
Are you sure that is working at all? On init in your forms I don't see super() call so you should get an error?
Do you have problem only with category field the rest data you get properly?
Where do you pass it kwargs.pop('request') ??
You can print and check what is in self.request.POST

How to resolve Undefined variable models error, in Python-Django Framework

Following is the code in views.py
class CreateGroup(LoginRequiredMixin,generic.CreateView):
fields = ('name','description')
model = Group
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,("Warning, already a member of
{}".format(group.name)))
else:
messages.success(self.request,"You are now a member of the {}
group.".format(group.name))
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.ObjectDoesNotExist:
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)
I am developing a social media clone site using Django. I had created the views for implying Groups and Group Members, and their membership.
It gives the error as: Undefined variable 'models' 'GroupMember' has no 'objects' member

Django: object not iterable

I want to fill my model form with initial data. However, I always receive an 'Attendee' object is not iterable. Full traceback: http://dpaste.com/0BH9MAM
When I comment this out: initial=self.object, the error disappears. However, my from is not pre-filled with any data. As I add more forms I can't work with FormMixin or UpdateForm
class AssignAttendee(SuccessMessageMixin, SingleObjectMixin, TemplateView):
template_name = 'attendees/front/assign_attendee.html'
success_message = _("Attendee has been successfully updated.")
def get_object(self):
return get_object_or_404(
Attendee,
ticket_reference=self.kwargs['ticket_reference'],
ticket_code=self.kwargs['ticket_code'],
)
def get(self, request, *args, **kwargs):
self.object = self.get_object()
return super().get(request, *args, **kwargs)
# def post(self, request, *args, **kwargs):
# self.object = self.get_object()
# return super().post(request, *args, **kwargs)
#cached_property
def attendee_form(self):
return AssignAttendeeForm(
prefix='attendee',
data=self.request.POST or None,
initial=self.object,
)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context = {
'attendee': self.object,
'attendee_form': self.attendee_form,
}
return context
forms.py
class AssignAttendeeForm(forms.ModelForm):
class Meta:
model = Attendee
fields = (
'ticket_reference',
'first_name',
'last_name',
'company_name',
'email',
)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['ticket_reference'].widget = forms.HiddenInput()
self.fields['ticket_reference'].disabled = True
for visible_field in self.visible_fields():
visible_field.field.widget.attrs['class'] = 'form-control'
You should pass a dict to Form.initial, not an object.
You are probably looking for the ModelForm.instance keyword argument, which allows updating an existing instance of a model.

Django pass User instance to Forms when form is created

I have a Django form and l would like to pass a user instance when the form is created
First Approach
This is where l create the form and pass the instance of the user:
form = QuestionForm(request.user, request.POST)
And inside the QuestionForm
def __init__(self, user, *args, **kwargs):
super(QuestionForm, self).__init__(*args, **kwargs)
self.data = user
log.info(self)
Study.objects.filter(owner = self.data.id))
Second Approach
This is where l create the form and pass the request:
form = QuestionForm ( ..., request=request)
And inside the QuestionForm
def __init__(self, *args, **kwargs):
self.request = kwargs.pop("request")
super(MyForm, self).__init__(*args, **kwargs)
ref = forms.ModelChoiceField(queryset=Study.objects.filter(owner = self.request.user.id))
Now l am getting an error that self is not define and as such l cannot get the user id to query the Study class
Any help would be much appreciated
If you do this code in field declaration section like
class QuestionForm(forms.Form):
ref = forms.ModelChoiceField(queryset=Study.objects.filter(owner=...)
then it will not work because it still doesn't have self variable.
You can do this in init method like this
class QuestionForm(forms.Form):
ref = forms.ModelChoiceField()
def __init__(self, *args, **kwargs):
super(MyForm, self).__init__(*args, **kwargs)
self.fields['ref'].queryset = Study.objects.filter(owner=request.user)

Django REST Framework : update() based on query string parameter

Is it possible to modify a ViewSet's update() function to update based on a query string parameter instead of a URL resource name or the request body?
For example, I want trigger something like this:
payload = {'field' : '2'}
r = requests.put("http://127.0.0.1:9876/job-defs?job-def-id=2", data=payload)
and have this update my field when job-def-id = 2.
What I have so far is this:
class JobDefinitionsViewSet(mixins.ListModelMixin,
mixins.CreateModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
viewsets.GenericViewSet):
serializer_class = JobDefinitionsSerializer
def update(self, request, pk=None):
job_def_id = self.request.query_params.get('job-def-id', None)
super(JobDefinitionsViewSet, self).update(self, request, pk=job_def_id)
...
# other unrelated code
...
I'm not too sure how to continue.
I want to reuse as much as the update() function from mixins.UpdateModelMixin as possible.
Any help is appreciated.
Assuming you want to use the same url for listing and for retrieving the details of the entity, discriminating on the presence of the url parameter job-def-id, here is a crazy idea:
class JobDefinitionsAllInOneView(mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
mixins.ListModelMixin,
mixins.CreateModelMixin,
generics.GenericAPIView):
queryset = JobDefinitions.objects.all()
serializer_class = JobDefinitionsSerializer
def get_object(self):
job_def_id = self.request.query_params.get('job-def-id', None)
if job_def_id is not None:
self.kwargs['pk'] = job_def_id
return super(JobDefinitionsAllInOneView, self).get_object()
def put(self, request, *args, **kwargs):
return self.update(request, *args, **kwargs)
def get(self, request, *args, **kwargs):
job_def_id = self.request.query_params.get('job-def-id', None)
if job_def_id is not None:
# return the details
return self.retrieve(request, *args, **kwargs)
else:
# return a list
return self.list(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs)
def patch(self, request, *args, **kwargs):
return self.partial_update(self, request, *args, **kwargs)
def delete(self, request, *args, **kwargs):
return self.destroy(self, request, *args, **kwargs)
I haven't tried it yet. I had a look at the source code here for get_object and here for the mixins

Categories

Resources