Django - Access request.session in form - python

I am calling a form as follows, then passing it to a template:
f = UserProfileConfig(request)
I need to be able to access the request.session within the form... so first I tried this:
class UserProfileConfig(forms.Form):
def __init__(self,request,*args,**kwargs):
super (UserProfileConfig,self).__init__(*args,**kwargs)
self.tester = request.session['some_var']
username = forms.CharField(label='Username',max_length=100,initial=self.tester)
This didn't work, I gather, because of when the form is constructed compared to setting the username charfield.
So, next I tried this:
class UserProfileConfig(forms.Form):
def __init__(self,request,*args,**kwargs):
super (UserProfileConfig,self).__init__(*args,**kwargs)
self.a_try = forms.CharField(label='Username',max_length=100,initial=request.session['some_var'])
username = self.a_try
To no avail.
Any other ideas?

Try this:
class UserProfileConfig(forms.Form):
def __init__(self,request,*args,**kwargs):
super (UserProfileConfig,self).__init__(*args,**kwargs)
self.fields['username'] = forms.CharField(label='Username',max_length=100,initial=request.session['some_var'])
I find this article about dynamic forms very helpful.

I am so surprised that Django use session in form is so hard. sometimes we really need use session data in form to valid fields.
I create a small project can solve this. django-account-helper
example code:
from account_helper.middleware import get_current_session
Class YourForm(forms.Form):
def clean(self):
session = get_current_session()
if self.cleaned_data.get('foo') == session.get('foo'):
# do something
pass
#... your code
pass

Related

How to get request value in another class in django?

It's an example that's as similar as possible, and it's not exactly the same as the actual code.
But I believe it's easy to understand.
class Fruits:
...
def get_sample_data(self, df):
...
data = {
'put_file_attachment': >here<,
}
...
class DataInputForm(forms.Form):
attachment = forms.FileField()
class MyView(FormView):
template_name = 'view.html'
form_class = DataInputForm
def get_success_url(self):
return str(
reverse_lazy("milk")
)
def post(self, request, *args, **kwargs):
get_file = request.FILES.get('attachment')
...
k = Fruits()
k.load_data()
return self.render_to_response(context)
I would like to bring the attachment(In fact, get_file) that the user attached to the web class Fruits's >here<
In other words, I would like to save the file(get_file) in DB column (put_file_attachment) by the user's attachment. How can I get a value passed to a request from another class to another class?
I tried to get 'get_file' by creating a MyView object in the Fruit class, but it doesn't work.
Is that possible in this structure or Am I not understanding the concept of request??
The variable must be explicitly passed to the class for it to be available. It's currently in a different scope, so it won't be available.
So, either refactor your Fruits class to take your file as an argument to your constructor (ie, __init__), or pass it in some other way, such as a parameter to your load_data method.

How to pass username into function inside a form in django?

I have a form which has a variable that calls a function to get a list of names. I need to pass the current logged in user as a dynamic parameter variable into this function.
I have spent about 2 days on this trying to work any and every solution I can. Cannot find anything that works. I have tried to initialize a request object but cannot get that to work.
class ManagerForm(forms.Form):
names = get_employee_names(<<dynamic username goes here>>)
manager = forms.ChoiceField(choices=names, widget=forms.RadioSelect)
The expected result is to pass the username as a string into the function as a parameter.
Forms by itself doesn't have access to request object and therefore can't identify which user is currently logged. Your view should pass current user username instead:
views.py:
def index(request):
# ...
form = ManagerForm(request.POST or None, current_user_username=request.user.username)
# ...
forms.py:
def get_employee_names(username):
# assuming it constructs correct choices tuples, like:
# choices = ((username, username), ('noname', 'noname'))
return choices
class ManagerForm(forms.Form):
manager = forms.ChoiceField(choices=[], widget=forms.RadioSelect)
def __init__(self, *args, **kwargs):
username = kwargs.pop('current_user_username')
super().__init__(*args, **kwargs)
self.fields['manager'].choices = get_employee_names(username)
This is description of what django expect choices to be.

return list of ids in a Get. Django Rest Framework

