netbox-community / pynetbox

Python API client library for Netbox.
Apache License 2.0
577 stars 172 forks source link

Problem with filters if filter value is Null #442

Open VictorPavlushin opened 2 years ago

VictorPavlushin commented 2 years ago

Netbox - v3.1.6 pynetbox - 6.5.0 Repeatability I think on all versions. Let's look at the request: https://demo.netbox.dev/api/dcim/racks/?site_id=21&location_id=null We'll get racks with no location. If we try to do the same through the pynetbox library: pynb.dcim.racks.filter(site_id=21, location_id=None) Then we get all the racks on this site. The request will look like: https://demo.netbox.dev/api/dcim/racks/?site_id=21 This applies to both the get request and all objects.

markkuleinio commented 2 years ago

Use location_id="null" (see https://github.com/netbox-community/pynetbox/issues/380)

VictorPavlushin commented 2 years ago

so i need to additionally keep track of the return value from the other request? It seems to me that this complicates and makes my code ugly. instead of: pynb.dcim.racks.filter(site_id=21, location=obj.location) like this: pynb.dcim.racks.filter(site_id=21, location=obj.location if obj.location else "null") It's not pretty in my opinion

markkuleinio commented 2 years ago

The problem/feature is apparently this (https://docs.python-requests.org/en/latest/user/quickstart/#passing-parameters-in-urls): "Note that any dictionary key whose value is None will not be added to the URL’s query string."

@zachmoody what do you think, could we change Request._make_call() to check for any None values and just replace them with "null"? Extra mention in release notes is probably needed.

VictorPavlushin commented 2 years ago

By the way, if you substitute "null" in the filter, for example, in vrf_id, then there will be an error: nb.ipam.prefixes.get(prefix=prefix.prefix, vrf_id=vrf) pynetbox.core.query.RequestError: The request failed with code 400 Bad Request: {'vrf': ['Related objects must be referenced by numeric ID or by dictionary of attributes. Received an unrecognized value: null']}

markkuleinio commented 2 years ago

I don't get why the error says about vrf while your .get() is using vrf_id.

What does your vrf variable contain?

Anyway, this is how it looks like here (pynetbox ~6.5.0, NetBox 3.2.0-dev):

>>> netbox.ipam.prefixes.get(prefix="10.1.1.0/24").vrf is None
True

>>> netbox.ipam.prefixes.get(prefix="10.2.2.0/24").vrf
TestVRF

>>> netbox.ipam.prefixes.get(prefix="10.1.1.0/24", vrf_id="null")
10.1.1.0/24

>>> netbox.ipam.prefixes.get(prefix="10.2.2.0/24", vrf_id="null")
(not found, correct)
VictorPavlushin commented 2 years ago

Indeed, my mistake, the "null" value was passed to the "create" function: nb.ipam.prefixes.create(obj)

zachmoody commented 2 years ago

@zachmoody what do you think, could we change Request._make_call() to check for any None values and just replace them with "null"? Extra mention in release notes is probably needed.

I don't know, I agree it is cleaner, but I also worry it could result in some astonishing behavior for clients. E.g. someone initializing a variable that winds up getting passed to get or filter as None now has very confusing result. I think the current behavior with null is worth calling out in the docs though.