Django accessing request.user data from form along with file submission - django-forms

I am trying to display a form with License Type data based on request.user data.
Form works fine when using user as a input variable to the form in the view.
However when I try to upload a file using the same form and use request.File.
I receive following error.
forms.py
from django import forms
class BusinessRequestForm(forms.Form):
business_name = forms.CharField(label='Enter Business Name', widget=forms.Textarea, help_text="Enter the Name of the business you require" )
business_type= forms.ChoiceField(label='Select Your Business Type', choices=BUSINESS_TYPE, help_text="If your business type is not present. Enter details in Additional info" )
license_type =forms.ModelChoiceField(label='Select the license type',queryset=Pricing.objects.none(),help_text="Check Pricing on Main Page Pricing")
additional_detail=forms.CharField(label='Enter any additional details', widget=forms.Textarea, help_text="Give details about your Tax Structure", required=False)
tax_structure=forms.CharField(label='Tax Structure ', widget=forms.Textarea, help_text="Describe Your Tax Structure If Applicable",required=False)
sales_invoice=forms.FileField(help_text="Upload your present Sales Invoice if any",required=False)
purchase_invoice=forms.FileField(help_text="Upload your present Purchase Invoice if any",required=False)
pay_slip=forms.FileField(help_text="Upload your present Pay Slip if any",required=False)
talley_file=forms.FileField(help_text="Upload your present Talley Export if any",required=False)
def __init__(self,input_user,*args,**kwargs):
super(BusinessRequestForm,self).__init__(*args,**kwargs)
select_user=MyProfile.objects.get(user=input_user)
price=Pricing.objects.all().filter(pricing_region=select_user.region).filter(target=select_user.sales_partner)
self.fields['license_type'].queryset=price
models.py
class Business_request(models.Model):
user=models.ForeignKey("auth.User")
business_name=models.CharField("Name of Business Required",max_length=200,help_text="Enter the name of the business")
business_type=models.CharField("Select Business Type",max_length=200,choices=BUSINESS_TYPE,help_text="If your business type is not present,enter in additional details and select the closest type here")
license_type=models.ForeignKey(Pricing)
tax_structure=models.CharField("Tax Structure",max_length=200,help_text="Describe your Tax Structure",blank=True)
additional_details=models.CharField("Enter any additional details",max_length=200,blank=True)
sales_invoice=models.FileField(upload_to='businessReqForm',null=True,blank=True)
purchase_invoice=models.FileField(upload_to='budinessReqForm',null=True,blank=True)
pay_slip=models.FileField(upload_to='budinessReqForm',null=True,blank=True)
talley_file=models.FileField(upload_to='budinessReqForm',null=True,blank=True)
views.py
#login_required
def businessRequestFormView(request):
if request.method == 'POST':
form = BusinessRequestForm(request.FILES,data=request.POST,input_user=request.user,)
if form.is_valid():
business_name=form.cleaned_data['business_name']
business_type=form.cleaned_data['business_type']
license_type=form.cleaned_data['license_type']
additional_details=form.cleaned_data['additional_detail']
tax_structure=form.cleaned_data['tax_structure']
s=Business_request()
s.user=request.user
s.business_name=business_name
s.business_type=business_type
s.license_type=license_type
s.additional_details=additional_details
if request.FILES['sales_invoice']:
sales_invoice=request.FILES['sales_invoice']
s.sales_invoice=sales_invoice
if request.FILES['purchase_invoice']:
purchase_invoice=request.FILES['purchase_invoice']
s.purchase_invoice=purchase_invoice
if request.FILES['pay_slip']:
pay_slip=request.FILES['pay_slip']
s.pay_slip=pay_slip
if request.FILES['talley_file']:
talley_file=request.FILES['talley_file']
s.talley_file=talley_file
s.save()
user=request.user
sender='info#accountingbuddy.org'
subject="AccountingBuddy.Org Business Setup Request Fm %s" % user.first_name
message="Business Name : %s , Business Type: %s , License Type: %s, Additional Details : %s , User %s , Phone %s, Email %s" % (business_name,business_type,license_type, additional_details, request.user,user.myprofile.phone_no,user.email)
recipients = ['keeganpatrao#gmail.com',]
recipients +=[user.email,]
send_mail(subject, message, sender, recipients)
return HttpResponseRedirect(reverse('accountingbuddy:thanks'))
else:
form = BusinessRequestForm(input_user=request.user)
return render(request, 'business_request_form.html', {'form': form})
Error
Environment:
Request Method: POST
Request URL: https://website.com/accountingbuddy/businessrequest/submit/
Django Version: 1.10.7
Python Version: 3.5.2
Installed Applications:
('mezzanine.boot',
'accountingbuddy',
'nova',
'bootstrap3',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.redirects',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.sitemaps',
'mezzanine.conf',
'mezzanine.core',
'mezzanine.generic',
'mezzanine.pages',
'mezzanine.blog',
'mezzanine.forms',
'mezzanine.galleries',
'mezzanine.twitter',
'mezzanine.accounts',
'filebrowser_safe',
'grappelli_safe',
'django.contrib.admin',
'django.contrib.staticfiles',
'django_comments')
Installed Middleware:
('django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'mezzanine.core.request.CurrentRequestMiddleware',
'mezzanine.core.middleware.RedirectFallbackMiddleware',
'mezzanine.core.middleware.TemplateForDeviceMiddleware',
'mezzanine.core.middleware.TemplateForHostMiddleware',
'mezzanine.core.middleware.AdminLoginInterfaceSelectorMiddleware',
'mezzanine.core.middleware.SitePermissionMiddleware',
'mezzanine.pages.middleware.PageMiddleware')
Traceback:
File "/webapps/accounting/accounting_home/myenv/lib/python3.5/site-packages/django/core/handlers/exception.py" in inner
42. response = get_response(request)
File "/webapps/accounting/accounting_home/myenv/lib/python3.5/site-packages/django/core/handlers/base.py" in _legacy_get_response
249. response = self._get_response(request)
File "/webapps/accounting/accounting_home/myenv/lib/python3.5/site-packages/django/core/handlers/base.py" in _get_response
187. response = self.process_exception_by_middleware(e, request)
File "/webapps/accounting/accounting_home/myenv/lib/python3.5/site-packages/django/core/handlers/base.py" in _get_response
185. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/webapps/accounting/accounting_home/myenv/lib/python3.5/site-packages/django/contrib/auth/decorators.py" in _wrapped_view
23. return view_func(request, *args, **kwargs)
File "/webapps/accounting/accounting_home/accounting_home/accountingbuddy/views.py" in businessRequestFormView
49. form = BusinessRequestForm(request.FILES,data=request.POST,input_user=request.user,)
Exception Type: TypeError at /accountingbuddy/businessrequest/submit/
Exception Value: __init__() got multiple values for argument 'input_user'

