Django class based views: variable across classes - django

I have a mixin called GroupAwareMixin in a mixins.py file:
class GroupAwareMixin(object):
group = None
def get_group(self):
self.group = self.bridge.get_group()
def dispatch(self, request, *args, **kwargs):
if not self.group:
self.get_group()
In the views.py file I have the following ListView which inherits from the above GroupAwareMixin:
class ChatListView(LoginRequiredMixin, GroupAwareMixin, ListView):
model = Chat
template_name = 'chat/home.html'
Further I have a Chat class in my views.py file, where I would like to access the group variable from the GroupAwareMixin class above. How I am able to access the group variable in the Chat class?
class Chat(ws.WS, ChatListView):
def on_message(self, websocket, msg):
slug = self.group
I tried to inherit from ChatListView, but the self.group in the Chat class is None.
The LoginRequiredMixin defines the following:
class LoginRequiredMixin(AccessMixin):
def dispatch(self, request, *args, **kwargs):
if not request.user.is_authenticated():
if self.raise_exception:
raise PermissionDenied # return a forbidden response
else:
return redirect_to_login(request.get_full_path(),
self.get_login_url(),
self.get_redirect_field_name())
return super(LoginRequiredMixin, self).dispatch(
request, *args, **kwargs)

Related

Django: How to clean data when list_editable in admin page?

I have a model which has a field 'keywords'. When I use a form to create/modify records, I am able to clean this field and then save it.
class ILProjectForm(forms.ModelForm):
class Meta:
models = ILProject
fields = '__all__'
def clean_keywords(self):
k = self.cleaned_data.get('keywords')
if k:
k = ','.join([a.strip() for a in re.sub('\\s+', ' ', k).strip().split(',')])
return k
However, I am not sure how to run clean() to update the data when I am using the list_editable option in the admin page.
I tried something like this bit I get an error saying I cannot set an attribute. What is the correct way to update the data after it has been cleaned?
class MyAdminFormSet(BaseModelFormSet):
def clean(self):
print(type(self.cleaned_data))
recs = []
for r in self.cleaned_data:
if r['keywords']:
r['keywords'] = ','.join([a.strip() for a in re.sub('\\s+', ' ', r['keywords']).strip().split(',')])
print(r['keywords'])
recs.append(r)
self.cleaned_data = recs <-- this part is problematic.
class ILProjectAdmin(...)
...
def get_changelist_formset(self, request, **kwargs):
kwargs['formset'] = MyAdminFormSet
return super().get_changelist_formset(request, **kwargs)
It should be like this:
class ILProjectAdmin(...)
...
def get_changelist_form(self, request, **kwargs):
return ILProjectForm
Please refer this tip: Django: Access request object from admin's form.clean()
class ProjectRequestForm(forms.ModelForm):
class Meta:
model = ProjectRequest
def __init__(self, *args, **kwargs):
self.request = kwargs.pop('request', None)
super(ProjectRequestForm, self).__init__(*args, **kwargs)
def clean(self):
if self.request.user.has_perm('access_role'):
raise ValidationError(f'No permission', code='invalid')
class ProjectRequestAdmin(admin.ModelAdmin):
def get_form(self, request, obj=None, **kwargs):
form = super(ProjectRequestAdmin, self).get_form(request, obj, **kwargs)
class AdminFormWithRequest(form):
def __new__(cls, *args, **kwargs):
kwargs['request'] = request
return form(*args, **kwargs)
return AdminFormWithRequest
def get_changelist_form(self, request, **kwargs):
class AdminFormWithRequest(ProjectRequestForm):
def __new__(cls, *args, **kwargs):
kwargs['request'] = request
return ProjectRequestForm(*args, **kwargs)
return AdminFormWithRequest

#permission_required decorator returns no user attribute in View error

