django-oscar / django-oscar-api

RESTful JSON API for django-oscar

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Add product with options not working

babanazar opened this issue · comments

Hi,
I have forked and cloned django oscar api. When I try to call /basket/add-service/ with options, it is not working. I see it on request.data but it does not appear in p_ser.validated_data property.
Can you please help?

EDIT:
By /basket/add-service/ I meant /basket/add-product/

Hi Babanazar,

I don’t know where this add-service endpoint is coming from but this is not part of oscarapi. How you can add options to a product is to be seen in the unit tests:

def test_add_put_product_option(self):

There is also an example to be found in the documentation.

@babanazar Did the examples mentioned above help you?

@maerteijn Thank you for your answer.
But unfortunately, I still can not solve the issue. I see the 'options' in request.data variable but it does not exist in p_ser.validated_data. Thus it is ignored and not added.

I have been debugging lately. I think my issue is similar to issue in the link.
https://stackoverflow.com/questions/68687339/django-rest-framework-cant-identify-serializer-field-name

image

I share screenshot of code where I think my input does not match. Here in match = regex.match(field), match is None even if field = 'options'.

@babanazar When I run the test mentioned above and manually inspect the options, I can see they are there:

(oscarapi) martijn@neopro:~/Dev/oss/django-oscar-api (master)$ sandbox/manage.py test oscarapi.tests.unit.testbasket.BasketTest.test_add_put_product_option
Creating test database for alias 'default'...
System check identified no issues (0 silenced).

ipdb> l
    122             quantity = p_ser.validated_data["quantity"]
    123             options = p_ser.validated_data.get("options", [])
    124
    125             import ipdb; ipdb.set_trace()
    126
--> 127             basket_valid, message = self.validate(basket, product, quantity, options)
    128             if not basket_valid:
    129                 return Response(
    130                     {"reason": message}, status=status.HTTP_406_NOT_ACCEPTABLE
    131                 )
    132

ipdb> options 
[OrderedDict([('option', <Option: Color>), ('value', 'red')])]

So this is not an Oscar API issue, so what did you do in your project? Did you overrride the views or serializers, and if so, please provide what you changed? And what is this add-service endpoint?

@maerteijn thank you for response.
I forked and modified the project. I renamed product model to service. I want to build a platform that sells services instead of products.
The rest of the project is functional. This part also passes the tests but I can not manage to add options via postman request.

Ok, please try to follow a similar scenario with the requests library as described in the documentation.

Is it still not possible to add options? (check: Did you provide the correct option_url)?

@maerteijn , I followed exactly the same steps described in the documentation. I still can not add options.
I provide the log of my steps in the attachment.
Can you please help me solve the issue with customizaiton?

logs.txt

@babanazar Ehm sorry, but your log is very messy and when you are trying to print the content of the basket lines, they are empty. That should ring a bell:

>> response = session.post('http://localhost:8000/api/basket/add-service/', json=data)
>>> response = session.get('http://localhost:8000/api/basket/')
>>> lines_url = response.json()['lines']
>>> response = session.get(lines_url)
>>> print(response.content)
b'[]'

When there is nothing in your basket, there are no options of course. Please check the output of the response your first line response = session.post('http://localhost:8000/api/basket/add-service/', json=data) as it was not succesful adding anything to your basket.

Please use the browsable api at http://localhost:8000/api/basket/ to check if something is in your basket lines at all. With a vanilla Oscar API install you can post this to the http://localhost:8000/api/basket/add-product/ endpoint :

{
    "url": "http://localhost:8000/api/products/1/",
    "quantity": 1,
    "options": [{
        "option": "http://localhost:8000/api/options/1/", "value": "blue"
    }]
}

Your basket result looks like this then:

{
    "id": 2,
    "status": "Open",
    "lines": "http://localhost:8000/api/baskets/2/lines/",
    "url": "http://localhost:8000/api/baskets/2/",
    "total_excl_tax": "10.00",
    "total_excl_tax_excl_discounts": "10.00",
    "total_incl_tax": "10.00",
    "total_incl_tax_excl_discounts": "10.00",
    "total_tax": "0.00",
    "currency": "EUR",
    "voucher_discounts": [],
    "offer_discounts": [],
    "is_tax_known": true
}

And when you follow the lines url you should see something like this:

[
    {
        "url": "http://localhost:8000/api/baskets/2/lines/5/",
        "product": "http://localhost:8000/api/products/1/",
        "quantity": 1,
        "attributes": [
            {
                "url": "http://localhost:8000/api/baskets/2/lines/5/lineattributes/2/",
                "value": "blue",
                "option": "http://localhost:8000/api/options/1/"
            }
        ],
        "price_currency": "EUR",
        "price_excl_tax": "10.00",
        "price_incl_tax": "10.00",
        "price_incl_tax_excl_discounts": "10.00",
        "price_excl_tax_excl_discounts": "10.00",
        "is_tax_known": true,
        "warning": null,
        "basket": "http://localhost:8000/api/baskets/2/",
        "stockrecord": "http://localhost:8000/api/products/1/stockrecords/1/",
        "date_created": "2021-12-14T19:33:35.588563Z",
        "date_updated": "2021-12-14T19:33:35.588625Z"
    }
]

As you can see, the option becomes a line attribute with the posted value blue.

I share screenshot of code where I think my input does not match. Here in match = regex.match(field), match is None even if field = 'options'.

I don't think your problem has anything to do with https://stackoverflow.com/questions/68687339/django-rest-framework-cant-identify-serializer-field-name

I forked and modified the project. I renamed product model to service. I want to build a platform that sells services instead of products.

I would recommend not to do that. Just rename some of the endpoints if you are exposing your api to other developers, but keep the django model names etc. It will cause nothing but trouble with the Oscar ecosystem.

It worked when I tried steps in the documentation in the command line. It also worked with raw data in postman. I think the issue is with my data format in x-www-form-urlencoded form. As a result, the issue is solved. Thanks for your guidance.