I have a model called "document-detail-sample" and when you call it with a GET, something like this, GET https://url/document-detail-sample/ then you get every "document-detail-sample".
Inside the model is the id. So, if you want every Id, you could just "iterate" on the list and ask for the id. Easy.
But... the front-end Developers don't want to do it :D they say it's too much work...
So, I gotta return the id list. :D
I was thinking something like GET https://url/document-detail-sample/id-list
But I don't know how to return just a list. I read this post and I know how to get the id_list in the backend. But I don't know what should I implement to just return a list in that url...
the view that I have it's pretty easy:
class DocumentDetailSampleViewSet(viewsets.ModelViewSet):
queryset = DocumentDetailSample.objects.all()
serializer_class = DocumentDetailSampleSerializer
and the url is so:
router.register(r'document-detail-sample', DocumentDetailSampleViewSet)
so:
1- is a good Idea do it with an url like .../document-detail-sample/id-list" ?
2- if yes, how can I do it?
3- if not, what should I do then?
You could use #list_route decorator
from rest_framework.decorators import detail_route, list_route
from rest_framework.response import Response
class DocumentDetailSampleViewSet(viewsets.ModelViewSet):
queryset = DocumentDetailSample.objects.all()
serializer_class = DocumentDetailSampleSerializer
#list_route()
def id_list(self, request):
q = self.get_queryset().values('id')
return Response(list(q))
This decorator allows you provide additional endpoint with the same name as a method. /document-detail-sample/id_list/
reference to docs about extra actions in a viewset
Assuming you don't need pagination, just override the list method like so
class DocumentDetailSampleViewSet(viewsets.ModelViewSet):
queryset = DocumentDetailSample.objects.all()
serializer_class = DocumentDetailSampleSerializer
def list(self, request):
return Response(self.get_queryset().values_list("id", flat=True))

django-rest-framework non orm-based filtering

I am using DjangoRestApi and while it works like a charm with queryset (orm-based) views, I am struggling to make views that use different back-end to behave same way orm-based views are. Notably I want to add filters and have them cast and validated automatically.
Pseudo code below:
class NewsFilter(django_filters.FilterSet):
category = django_filters.NumberFilter(name='category')
limit = django_filters.NumberFilter(name='limit')
page = django_filters.NumberFilter(name='page')
class NewsView(generics.APIView):
filter_class = NewsFilter
def get(self, request):
filters = self.filter_class(??) # not sure, what to put here
payload = logic.get_business_news(**filters.data) # same
return Response(payload, status=status.HTTP_200_OK)
Any hint how to tackle problem will be appreciated.
Ultimate goal is to:
user types something into url or sends via POST, django-rest intercepts relevant values, extracts them, casts them into correct type and return as a dictionary
filters are displayed as they would if serializer was ORM based
The function signature to any single filter is like
class MyFilter(django_filters.Filter):
def filter(self,queryset,value):
[...]
The function signature to a FilterSet is:
def __init__(self, data=None, queryset=None, prefix=None, strict=None):
So, it looks like you pass in request.GET as data param and then pass in your queryset.

Django Form inheritance problem

Why can't I do this?
from django import forms
from django.forms import widgets
class UserProfileConfig(forms.Form):
def __init__(self,*args,**kwargs):
super (UserProfileConfig,self).__init__(*args,**kwargs)
self.tester = 'asdf'
username = forms.CharField(label='Username',max_length=100,initial=self.tester)
More specifically, why cant the forms.CharField grab the variable tester that I set during construction?
I feel like I am missing something about the way Python handles this sort of thing...
edit :
What I am actually trying to do is this:
class UserProfileConfig(forms.Form):
def __init__(self,request,*args,**kwargs):
super (UserProfileConfig,self).__init__(*args,**kwargs)
self.tester = request.session['some_var']
username = forms.CharField(label='Username',max_length=100,initial=self.tester)
In other words, I need to grab a session variable and then set it to an initial value...
Is there any way to handle this through the __init__ or otherwise?
What you've got doesn't work because your CharField gets created, and pointed to by UserProfileConfig.username when the class is created, not when the instance is created. self.tester doesn't exist until you call __init__ at instance creation time.
You can just do it this way
from django import forms
from django.forms import widgets
class UserProfileConfig(forms.Form):
username = forms.CharField(label='Username',max_length=100,initial=self.tester)
tester = 'asdf'
You could do this:-
class UserProfileConfig(forms.Form):
username = forms.CharField(label='Username',max_length=100)
def view(request):
user_form = UserProfileConfig(initial={'username': request.session['username',})
Which is the generally accepted method, but you can also do this:-
class UserProfileConfig(forms.Form):
def __init__(self,request,*args,**kwargs):
super (UserProfileConfig,self).__init__(*args,**kwargs)
self.fields['username'] = request.session['some_var']
username = forms.CharField(label='Username',max_length=100)
def view(request):
user_form = UserProfileConfig(request=request)

Categories