0

So, I've been using Ruby on Rails for some time, and I'm wondering if there is something like .presence in Python/Django.

Presence returns the receiver if it is present otherwise returns nil.

object.presence is equivalent to:

object.present? ? object : nil

For example, something like:

state   = params[:state]   if params[:state].present?
country = params[:country] if params[:country].present?
region  = state || country || 'US'
becomes

region = params[:state].presence || params[:country].presence || 'US'

Anthony

dreftymac
  • 31,404
  • 26
  • 119
  • 182
Anthony
  • 931
  • 1
  • 13
  • 30
  • 1
    `d = {'foo': 'asad', 'bar': 'asdfsfs'}; d.get('foo'); d.get('foobar')`. The former will return `asad` and the latter will return `None` – han solo Mar 15 '19 at 16:58
  • Describe the purpose of the function here. And have you checked the list of Python built-ins? – Carcigenicate Mar 15 '19 at 16:58
  • 3
    For the sake of clarity, `presence` and `present?` are not built-in Ruby methods; they're [defined by Rails](https://api.rubyonrails.org/classes/Object.html#method-i-presence). – Jordan Running Mar 15 '19 at 17:05
  • 3
    I don't think it's necessary, becase python's truthiness criteria is the same as rails' `present?`. In ruby, only nil and false are "falsey" whereas in Python, empty strings/arrays/objects are also "falsey" (see https://docs.python.org/2.4/lib/truth.html). So, you could just say `params = {"state": "", "country": ""}; result = params.get("state") or params.get("country") or "US"` and result would equal "US". – max pleaner Mar 15 '19 at 17:13
  • 1
    For the sake of clarity, this question provides an overview of `present?`: https://stackoverflow.com/a/20663389/1779477 – idmean Mar 15 '19 at 18:44

2 Answers2

4

In Python, you can achieve this by doing the following, assuming params is a dict:

state = params.get('state')
country = params.get('country')
region = 'US' if (state and country) else None

The method dict.get(key) will return the value associated to the key that has been passed. If no such key exists, it returns None.

If you need to replace the empty values with actual empty strings, you may do this instead:

state = params.get('state', '')
country = params.get('country', '')
region = 'US' if (state and country) else ''

Overall, the "Pythonic" way of doing this is to use a Form:

class Address(Model):
    state = ...
    country = ...
    region = ...

AddressForm = modelform_factory(Address)

#inside view
def view(request):
    if request.method == 'POST':
        form = AddressForm(request.POST, request.FILES)

        if form.is_valid():
            address = form.save(commit=False)
            address.region = 'US' if address.state and address.country
            address.save()

By creating a custom AddressForm class you can do this processing automatically on the instance before saving it. This is the precise role of Form classes.

sleblanc
  • 3,821
  • 1
  • 34
  • 42
  • Disclaimer, I haven't used Django in a while and I have based this answer by reading the documentation, without actually testing this. – sleblanc Mar 30 '19 at 14:19
0

The accepted answer is incorrect.

The ruby version translated to python is roughly (except for truthiness edge cases):

region = params.get('state') or params.get('country') or 'US'

sleblancs answer instead sets the region to 'US' if state and country is set. Completely different.