Related

How to assert response.data with queryset?

I am testing my API endpoints based on user roles that I have specified using choices in my models.py.
My problem is, when comparing my response.data with the queryset. I am getting this error:
AssertionError: OrderedDict([('count', 1), ('next', None)[228 chars])])]) != <QuerySet [<Project: New Housing 3>]>
def test_projects_list_only_contractor(self):
response = self.client.get(self.url, format='json')
if self.user.role == Role.CONTRACTOR and self.user.is_authenticated:
current_projects = self.user.contractor.projects.all()
self.assertEqual(response.status_code, status.HTTP_200_OK)
# print(response.data)
# [project for project in current_projects]
self.assertEqual(response.data, current_projects )
I have tried converting my current_projects to list, response.data to response.json()['results']
I have also tried using Projects.objects.filter(contractor=self.contractor) for my queryset

drf_yasg: How to define multipart/form-data in request body

Not able to generate a swagger file with multipart/form-data content-type in request
Description
I have a POST request to upload a document where I send the document sent in multipart/form-data. I have tried to describe the form data as such
This is how my request looks in postman
When I try to generate a swagger file. It gives me the following error
drf_yasg.errors.SwaggerGenerationError: cannot add form parameters when the request has a request body; did you forget to set an appropriate parser class on the view?
Minimal Reproduction
#swagger_auto_schema(
operation_id='Create a document',
operation_description='Create a document by providing file and s3_key',
manual_parameters=[
openapi.Parameter('file', openapi.IN_FORM, type=openapi.TYPE_FILE, description='Document to be uploaded'),
openapi.Parameter('s3_key', openapi.IN_FORM, type=openapi.TYPE_STRING, description='S3 Key of the Document '
'(folders along with name)')
],
responses={
status.HTTP_200_OK: openapi.Response(
'Success', schema=openapi.Schema(type=openapi.TYPE_OBJECT, properties={
'doc_id': openapi.Schema(type=openapi.TYPE_STRING, description='Document ID'),
'mime_type': openapi.Schema(type=openapi.TYPE_STRING, description='Mime Type of the Document'),
'version_id': openapi.Schema(type=openapi.TYPE_STRING, description='S3 version ID of the document')
})
)
}
)
In your View class, you need to set the MultiPartParser class, defining what type of media you are using:
from rest_framework.views import APIView
from rest_framework.parsers import MultiPartParser
class MyAPIView(APIView):
parser_classes = [MultiPartParser]
#swagger_auto_schema(
operation_id='Create a document',
operation_description='Create a document by providing file and s3_key',
manual_parameters=[
openapi.Parameter('file', openapi.IN_FORM, type=openapi.TYPE_FILE, description='Document to be uploaded'),
openapi.Parameter('s3_key', openapi.IN_FORM, type=openapi.TYPE_STRING, description='S3 Key of the Document '
'(folders along with name)')
],
responses={
status.HTTP_200_OK: openapi.Response(
'Success', schema=openapi.Schema(type=openapi.TYPE_OBJECT, properties={
'doc_id': openapi.Schema(type=openapi.TYPE_STRING, description='Document ID'),
'mime_type': openapi.Schema(type=openapi.TYPE_STRING, description='Mime Type of the Document'),
'version_id': openapi.Schema(type=openapi.TYPE_STRING, description='S3 version ID of the document')
})
)
}
)
def post(self, request, *args, **kwargs):
# Content of the post method

