Defining unique constraints

The RESTful Web Service doesn't use any constraints, and therefore, it is possible to create many drone categories with the same name. We don't want to have many drone categories with the same name. Each drone category name must be unique in the database table that persists drone categories (the drones_dronecategory table). We also want drones and pilots to have unique names. Hence, we will make the necessary changes to add unique constraints to each of the following fields:

  • The name field of the DroneCategory model
  • The name field of the Drone model
  • The name field of the Pilot model

We will learn the necessary steps to edit existing models and add constraints to fields that are already persisted in tables and to propagate the changes in the underlying database by running the already analyzed migrations process.

Make sure you quit Django's development server. Remember that you just need to press Ctrl + C in the terminal or Command Prompt window in which it is running. We have to edit the models and then execute migrations before starting Django's development server again.

Now, we will edit the existing code that declares the models to add unique constraints to the name field for the models that we use to represent and persist the drone categories, drones, and pilots. Open the drones/models.py file and replace the code that declares the DroneCategory, Drone, and Pilot classes with the following code. The lines that were edited are highlighted in the code listing. The code for the Competition class remains without changes. The code file for the sample is included in the hillar_django_restful_07_01 folder, in the restful01/drones/models.py file:

  class DroneCategory(models.Model): 
     name = models.CharField(max_length=250, unique=True) 
 
     class Meta: 
        ordering = ('name',) 
 
     def __str__(self): 
         return self.name 
 
 
  class Drone(models.Model): 
     name = models.CharField(max_length=250, unique=True) 
     drone_category = models.ForeignKey( 
         DroneCategory,  
         related_name='drones',  
         on_delete=models.CASCADE) 
      manufacturing_date = models.DateTimeField() 
      has_it_competed = models.BooleanField(default=False) 
      inserted_timestamp = models.DateTimeField(auto_now_add=True) 
 
    class Meta: 
        ordering = ('name',) 
 
    def __str__(self): 
        return self.name 
 
 
  class Pilot(models.Model): 
    MALE = 'M' 
    FEMALE = 'F' 
    GENDER_CHOICES = ( 
        (MALE, 'Male'), 
        (FEMALE, 'Female'), 
    ) 
    name = models.CharField(max_length=150, blank=False, unique=True) 
    gender = models.CharField( 
        max_length=2, 
        choices=GENDER_CHOICES, 
        default=MALE, 
    ) 
    races_count = models.IntegerField() 
    inserted_timestamp = models.DateTimeField(auto_now_add=True) 
 
    class Meta: 
        ordering = ('name',) 
 
    def __str__(self): 
        return self.name 

We added unique=True as one of the named arguments for each call to the models.CharField initializer. This way, we specify that the fields must be unique, and Django's ORM will translate this into a requirement for the creation of the necessary unique constraints for the fields in the underlying database tables.

Now, it is necessary to execute the migrations that will generate the unique constraints we added for the fields in the models in the database. This time, the migrations process will synchronize the database with the changes we made in the models, and therefore, the process will apply a delta. Run the following Python script:

    python manage.py makemigrations drones

The following lines show the output generated after running the previous command:

Migrations for 'drones':
drones/migrations/0002_auto_20171104_0246.py
- Alter field name on drone
- Alter field name on dronecategory
- Alter field name on pilot

The lines in the output indicate that the drones/migrations/0002_auto_20171104_0246.py file includes the code to alter the fields called name on drone, dronecategory, and pilot. It is important to take into account that the Python filename generated by the migrations process encodes the date and time, and therefore, the name will be different when you run the code in your development computer.

The following lines show the code for the file that was automatically generated by Django. The code file for the sample is included in the hillar_django_restful_07_01 folder, in the restful01/drones/migrations/0002_auto_20171104_0246.py file:

# -*- coding: utf-8 -*- 
# Generated by Django 1.11.5 on 2017-11-04 02:46 
from __future__ import unicode_literals 
 
from django.db import migrations, models 
 
 
class Migration(migrations.Migration): 
 
    dependencies = [ 
        ('drones', '0001_initial'), 
    ] 
 
    operations = [ 
        migrations.AlterField( 
            model_name='drone', 
            name='name', 
            field=models.CharField(max_length=250, unique=True), 
        ), 
        migrations.AlterField( 
            model_name='dronecategory', 
            name='name', 
            field=models.CharField(max_length=250, unique=True), 
        ), 
        migrations.AlterField( 
            model_name='pilot', 
            name='name', 
            field=models.CharField(max_length=50, unique=True), 
        ), 
    ] 

The code defines a subclass of the django.db.migrations.Migration class called Migration, which defines an operations list with many migrations.AlterField instances. Each migrations.AlterField instance will alter the field in the table for each of the related models: drone, dronecategory, and pilot.

Now, run the following Python script to execute all the generated migrations and apply the changes in the underlying database tables:

    python manage.py migrate

The following lines show the output generated after running the previous command. Notice that the order in which the migrations are executed can differ in your development computer:

    Operations to perform:
      Apply all migrations: admin, auth, contenttypes, drones, sessions
    Running migrations:
      Applying drones.0002_auto_20171104_0246... OK
  

After we run the previous command, we will have unique indexes on the name fields for the following tables in the PostgreSQL database:

  • drones_drone
  • drones_dronecategory
  • drones_pilot

We can use the PostgreSQL command-line tools or any other application that allows us to easily check the contents of the PostgreSQL database to check the tables that Django updated. If you are working with an SQLite or any other database with this example, make sure you use the commands or tools related to the database you are using.

The following screenshot shows a list of the indexes for each of the previously enumerated tables in the SQLPro for Postgres GUI tool. Each table has a new unique index for the name field:

The following are the names generated for the new unique indexes in the sample database:

  • The drones_drone_name_85faecee_uniq index for the drones_drone table
  • The drones_drone_dronecategory_name_dedead86_uniq index for the drones_dronecategory table
  • The drones_pilot_name_3b56f2a1_uniq index for the drones_pilot table
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.216.123.120