Django REST API: Queryset with arguments - django-rest-framework

folks: I am trying to get the details of an entry in the database table through Django REST Framework with "url arguments" I am using the following code to get the value of "symbol" parameter however, I am getting the runtime error on the command line related to base_name. Here is the detail of my code:
class ticker_detail_full_view(viewsets.ModelViewSet):
serializer_class = ticker_detail_full
def get_queryset(self):
ticker = self.kwargs['symbol']
return ticker.objects.filter(symbol = ticker)
url: http://localhost:8000/qres/ticker_detail_full/?symbol=AMZN
I am getting the following error on the Django command-line:
router.register('ticker_detail_full', views.ticker_detail_full_view)
File
"/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/rest_framework/routers.py",
line 82, in register
base_name = self.get_default_base_name(viewset)
File
"/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/rest_framework/routers.py",
line 161, in get_default_base_name
assert queryset is not None, 'base_name argument not specified, and could ' \
AssertionError: base_name argument not specified, and could not
automatically determine the name from the viewset, as it does not have
a .queryset attribute.

Related

boto3 and lambda: Invalid type for parameter KeyConditionExpression when using DynamoDB resource and localstack

I'm having very inconsistent results when trying to use boto3 dynamodb resources from my local machine vs from within a lambda function in localstack. I have the following simple lambda handler, that just queries a table based on the Hash Key:
import boto3
from boto3.dynamodb.conditions import Key
def handler(event, context):
dynamodb = boto3.resource(
"dynamodb", endpoint_url=os.environ["AWS_EP"]
)
table = dynamodb.Table("precalculated_scores")
items = table.query(
KeyConditionExpression=Key("customer_id").eq(event["customer_id"])
)
return items
The environment variable "AWS_EP" is set to my localstack DNS when protyping (http://localstack:4566).
When I call this lamdba I get the following error:
{
"errorMessage": "Parameter validation failed:\nInvalid type for parameter KeyConditionExpression, value: <boto3.dynamodb.conditions.Equals object at 0x7f7440201960>, type: <class 'boto3.dynamodb.conditions.Equals'>, valid types: <class 'str'>",
"errorType": "ParamValidationError",
"stackTrace": [
" File \"/opt/code/localstack/localstack/services/awslambda/lambda_executors.py\", line 1423, in do_execute\n execute_result = lambda_function_callable(inv_context.event, context)\n",
" File \"/opt/code/localstack/localstack/services/awslambda/lambda_api.py\", line 782, in exec_local_python\n return inner_handler(event, context)\n",
" File \"/var/lib/localstack/tmp/lambda_script_l_dbef16b3.py\", line 29, in handler\n items = table.query(\n",
" File \"/opt/code/localstack/.venv/lib/python3.10/site-packages/boto3/resources/factory.py\", line 580, in do_action\n response = action(self, *args, **kwargs)\n",
" File \"/opt/code/localstack/.venv/lib/python3.10/site-packages/boto3/resources/action.py\", line 88, in __call__\n response = getattr(parent.meta.client, operation_name)(*args, **params)\n",
" File \"/opt/code/localstack/.venv/lib/python3.10/site-packages/botocore/client.py\", line 514, in _api_call\n return self._make_api_call(operation_name, kwargs)\n",
" File \"/opt/code/localstack/.venv/lib/python3.10/site-packages/botocore/client.py\", line 901, in _make_api_call\n request_dict = self._convert_to_request_dict(\n",
" File \"/opt/code/localstack/.venv/lib/python3.10/site-packages/botocore/client.py\", line 962, in _convert_to_request_dict\n request_dict = self._serializer.serialize_to_request(\n",
" File \"/opt/code/localstack/.venv/lib/python3.10/site-packages/botocore/validate.py\", line 381, in serialize_to_request\n raise ParamValidationError(report=report.generate_report())\n"
]
}
Which is a weird error - From what I researched on other question it usually happens when using the boto3 client, but I am using boto3 resources. Furthermore, when I run the code locally in my machine it runs fine.
At first I thought that it might be due to different versions for boto3 (My local machine is using version 1.24.96, while the version inside the lambda runtime is 1.16.31). However I downgraded my local version to the same as the one in the runtime, and I keep getting the same results.
After some answers on this question I managed to get the code working against actual AWS services, but it still won't work when running against localstack.
Am I doing anything wrong? Os might this be a bug with localstack?
--- Update 1 ---
Changing the return didn't solve the problem:
return {"statusCode": 200, "body": json.dumps(items)}
--- Update 2 ---
The code works when running against actual AWS services instead of running against localstack. Updating the question with this information.
This works fine from both my local machine and Lambda:
import json, boto3
from boto3.dynamodb.conditions import Key
def lambda_handler(event, context):
dynamodb = boto3.resource(
"dynamodb",
endpoint_url="https://dynamodb.eu-west-1.amazonaws.com"
)
table = dynamodb.Table("test")
items = table.query(
KeyConditionExpression=Key("pk").eq("1")
)
print(items)
return {
'statusCode': 200,
'body': json.dumps('Hello from Lambda!')
}
Also be sure that event["customer_id"] is in fact a string value as expected by the eq function.
I would check to ensure you have the endpoint setup correctly and that you have the current version deployed.
It may also be the fact you are trying to return the results of your API call via the handler, instead of a proper JSON response as expected:
return {
'statusCode': 200,
'body': json.dumps(items)
}

How to provide the "result.has_errors()" and "result.has_validation_errors()" attributes when using import_data method for Django import_export

I need to make changes to a csv file being imported using the module import_Export for Django. I implement the import_data method for this but get the error 'Dataset' object has no attribute 'has_errors'
Traceback (most recent call last):
File "C:\Program Files\Python36\lib\site-packages\django\core\handlers\exception.py", line 34, in inner
response = get_response(request)
File "C:\Program Files\Python36\lib\site-packages\django\core\handlers\base.py", line 115, in _get_response
response = self.process_exception_by_middleware(e, request)
File "C:\Program Files\Python36\lib\site-packages\django\core\handlers\base.py", line 113, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Program Files\Python36\lib\site-packages\django\utils\decorators.py", line 130, in _wrapped_view
response = view_func(request, *args, **kwargs)
File "C:\Program Files\Python36\lib\site-packages\django\views\decorators\cache.py", line 44, in _wrapped_view_func
response = view_func(request, *args, **kwargs)
File "C:\Program Files\Python36\lib\site-packages\django\contrib\admin\sites.py", line 231, in inner
return view(request, *args, **kwargs)
File "C:\Program Files\Python36\lib\site-packages\import_export\admin.py", line 316, in import_action
if not result.has_errors() and not result.has_validation_errors():
Exception Type: AttributeError at /admin/engine/mtg/import/
Exception Value: 'Dataset' object has no attribute 'has_errors'
How can I provide the result.has_error() and result.has_validation_errors() when I return my customized dataset to avoid this error? Here is where I implement the method
Admin
class ModelResource(resources.ModelResource):
def import_data(self, dataset, dry_run=False, raise_errors=True,use_transactions=None, collect_failed_rows=False, **kwargs):
new_dataset = do_stuff(dataset)
return new_dataset
The documentation states that the first thing that the import_data method does is create a "result" instance containing error information. I'm assuming this is what I need maybe? But I don't know how to gain access to it or return it with my new dataset[Import Data workflow][1]
[1]: https://django-import-export.readthedocs.io/en/latest/import_workflow.html?highlight=before)import
You shouldn't need to override has_errors() and has_validation_errors() because the logic should be handled for you.
Generally you shouldn't be over-riding import_data() because this is where the import logic happens. Pass a valid Dataset object into import_data() as the first arg. I suggest having a quick look at the source, because this will clarify what is going on.
If you need to modify the imported data, then there are several hooks you can use. This is where you subclass the base Resource and add your own logic.
This example is based on the django-import-export example app:
class BookResource(resources.ModelResource):
def before_import_row(self, row, row_number=None, **kwargs):
"""
Override to add additional logic.
"""
pass
def before_save_instance(self, instance, using_transactions, dry_run):
"""
Override to add additional logic.
"""
pass
class Meta:
model = Book
fields = ('id', 'author_email', 'price')
Then you can call this with:
rows = [
('book1', 'email#example.com', '10.25'),
('book2', 'email#example.com', '10.25'),
('book1', 'email#example.com', '10.25'),
]
dataset = tablib.Dataset(*rows, headers=['name', 'author_email', 'price'])
book_resource = BookResource()
result = book_resource.import_data(dataset)
print(result.totals)

Getting a WARNING and ERROR: unexpected keyword argument 'queryset'

Unexpected keyword argument 'queryset' in constructor call [E:unexpected-keyword-arg]
Tried using form_kwargs as shown on stack overflow here:
# How to use the new form_kwargs on an inline formset?
if request.method == "POST":
ctx['formset'] = project_comparison_form_set(
data=request.POST, files=request.FILES, queryset=ctx['projects'])
ctx['data1'] = request.POST.copy
if ctx['formset'].is_valid():
instances = ctx['formset'].save(commit=False)
for project in instances:
project.save()
Getting both a warning and error message in pylint Unexpected keyword argument 'queryset' in constructor call [E:unexpected-keyword-arg]
You don't show where project_comparison_form_set is defined, but i assume that it is a modelformset_factory.
Here, you do not have the queryset argument. If you do want to pass a queryset, you can pass it to the formset and the formset than to the modelformset_factory.
Check the documentation https://docs.djangoproject.com/en/4.1/topics/forms/modelforms/#changing-the-queryset.

How can I use scrapy to fetch the data through proxy, at the same time I do not use middlewares

I am using scrapy to fetch the data, I bought some proxies. I read the scrapy doc, I found that if I want to use proxy, I should write middlewares. Now my question is how can I use proxy without middlewares? I tried like this:
def start_requests(self):
name = my_name
password = password
proxy = my proxy
return[
FormRequest(url,formate={'account':my_name,'password':password},
meta={'proxy':proxy},
callback=self.after_login)
]
def after_login(self, response):
response.xpath(.....)
I got TypeError:argument of type 'NoneType' is not iterable
Here is the Traceback:
Traceback (most recent call last):
File "/home/think/sjs-project/sjs/venv/local/lib/python2.7/site-packages/twisted/internet/endpoints.py", line 542, in connect
timeout=self._timeout, bindAddress=self._bindAddress)
File "/home/think/sjs-project/sjs/venv/local/lib/python2.7/site-packages/twisted/internet/posixbase.py", line 482, in connectTCP
c = tcp.Connector(host, port, factory, timeout, bindAddress, self)
File "/home/think/sjs-project/sjs/venv/local/lib/python2.7/site-packages/twisted/internet/tcp.py", line 1165, in __init__
if abstract.isIPv6Address(host):
File "/home/think/sjs-project/sjs/venv/local/lib/python2.7/site-packages/twisted/internet/abstract.py", line 522, in isIPv6Address
if '%' in addr:
TypeError: argument of type 'NoneType' is not iterable
What am I doing wrong? Thanks very much.

