# Simple Django Tip #4

So far [my tips](https://hellosambhavi.com/simple-django-tip-1) were more about the [environment](https://hellosambhavi.com/simple-django-tip-2) and setting up [the stage](https://hellosambhavi.com/simple-django-tip-3) in the right way.

Let's look at a few key points to remember while defining a `model` in `models.py.`

I plan to write a couple of posts regarding model design, rather than one single long post.

### Models in Django

A `model` in the Django ORM world is the equivalent of a table in the database. That's the beauty of ORMs. We can define the complete table structure in the application itself, create, modify, query and do every single thing that we do using SQLs but without them.

<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">A word of caution though, Do give a lot of thought while defining a model, the relationships, the validations, and the audit columns it may need upfront. It gets quite tricky to keep applying changes to the model once data starts to load.</div>
</div>

Let's jump in straight 😀. To not repeat myself I'd urge you to refer to [my previous post](https://hellosambhavi.com/simple-django-tip-3) to perform the usual steps of creating a Django project and other steps.

I'm a big fan of popsicles and soft cones 🍦😋. Just to give the post a bit of flavor, I decided to take an example of defining a few `models` for a hypothetical website that sells and delivers ice cream.

A few models for our ice cream website would be:

* Customer
    
* Icecream
    
* Order
    

Now for a few tips to keep in mind while we define a model. We shall apply them in the end to these models to see what it looks like.

### Tips to remember while defining a model

### Use descriptive field names

This may seem like an age-old tip. But it is forgotten many a time 😂. Do not worry about the name of a field being long as long as it is self-explanatory.

```python
# WRONG
class Customer(models.Model):
    fname = models.CharField(...)
    lname = models.CharField(...)

# RIGHT
class Customer(models.Model):
    first_name = models.CharField(...)
    last_name = models.CharField(...)
```

### Use descriptive related names

Tables being related is extremely common in any database. In Django, while we use `ForeignKey` as field type, make sure to give an understandable value for `related_name`.

If not followed from the beginning, it becomes unnecessarily complicated when the number of models starts to grow. I generally use the approach of noun + verb combination. Feel free to use whatever suits your naming standards but make sure it's descriptive. Let's see an example.

```python
# WRONG
class Order(models.Model):
   ordered_by = models.ForeignKey(
        Customer, on_delete=models.CASCADE, related_name="ordered_by")

# RIGHT
class Order(models.Model):
   ordered_by = models.ForeignKey(
        Customer, on_delete=models.CASCADE, related_name="customer_who_ordered")
```

### Use `choices` whenever there is a list of values

When a field in a model is designed to have a limited set of choices (think of a dropdown as its corresponding widget in the UI), it's always a good idea to define choices for the field.

It makes the code more readable and easy to maintain when there is a need to modify the values for some business reason. Validation of the field is also quite straightforward when defined as a choice field.

Where to place the choices field is debatable 😀.

If there are a lot of such list values in your business scenario or if a particular type of value will appear in multiple tables/classes (example: gender field) then a probable case may be to have a separate `choices.py` so that a particular choice field can be reused.

Otherwise, it's a good idea to just define it as the first thing in your class.

```python
# WRONG
class Icecream(models.Model):
    flavor = models.CharField("Choose your flavor", max_length=500, \
             blank=False, null=False)


# RIGHT
class Icecream(models.Model):
    flavor_choices = (
        ("butterscotch", "Butterscotch"),
        ("carmel", "Carmel"),
        ("pista", "Pista"),
        ("strawberry", "Strawberry"),
        ("vanilla", "Vanilla")
    )
    flavor = models.CharField("Choose your flavor", choices=flavor_choices,
          default="vanilla")                
   
```

### Use indexes for frequently queried fields

There are a few fields that will be used in most of the queries, especially the unique fields in a table. For such cases, it helps by defining them as indexes as part of `Meta` definition.

<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">One should be judicious though while defining indexes on fields as it may slow down write operations.</div>
</div>

Let's assume in our ice cream shop website, email is the unique identifier for a customer. Hence all queries that fetch customer details, dashboard-related ones especially will use email as part of the `where` clause. In such a case, we should define the index on the `email` column.

```python
# WRONG
class Customer(models.Model):
    first_name = models.CharField("First name", ...)
    last_name = models.CharField("Last name", ...)
    email = models.EmailField("Email address", ...)

# RIGHT
class Customer(models.Model):
    first_name = models.CharField("First name", ...)
    last_name = models.CharField("Last name", ...)
    email = models.EmailField("Email address", ...)
    class Meta:
        indexes = [
            models.Index(fields=["email"]),
        ]
```

<div data-node-type="callout">
<div data-node-type="callout-emoji">💡</div>
<div data-node-type="callout-text">db_index will be deprecated in the future. Hence the above definition is considered good practice</div>
</div>

### Will be continued

As I mentioned at the beginning of the post, I shall write a couple of posts in the immediate future concerning `models` as it is the backbone of any Django application.

Hope you found them useful!