I'm working with Django-admin panel. I have created a custom view file to add a file manager.
To make file uploading safe, I just added permission_required decorator. But it throws an error 'FileBrowser' object has no attribute 'user'.
Here is my code.
class FileBrowser(ListView):
model = File
paginate_by = 30
template_name = "file_manager/browser.html"
extra_context = {
'file_type': type,
'title': "Media Browser",
}
#permission_required('file_manager.view_file')
def dispatch(self, request, *args, **kwargs):
file_type = request.GET.get('type')
self.queryset = File.objects.filter(type=file_type)
self.extra_context['value_to'] = request.GET.get('value_to')
self.extra_context['image_to'] = request.GET.get('image_to')
self.extra_context['form'] = FileForm()
return super().dispatch(request, *args, **kwargs)
You can not decorate the method like that, since such decorator does not expect self as first parameter. It thus sees self as the request parameter.
What you can do is work with a #method_decorator decorator, like:
from django.utils.decorators import method_decorator
#method_decorator(permission_required('file_manager.view_file'), name='dispatch')
class FileBrowser(ListView):
# …
def dispatch(self, request, *args, **kwargs):
# …
For a class-based view however, you can work with the PermissionRequiredMixin [Django-doc]
from django.contrib.auth.mixins import PermissionRequiredMixin
class FileBrowser(PermissionRequiredMixin, ListView):
permission_required = 'file_manager.view_file'
# …
def dispatch(self, request, *args, **kwargs):
# …
There was a small mistake in my code. But I didn't noticed that. I simply forgot to use #method_decorator and directly wrote #permission_required decorator.
This was what I wrote.
#permission_required('file_manager.view_file')
def dispatch(self, request, *args, **kwargs):
.......
.......
return super().dispatch(request, *args, **kwargs)
This is what I changed to:
#method_decorator(permission_required('file_manager.view_file'))
def dispatch(self, request, *args, **kwargs):
.......
.......
return super().dispatch(request, *args, **kwargs)
Now it's working fine.

How can i use middleware decorator for class-based view in djabgo?

How can i use middleware decorator for classbased view?
class APIViewMixin():
apiMiddleware = decorator_from_middleware(APISecretMiddleware)
#apiMiddleware
def dispatch(*args, **kwargs):
return super().dispatch(*args, **kwargs)
class ThemesView(APIViewMixin, View):
def get(self, request, id= None, *args, **kwargs):
if (id!= None):
serializer = vocabulary.customserializers.ThemesSerialiser(showWords=True);
return HttpResponse(serializer.serialize([vocabulary.models.Theme.objects.get(pk= id)]), content_type='application/json')
else:
serializers = vocabulary.customserializers.ThemesSerialiser(showWords=False);
return HttpResponse(serializers.serialize(vocabulary.models.Theme.objects.all()), content_type='application/json',)
this doesnt work

how to access session variable inside form class

Hi i have a session variable city, how to access it inside form class.
Something like this
class LonginForm(forms.Form):
current_city=request.city
A Form has by default no access to the request object, but you can make a constructor that takes it into account, and processes it. For example:
class LonginForm(forms.Form):
def __init__(self, *args, request=None, **kwargs):
super(LonginForm, self).__init__(*args, **kwargs)
self.request = request # perhaps you want to set the request in the Form
if request is not None:
current_city=request.city
In the related views, you then need to pass the request object, like:
def some_view(request):
my_form = LonginForm(request=request)
# ...
# return Http Response
Or in a class-based view:
from django.views.generic.edit import FormView
class LonginView(FormView):
template_name = 'template.html'
form_class = LonginForm
def get_form_kwargs(self, *args, **kwargs):
kwargs = super(LonginView, self).get_form_kwargs(*args, **kwargs)
kwargs['request'] = self.request
return kwargs

Redirect to url from "post-only" view

I have the following setup for a combination of a DetailView and a FormView:
class EventBookView(LoginRequiredMixin, View):
def get(self, request, *args, **kwargs):
view = EventBookBaseView.as_view()
return view(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
view = EventBookFormView.as_view()
return view(request, *args, **kwargs)
class EventBookBaseView(DetailView):
template_name = "event_book.html"
model= Event
context_object_name = 'event'
class EventBookFormView(SingleObjectMixin, FormView):
template_name = "event_book.html"
form_class = PersonalInfoForm
model = Event
context_object_name = 'event'
def post(self , request , *args , **kwargs):
#do stuff
...
return redirect('user_bookings')
Unfortunately, the redirect to the url with the name 'user_bookings' is not working. How can I redirect to that url?
thanks!
You can use success_url, when Form is properly processed then view is redirected.
eg.
class MyFormView(FormView):
success_url = reverse_lazy('user_bookings')
EDIT: changed reverse to reverse_lazy
A POST method should not return a redirection.
If you need so, try to use HttpResponseRedirect.
Like:
return HttpResponseRedirect('/user_bookings/')