Unique Key Error when exporting Scrapy data to Elasticsearch

I'm attempting to use the scrapy elasticsearch pipeline (here: https://github.com/knockrentals/scrapy-elasticsearch) to put data into elasticsearch. however i get the following error, i'm aware that it's related to the ELASTICSEARCH_UNIQ_KEY value that is currently set at 'url' but i have no idea what it should be set to.
Similar posts on here recommend solutions that involve creating a field for the unique key but i don't understand what this means.
Here's my error message:
2015-08-05 11:34:40 [scrapy] ERROR: Error processing {'link': [u'http://www.meetup.com/Search-Meetup-Karlsruhe/events/192357732/'],
'title': [u'Suchen in der vernetzten Welt']}
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/twisted/internet/defer.py", line 588, in _runCallbacks
current.result = callback(current.result, *args, **kw)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/scrapyelasticsearch/scrapyelasticsearch.py", line 70, in process_item
self.index_item(item)
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/scrapyelasticsearch/scrapyelasticsearch.py", line 52, in index_item
local_id = hashlib.sha1(item[uniq_key]).hexdigest()
File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/scrapy/item.py", line 56, in __getitem__
return self._values[key]
KeyError: 'url'
Similar posts on here recommend solutions that involve creating a
field for the unique key but i don't understand what this means.
Declare a field in your Item with the name you configured in the ELASTICSEARCH_UNIQ_KEY.
import scrapy
class DemoItem(scrapy.Item):
url = scrapy.Field() # ELASTICSEARCH_UNIQ_KEY
class DemoSpider(scrapy.Spider):
name = 'demo'
start_urls = ['http://www.example.com']
def parse(self, response):
demoItem = DemoItem()
demoItem['url'] = response.url
yield demoItem

Resources