Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

django Charfield suitable for a primary key?

In my django model I would like to set the field unique_id below to be the primary key as this will be the field used in queries for the model. It satisfies unique=True and null=False. However as django sets an AutoField to primary key in the background I'm unsure whether a CharField (which uses a unique 3 character code) is suitable as a primary key or whether this will be sub-optimal?

class PaymentMethod(models.Model):
    unique_id = models.CharField(max_length=3)
    last_updated = models.DateTimeField(auto_now=True)
like image 943
Yunti Avatar asked Jun 30 '16 07:06

Yunti


People also ask

How do I refer primary key in Django?

If you'd like to specify a custom primary key, specify primary_key=True on one of your fields. If Django sees you've explicitly set Field. primary_key , it won't add the automatic id column. Each model requires exactly one field to have primary_key=True (either explicitly declared or automatically added).

Does Django support composite primary key?

Django does not support composite primary keys.

How can create primary key in Django model?

By default, Django adds an id field to each model, which is used as the primary key for that model. You can create your own primary key field by adding the keyword arg primary_key=True to a field. If you add your own primary key field, the automatic one will not be added.

What does CharField mean in Django?

CharField is generally used for storing small strings like first name, last name, etc. To store larger text TextField is used. The default form widget for this field is TextInput. CharField has one extra required argument: CharField.max_length. The maximum length (in characters) of the field.


2 Answers

There is nothing wrong with setting the CharField to be a primary key, by changing the model to be:

class PaymentMethod(models.Model):
    unique_id = models.CharField(max_length=3, primary_key=True)
    last_updated = models.DateTimeField(auto_now=True)

In actual fact if the unique_id is the field you will be querying it makes perfect sense to use it. Your other options are to use your existing model but with unique=True:

class PaymentMethod(models.Model):
    unique_id = models.CharField(max_length=3, unique=True)
    last_updated = models.DateTimeField(auto_now=True)

In this case your primary key will be an auto incrementing integer as you previously stated.

Another option depending on the number of records you are looking to store in the PaymentMethod models; and where the data is used elsewhere within your application. Is too look into using a model choices field. The model choices field might be on your payments or order model (depends on your application and what you are trying to do). This removes the need for a foreignkey and potentially reduces the number of queries in your app.

It could look something like this:

class Payment(models.Model):
    VISA = 'VIS'
    CREDIT = 'CRE'
    MASTER_CARD = 'MAS'
    PAYPAL = 'PAL'
    PAYMENT_OPTIONS= (
        (VISA, 'Visa'),
        (CREDIT, 'Credit Card'),
        (MASTER_CARD, 'Master Card'),
        (PAYPAL, 'Paypal')
    )

    items = models.ForeignKey(Item)
    date = models.DateField(auto_now=True)
    ...
    payment_method = models.CharField(max_length=3, choices=PAYMENT_OPTIONS, default=VISA)

The PAYMENT_OPTIONS can be used to render dropdown boxes on the forms when using django model forms. Otherwise the users selection is limited to the options listed within this model. This method would be a lot more efficient if you only have a small subset of PaymentMethod(s).

like image 156
Matt Seymour Avatar answered Oct 17 '22 18:10

Matt Seymour


It's possible to use CharField as primary key. You just have to mark the field as primary key.

field_name = models.CharField(primary_key=True, max_length=100)

But I wouldn't recommend it because:

  • Primary keys are used in urls (typically in Rest APIs) - but not all characters are allowed in urls
  • DRF (django-rest-framework) use urls patterns that don't catch some characters by default (for example ".")
  • Primary keys must be unique - it's harder to accomplish it if the field is a string, especially when you let users to define it
like image 38
jozo Avatar answered Oct 17 '22 18:10

jozo