'simple-salesforce create custom field

I'm having difficulties creating a field on a custom object using simple-salesforce. If I trace down into the code I can see that the API is returning success, but I don't see that the field is created on the object.

I know next to nothing about Salesforce, so it is possible that I'm missing something on how permissions or visibility need to be set when I create the custom object. I believe that I have Admin and API permissions.

Environment:

  • python: 3.9.7
  • simple-salesforce: 1.11.6

Here is my test script.

# -*- coding: utf-8 -*-
import os

from simple_salesforce import Salesforce


secrets = dict()
secrets["username"] = os.environ["DEV_SALESFORCE_USER"]
secrets["password"] = os.environ["DEV_SALESFORCE_PASSWORD"]
secrets["security_token"] = os.environ["DEV_SALESFORCE_SECURITY_TOKEN"]
sf = Salesforce(
    username=secrets["username"],
    password=secrets["password"],
    security_token=secrets["security_token"],
    client_id="Data Engineering",
    domain="test",
)
mdapi = sf.mdapi

obj_api_name = "NatesCustomObject__c"
obj_label = "Nates Custom"
field_api_name = "SomeText__c"
field_label = "Some Text"

# Try to delete the custom object so we are starting from scratch.
try:
    mdapi.CustomObject.delete(obj_api_name)
except Exception:
    pass

# Define the custom object.
custom_object = mdapi.CustomObject(
    fullName=obj_api_name,
    label=obj_label,
    pluralLabel="Nates Custom Objects",
    nameField=mdapi.CustomField(label="Name", type=mdapi.FieldType("Text")),
    deploymentStatus=mdapi.DeploymentStatus("Deployed"),
    sharingModel=mdapi.SharingModel("Read"),
)
# Create the custom object.
mdapi.CustomObject.create(custom_object)

# Define the custom field.
field = mdapi.CustomField(
    fullName=f"{obj_api_name}.{field_api_name}", label=field_label, type=mdapi.FieldType("Text"), length=10
)
# Create the custom field.
mdapi.CustomField.create(field)

describe_response = sf.NatesCustomObject__c.describe()
for f in describe_response["fields"]:
    print(f["name"])

Script Output:

Id
OwnerId
IsDeleted
Name
CreatedDate
CreatedById
LastModifiedDate
LastModifiedById
SystemModstamp


Solution 1:[1]

Through some research I found that I needed to make that field editable in the Profile associated with the user.

# Get the current profile
profile = mdapi.Profile.read("Integration User")

# Add the new field to the profile
field_security = mdapi.ProfileFieldLevelSecurity(
    field=f"{obj_api_name}.{field_api_name}", editable=True, readable=True
)
profile.fieldPermissions.append(field_security)

# Remove a couple of tabs that aren't owned by the current user.
uneditable_tabs = ["standard-LightningInstrumentation", "standard-Snippet"]
profile.tabVisibilities = [t for t in profile.tabVisibilities if t.tab not in uneditable_tabs ]

# Update the profile
mdapi.Profile.update(profile)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Nathan Atkins