How do I access an S3Boto3StorageFile in Django for uploading to other locations?

Viewed 752

I am trying to upload files to Pipedrive, our CRM, when a lead is being submitted. Everything below here works according to plan, except my views.py when it calls the lead_file_upload() function. I get the following error:

expected str, bytes or os.PathLike object, not S3Boto3StorageFile

I am assuming this is a result of me using AWS S3 Storage and the file_data = default_storage.open(file.file.file, 'rb') on an S3Boto3StorageFile object. How do I open an S3Boto3StorageFile object which can then be passed on to the lead_file_upload() function?

models.py:

class Lead(models.Model):
    lead_name = models.CharField(max_length=50)
    timestamp = models.DateTimeField(auto_now_add=True)
    comments = models.TextField(blank=True)
    submitted_by = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, blank=True, on_delete=models.SET_NULL)

    def __str__(self):
        return self.lead_name

class LeadFile(models.Model):
    file = models.FileField(upload_to="lead/%Y/%m/%d", blank=True)
    lead = models.ForeignKey(Lead, on_delete=models.CASCADE)

forms.py:

from django import forms
from django.forms import ClearableFileInput
from .models import LeadFile

class LeadForm(forms.Form):
    coop_name = forms.CharField(max_length=50,
        label = "Name of lead")
    comments =  forms.CharField(max_length=2000, widget=forms.Textarea({}), required=False)

class LeadFileModelForm(forms.ModelForm):
    class Meta:
        model = LeadFile
        fields = ['file']
        widgets = {
            'file': ClearableFileInput(attrs={'multiple': True}),
        }
        labels = {
            'file': 'Add files',
        }

views.py:

def lead(request):
    title = 'Submit lead'
    user = request.user
    if request.method == 'POST':
        form = LeadForm(request.POST)
        fileform = LeadFileModelForm(request.POST, request.FILES)
        files = request.FILES.getlist('file')
        if form.is_valid() and fileform.is_valid():
            lead_name = form.cleaned_data['lead_name']
            comments = form.cleaned_data['comments']
            lead = Lead(lead_name=lead_name, comments=comments, submitted_by=user)
            lead.save()
            for f in files:
                file = LeadFile(file=f, offer=lead)
                file.save()
                file_data = default_storage.open(file.file.file, 'rb')
                lead_file_upload(file_data, offer)
                file_data.close()
            # Ship things to Pipedrive
            ship_note_to_pipedrive = lead_upload(lead)
    else:
        form = LeadForm()
        fileform = LeadFileModelForm()
    context = {'title': title, 'form': form, 'fileform': fileform}
    return render(request, 'lead.html', context)

The lead_file_upload() function:

def lead_file_upload(the_file, instance):
    headers = {'Accept': 'application/json', 'Content-Type': 'application/x-www-form-urlencoded'}
    files = {'file': the_file}
    data = {'deal_id': str(instance.lead_name)}
    pd_token = os.getenv("PIPEDRIVE_TOKEN")
    url = 'https://api.pipedrive.com/v1/files?api_token=%s' %pd_token
    r = requests.post(url, files=files, data=data, headers=headers)
    return r.status_code
0 Answers
Related