Http 403 Error: Details Request had insufficient authentification scopes Google Classroom Announcements

I am using Python Google Classroom API to retrieve announcements data.
Here is my code.
from fetch import Fetch
from googleapiclient.discovery import build
cred = 'catp.json'
get_credits = Fetch(cred) #fetching credential data
credit = get_credits()
service = build('Classroom', 'v1', credentials=credit)
setup = service.courses()
data = setup.list().execute()['courses']
course_names = []
course_ids = []
for i in range(len(data)):
course_names.append(data[i]['name'])
course_ids.append(data[i]['id'])
announcement_data = setup.announcements().list(courseId=course_ids[0]).execute()
But I receive the following Traceback Error:
Additional Information:
My project is registered under service account.
My role is Owner.
I have students account on Google Classroom.
To check whether the same error would be called if I tried to access announcements from a teachers account I created a Course in Classroom, using my Students account and posted some demo announcements.
The result was the same TracebackError. I also tried getting access to the data using API Explorer from Google, passing the same course ID as an argument. The data was received normally without any errors.
[Edit]
Here is the code for fetching credentials, Fetch(cred):
import os
import pickle
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
class Fetch:
def __init__ (self, credential_filename):
self.scopes = ['https://www.googleapis.com/auth/classroom.courses.readonly',
'https://www.googleapis.com/auth/classroom.announcements',
]
self.path = 'C:/frank/programs/python/google api'
self.credential_file = credential_filename
def __call__(self):
os.chdir(self.path)
token = open('token.pickle', 'rb')
creds = pickle.load(token)
if creds.valid == False:
if creds.expired == True:
creds.refresh(Request())
else:
try:
flow = InstalledAppFlow.from_client_secrets_file(self.credential_file, self.scopes)
creds = flow.run_local_server(port=0)
except FileNotFoundError:
print(f'{self.credential_file} does not exist')
token = open(self.token_file, 'wb')
pickle.dump(creds, token)
return creds

Allauth will not return the desired token payload

