Reputation: 83
This is the merchant model:
class Merchant(models.Model):
merchant_token = models.CharField(max_length=255, unique=True)
and this is transaction model which the first field is linked to merchant_token on Merchant model:
class Transaction(models.Model):
transaction_merchant_token = models.ForeignKey(Merchant, on_delete=models.CASCADE)
First I get the merchant token with POST request then I get the merchant field with:
merchant = Merchant.objects.get(merchant_token__exact=posted_token)
but when I want to insert new transaction with posted token:
new_transaction = Transaction(
transaction_merchant_token=merchant.merchant_token
)
new_transaction.save()
I get ValueError exception:
Cannot assign "93C38:9VLlOUuaRq7J8boHyX80cI5MYy8yCpsb": Transaction.transaction_merchant_token must be a Merchant instance.
Upvotes: 2
Views: 1010
Reputation: 477794
Conceptually a ForeignKey
refers to a model object, not to the primary key of that object.
Yes, Django will make a field_id
(given the name of the ForeignKey
field is field
) to store the value of the primary key of the referred model object, and only the field_id
is a realy database column. But the field_id
, is not the same as a field
.
You can thus do two things:
you use the transaction_merchant_token
field, and you pass a Merchant
object:
new_transaction = Transaction(
transaction_merchant_token=merchant
)
you use the transaction_merchant_token_id
field, and then you pass the value of the primary key (for example the token):
new_transaction = Transaction(
transaction_merchant_token_id=merchant.pk
)
Note (nomenclature): that since the
ForeignKey
is thus not the token itself, it is common to name theForeignKey
after the model, not after the primary key of the model object, so I advise to rename your foreign key, for example to:class Transaction(models.Model): transaction_merchant = models.ForeignKey(Merchant, on_delete=models.CASCADE)
or even better:
class Transaction(models.Model): merchant = models.ForeignKey(Merchant, on_delete=models.CASCADE)
prefixing the attributes with the name of the current model is not necessary, and might be bad if you want to use "duck typing" in functions.
Upvotes: 1
Reputation: 2180
You should pass the merchant instance itself not the token
new_transaction = Transaction(transaction_merchant_token=merchant)
new_transaction.save()
I would redefine the models to look like this
class Merchant(models.Model):
token = models.CharField(max_length=255, unique=True)
class Transaction(models.Model):
merchant = models.ForeignKey(Merchant, on_delete=models.CASCADE)
Then when you want to get the merchant token, you do it this way
new_transaction.merchant.token
Upvotes: 1