sephrrr
sephrrr

Reputation: 83

must be instance django

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

Answers (2)

willeM_ Van Onsem
willeM_ Van Onsem

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:

  1. you use the transaction_merchant_token field, and you pass a Merchant object:

    new_transaction = Transaction(
        transaction_merchant_token=merchant
    )
  2. 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 the ForeignKey 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

Nour Wolf
Nour Wolf

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

Related Questions