Loading CSV to Odoo - csv

I would like to know if it is possible to directly import CSV file to Odoo using External API.
I have searched a bit and did not find a proper answer. Any link guidance would be appreciated.
Thanks!

You can use base_import module, you will need to properly configure your POST data if you want to use set_file controller, or use your own controller. For example, set_file controller function expects file body in file attribute, an import_id attribute (Integer value). Checkout the function definition:
class ImportController(http.Controller):
#http.route('/base_import/set_file', methods=['POST'])
def set_file(self, file, import_id, jsonp='callback'):
import_id = int(import_id)
written = request.env['base_import.import'].browse(import_id).write({
'file': file.read(),
'file_name': file.filename,
'file_type': file.content_type,
})
return 'window.top.%s(%s)' % (misc.html_escape(jsonp), json.dumps({'result': written}))

Related

How would I get access to a file I don't know the name of

I might describe this very poorly but here we go. What I am doing is creating a file with the user id from discord. In a different function, I want to access the file but I don't know the name of it
import json
import discord
#client.command()
async def function1(ctx):
test1 = 3
author = ctx.message.author.mention
await ctx.send(author)
with open(author+'.txt', 'w+') as outfile:
json.dump(test1, outfile)
#client.command()
async def function2(ctx):
with open(author+'.txt') as infile: #The "author+'.txt'" does not work because it does not know what author is.
test2 = json.load(infile)
await ctx.send(test2)
How would I get around this and access this file? I have an idea, I could save the author and then call it in function two. This would not work because there are many people using the bot. Am I on the right track? Thanks for the help in advance.

Import csv file in drf