I have a django-rest-auth project called merchant. within it I have implemented django-restauth and allauth packages with JWT.
Everything works OK. However, I wish to return additional fields in the JWT token and here's my implementation of it.
In app.views.py
def jwt_response_payload_handler(token, user=None, request=None):
return {
'token': token,
'user': User_Serializer(user, context={'request':request}).data
}
serializers.py
class User_Serializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['email', 'username', 'is_staff']
settings.py
JWT_AUTH = {
'JWT_RESPONSE_PAYLOAD_HANDLER': 'merchant.coin_app.views.jwt_response_payload_handler',
'JWT_EXPIRATION_DELTA': datetime.timedelta(minutes=10),
'JWT_AUTH_HEADER_PREFIX': 'JWT'
}
The payload returned does not contain email/is_staff. Perhaps I am missing something.
The registered handler in the JWT_RESPONSE_PAYLOAD_HANDLER setting option is invoked after the JWT token is generated.
The handler requiring customization is JWT_PAYLOAD_HANDLER which creates the payload object that is tokenized and not JWT_RESPONSE_PAYLOAD_HANDLER.
In your project settings, configure
JWT_AUTH = {
'JWT_PAYLOAD_HANDLER': 'merchant.coin_app.views.jwt_payload_handler',
'JWT_EXPIRATION_DELTA': datetime.timedelta(minutes=10),
'JWT_AUTH_HEADER_PREFIX': 'JWT'
}
Then in your view, extend the result of rest_framework_jwt.utils.jwt_payload_handler
import rest_framework_jwt.utils.jwt_payload_handler as base_jwt_payload_handler
def jwt_response_payload_handler(user):
payload = base_jwt_payload_handler(user)
payload['user'] = User_Serializer(user).data
return payload

Passing variables to the Ansible httpapi plugin

I am looking for some help to add one additional variable to the HTTP plugin.
I wanted to pass variable 'ansible_domain' from the inventory or variable file.
I am able to pass to the username and password, but additional variables are not accepted from an inventory file or var file.
The end point required one more parameter to log in for few functions, and I am unable to proceed.
How can I fix this?
I am using Ansible 2.8.
options:
domain:
type: str
description:
- Specifies the api token path of the FTD device
env:
- name: ansible_domain
vars:
- name: ansible_domain
"""
import json
from ansible.module_utils.basic import to_text
from ansible.errors import AnsibleConnectionFailure
from ansible.module_utils.six.moves.urllib.error import HTTPError
from ansible.plugins.httpapi import HttpApiBase
from ansible.module_utils.connection import ConnectionError
BASE_HEADERS = {
'Content-Type': 'application/json',
}
DOMAIN1 = 'domain'
class HttpApi(HttpApiBase):
def login(self, username, password ):
if username and password:
payload = {'user': username, 'password': password, 'domain': DOMAIN1}
url = '/web_api/login'
response, response_data = self.send_request(url, payload)
else:
raise AnsibleConnectionFailure('Username and password are required for login')
try:
self.connection._auth = {'X-chkp-sid': response_data['sid']}
self.connection._session_uid = response_data['uid']
except KeyError:
raise ConnectionError(
'Server returned response without token info during connection authentication: %s' % response)
def logout(self):
url = '/web_api/logout'
response, dummy = self.send_request(url, None)
def get_session_uid(self):
return self.connection._session_uid
def send_request(self, path, body_params):
data = json.dumps(body_params) if body_params else '{}'
try:
self._display_request()
response, response_data = self.connection.send(path, data, method='POST', headers=BASE_HEADERS)
value = self._get_response_value(response_data)
return response.getcode(), self._response_to_json(value)
except AnsibleConnectionFailure as e:
return 404, 'Object not found'
except HTTPError as e:
error = json.loads(e.read())
return e.code, error
def _display_request(self):
self.connection.queue_message('vvvv', 'Web Services: %s %s' % ('POST', self.connection._url))
def _get_response_value(self, response_data):
return to_text(response_data.getvalue())
def _response_to_json(self, response_text):
try:
return json.loads(response_text) if response_text else {}
# JSONDecodeError only available on Python 3.5+
except ValueError:
raise ConnectionError('Invalid JSON response: %s' % response_text)

Resources