0

I'm using django-salesforce to get a list of Contacts (child) and the Accounts (parent) associated with them.

In my models.py, what is the syntax for defining a field in the Contact class to hold the Account name?

Here's my models.py:

from django.db import models
from salesforce.models import SalesforceModel

class Account(SalesforceModel):
    Name = models.CharField(max_length=255)

    def __unicode__(self):
        return u'%s %s' % (self.Name, self.Id)

class Contact(SalesforceModel):
    FirstName = models.CharField(max_length=255)
    LastName = models.CharField(max_length=255)
    AccountId = models.CharField(max_length=255)

    def __unicode__(self):
        return u'%s %s %s' % (self.FirstName, self.LastName, self.AccountId)

I've not been able to find any examples, but I was thinking it would look something like this:

AccountName = models.ForeignKey(Account, db_column='Name')
hynekcer
  • 14,942
  • 6
  • 61
  • 99

2 Answers2

2

I'm the author of django-salesforce. You shouldn't have to do anything too special to make a Foreign Key relationship work, although you will likely need to be explicit about your key names. Here's a very trivial example, found in the example app contained in the source tarball:

class User(SalesforceModel):
    Email = models.CharField(max_length=100)
    LastName = models.CharField(max_length=80)
    FirstName = models.CharField(max_length=40)
    IsActive = models.BooleanField()

class Account(SalesforceModel):
    Owner = models.ForeignKey(User, db_column='OwnerId')

Because the default Salesforce naming conventions are different than Django's, you must explicitly tell it the name of your foreign key field. Otherwise it will use the Django convention of appending '_id' rather than the SF convention of appending 'Id'

Then, similar to that mentioned in David's response, you'd access the first name of an account owner with:

a = models.Account.objects.all()[0]
print a.Owner.FirstName
Phil Christensen
  • 415
  • 3
  • 11
  • I'm writing tests based on the tests in the source tarball. I've got the User model as you listed. When I add the Account model, I get the following error: django.db.utils.DatabaseError: (1075, 'Incorrect table definition; there can be only one auto column and it must be defined as a key'). I'm thinking that perhaps the DATABASES setting is causing the problem. I've got two databases, 'default': 'ENGINE' 'django.db.backends.mysql' and 'salesforce': 'ENGINE' 'salesforce.backend'. Do you think Django is seeing the 'default', and tries to apply the MySQL constraints to the Salesforce table? – user2262804 Nov 14 '13 at 16:52
  • I'd need more info to be sure, but it sounds to me like it's an invalid model, probably with a duplicate field added to represent the 'Id' field at Salesforce. You don't need to specify a primary key when you're inheriting from SalesforceModel, because it automatically adds the default "Id" field common to most SFDC models. – Phil Christensen Jul 15 '14 at 20:35
1

The account name shouldn't be held in a field in Contact, since it's already held in Account (this is the purpose of database normalization- to reduce redundancy).

Instead you would connect it using a single ForeignKey:

class Contact(SalesforceModel):
    FirstName = models.CharField(max_length=255)
    LastName = models.CharField(max_length=255)
    Account = models.ForeignKey(Account)

and get the account name from a Contact object c with:

c.Account.Name
David Robinson
  • 77,383
  • 16
  • 167
  • 187
  • Thanks, this answer makes sense and it seems like that is the way it should work. When I try this I get an error: No such column 'Account_id' on entity 'Contact'. If you are attempting to use a custom field, be sure to append the '__c' after the custom field name. – user2262804 Apr 22 '13 at 17:22
  • Hi, this happens when I do manage.py shell: >>> c = Contact.objects.all() >>> c[0] I believe what's happening is that django is appending the _id to account. – user2262804 Apr 23 '13 at 14:51
  • Did you remember to syncdb, and are you sure you changed your models to the one in my answer? – David Robinson Apr 23 '13 at 14:59
  • Yes, I ran syncdb and models.py matches. This error came up when using sqlite. I tried using mysql and got a different error: django.db.utils.DatabaseError: (1075, 'Incorrect table definition; there can be only one auto column and it must be defined as a key'). – user2262804 Apr 23 '13 at 16:11
  • Thanks David, your answer was what I was looking for. Looks like the issue I'm facing now is a different problem. MySQL not liking multiple auto increment fields. – user2262804 Apr 24 '13 at 14:58
  • @user2262804: Django-salesforce works nice also with alternate non Salesforce databases by switching DATABASES['salesforce'] settings, but the parameter "db_column" should used for field definitions frequently. (You get id easily, even excessively by `inspectdb --verbosity=2`). I'm sure that auto increment fields are not duplicated in the recent versions. (I should remember "everything" after May 2013.) – hynekcer Sep 05 '17 at 19:20