I'm trying to create a view to import a csv using drf and django-import-export.
My example (I'm doing baby steps and debugging to learn):
class ImportMyExampleView(APIView):
parser_classes = (FileUploadParser, )
def post(self, request, filename, format=None):
person_resource = PersonResource()
dataset = Dataset()
new_persons = request.data['file']
imported_data = dataset.load(new_persons.read())
return Response("Ok - Babysteps")
But I get this error (using postman):
Tablib has no format 'None' or it is not registered.
Changing to imported_data = Dataset().load(new_persons.read().decode(), format='csv', headers=False) I get this new error:
InvalidDimensions at /v1/myupload/test_import.csv
No exception message supplied
Does anyone have any tips or can indicate a reference? I'm following this site, but I'm having to "translate" to drf.
Starting with baby steps is a great idea. I would suggest get a standalone script working first so that you can check the file can be read and imported.
If you can set breakpoints and step into the django-import-export source, this will save you a lot of time in understanding what's going on.
A sample test function (based on the example app):
def test_import():
with open('./books-sample.csv', 'r') as fh:
dataset = Dataset().load(fh)
book_resource = BookResource()
result = book_resource.import_data(dataset, raise_errors=True)
print(result.totals)
You can adapt this so that you import your own data. Once this works OK then you can integrate it with your post() function.
I recommend getting the example app running because it will demonstrate how imports work.
InvalidDimensions means that the dataset you're trying to load doesn't match the format expected by Dataset. Try removing the headers=False arg or explicitly declare the headers (headers=['h1', 'h2', 'h3'] - swap in the correct names for your headers).

How to return a nested json value with boto3

Using python3, boto3, with AWS. Trying to specify the return to one value instead of all that come back normally.
I have:
response = ec2client.describe_network_acls()
print(response["Associations"])
I get all three associations back:
[{'NetworkAclId': 'acl-58***221', 'NetworkAclAssociationId': 'aclassoc-267***56', 'SubnetId': 'subnet-e5###6bf'}, {'NetworkAclId': 'acl-5823###1', 'NetworkAclAssociationId': 'aclassoc-0a2###7a', 'SubnetId': 'subnet-ec0c###4'}]
But, I would like to just get the subnet id.
Thanks in advance, any assistance is appreciated!
import boto3
ec2_client=boto3.client('ec2')
response = ec2_client.describe_network_acls()
for acl in response['NetworkAcls']:
for association in acl['Associations']:
print(association['SubnetId'])
The trick is to look at the sample output in the boto3 documentation to determine available fields and lists.
response = ec2client.describe_network_acls()
subnet_ids = list(map(lambda assoc: assoc["SubnetId"], response))
print(subnet_ids)
If you need the code

How to retrieve data from self-made restfull_api

I trying to retrieve the information from my API via Y/views.py from another app in the same project. I am receiving the following error ([WinError 10061]). Although, i am able to perform get/post/put via my json_main.js. Thanks to all who support me in this journey. Please read what is already working. And as additional question I would ask why it is not possible to retrieve the data directly via my model/sqlite db.
I already created the following:
X/Views + X/Template.html. X/Views renders information from the backend to the X/template.html. Within this template there is a JSON script(working) that performs a POST/GET/PUT to the API(working) on image click.
The function ultimately results in a new record in API/Bestellingen. The information stored via this JSON function (incl. token authentication; csrf) should now be retrieved in the views.py of Y/view. I already created an example dict. that is rendered to Y/template.html
I tried several JSON request methods (coreapi, urllib2, urllib3, requests), but keep receiving the error as mentioned before. As already stated: JSON.js script does work. Doing the same via POSTMAN also works.
Since i am performing the same via .js and postman, I am quite sure that the variables (token, header and the request) should be ok.
I will show some short snippets of already working code. Herafter i will show the code that doesn't seem to work.
Information from X/views.py -> X/template.html
return render(request, 'smaakjes/smaakjes.html', {'Drank': super_dict})
X/Template.html (see onclick ="")
{% for key, value_list in Drank.items %}
<img onclick="PostImageDetails(this)" style="margin: 0 auto;" src="{{ value }}" id="{{ value }}">
JSON.js (works), sends information to http:127:0:0:0:8000/api/bestellingen. I can see the stored information via the API view.
xmlhttp.send(JSON.stringify({'url':imageSrc, 'username': imageId}))
Y/views.py -> renders information to Y/template.html(works)
def BestellingenDashboard(request):
Data = {'iets': '1'}
return render(request, 'homepage.html', {'bestellingen' : Data})
Once information has been stored in the API/bestellingen, I would like to retrieve the whole json dict. via python Y/Views.py and store it in the above 'Data'(that's ofc easy :)). Does somebody know what i am doing wrong? Why is postman working? Am i Missing a header or something? In my opinion, retrieving data from your own API should be very easy :D
from django.http import HttpResponse
from django.shortcuts import render
from api.models import Bestellingen
import json
import secrets
import requests
URL = "http://127.0.0.1:8000/api/bestellingen/"
data_json = json.dumps(data)
payload = {'json_payload': data_json}
r = requests.get(url=URL, headers={'Content-Type': 'application/json', 'token' : secrets.token_hex(40)}, json=payload)
a = r.json()
print(a)
def BestellingenDashboard(request):
Data = {'iets': '1'}
return render(request, 'homepage.html', {'bestellingen' : Data})
As you can read, most is working (api, endpoints, apiviews, rendering info from X-X.html,X.html->API. I now want to get the information in Y.views, so that i can use this information in Y/template.html

Django Rest Framework: what happened to my default Renderer?

I would like calls to /contacts/1.json to return json, 1.api to return browsableAPI, and calls with format=None aka /contacts/1/ to return a template where we call render_form. This way end-users can have pretty forms, and developers can use the .api format, and ajax/apps etc use .json. Seems like a common use case but something isn't clicking for me here in DRF...
Struggling with how DRF determines the Renderer used when no format is given. I found and then lost some info here on stack exchange that basically said to split the responses based on format. Adding the TemplateHTMLRenderer caused all sorts of pain. I had tried to split based on format but that is giving me JSON error below.
I don't understand the de facto way to define what renderer should be used. Especially when no format is provided. I mean, it "just works" when using Response(data). And I can get the TemplateHTMLRenderer to work but at the cost of having no default Renderer.
GET /contacts/1/ Gives the error:
<Contact: Contact object> is not JSON serializable
Using this code:
class ContactDetail(APIView):
permission_classes = (permissions.IsAuthenticatedOrReadOnly,
IsOwnerOrReadOnly,)
queryset = Contact.objects.all()
renderer_classes = (BrowsableAPIRenderer, JSONRenderer, TemplateHTMLRenderer,)
"""
Retrieve, update or delete a contact instance.
"""
def get_object(self, pk):
try:
return Contact.objects.get(pk=pk)
except Contact.DoesNotExist:
raise Http404
def get(self, request, pk, format=None):
contact = self.get_object(pk)
serializer = ContactSerializer(contact)
if format == 'json' or format == "api":
return Response(serializer.data)
else:
return Response({'contact': contact, 'serializer':serializer}, template_name="contact/contact_detail.html")
But GET /contacts/1.json , 1.api, or 1.html ALL give me the correct output. So it seems that I have created an issue with the content negotiation for the default i.e. format=None
I must be missing something fundamental. I have gone through the 2 tutorials and read the Renderers docs but I am unclear on what I messed up here as far as the default. I am NOT using the DEFAULT_RENDERERS in settings.py, didn't seem to make a difference if in default or inside the actual class as shown above.
Also if anyone knows a way to use TemplateHTMLRenderer without needing to switch on format value, I'm all ears.
EDIT: IF I use
if format == 'json' or format == "api" or format == None:
return Response(serializer.data)
else:
return Response({'contact': contact, 'serializer':serializer},
Then I am shown the browsable API by default. Unfortunately, what I want is the Template HTML view by default, which is set to show forms for end users. I would like to keep the .api format for developers.
TL; DR: Check the order of your renderers - they are tried in order of declaration until a content negotiation match or an error occurs.
Changing the line
renderer_classes = (BrowsableAPIRenderer, JSONRenderer, TemplateHTMLRenderer, )
to
renderer_classes = (TemplateHTMLRenderer, BrowsableAPIRenderer, JSONRenderer, )
Worked for me. I believe the reason is because the content negotiator starts at the first element in the renderer classes tuple when trying to find a renderer. When I have format==None, I'm thinking there is nothing else for DRF to go on, so it assumes I mean the "default" which seems to be the first in the tuple.
EDIT: So, as pointed out by #Ross in his answer, there is also a global setting in the settings.py for the project. If I remove my class level renderer_classes declaration and instead use this in settings.py
# ERROR
REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': (
'rest_framework.renderers.BrowsableAPIRenderer',
'rest_framework.renderers.JSONRenderer',
'rest_framework.renderers.TemplateHTMLRenderer',
)
}
Then I get a (different) JSON error. However, as long as
'rest_framework.renderers.BrowsableAPIRenderer',
is not listed first, for example:
# SUCCESS, even though JSON renderer is checked first
'DEFAULT_RENDERER_CLASSES': (
'rest_framework.renderers.JSONRenderer',
'rest_framework.renderers.TemplateHTMLRenderer',
'rest_framework.renderers.BrowsableAPIRenderer',
)
So if we hit BrowsableAPIRenderer before we try TemplateHTMLRenderer then we get an error - whether or not we are relying on renderer_classes or DEFAULT_RENDERER_CLASSES. I imagine it passes through JSONRenderer gracefully but for whatever reason BrowsableAPIRenderer raises an exception.
So I have simplified my view code after analyzing this...
def get(self, request, pk, format=None):
contact = self.get_object(pk)
serializer = ContactSerializer(contact)
if format == None:
return Response({'contact': contact, 'serializer':serializer}, template_name="contact/contact_detail.html")
else:
return Response(serializer.data)
..which better reflects what I was originally trying to do anyway.
When I look at the source code, the priority seems to be the order of the renderers specified in the DEFAULT_RENDERER_CLASSES parameter in settings.py:
REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES': (
'rest_framework.renderers.JSONRenderer',
'rest_framework.renderers.TemplateHTMLRenderer',
),
'DEFAULT_PARSER_CLASSES': (
'rest_framework.parsers.JSONParser',
'rest_framework.parsers.TemplateHTMLRenderer',
)
}
So, if you specify a bunch of renderer classes, the first renderer that is valid will be selected based on if it is valid for the request given the .json/.api/.html extension and the Accept: header (not content-type, as I said in the comment on your question).