diff --git a/zerver/migrations/0001_initial.py b/zerver/migrations/0001_initial.py index 5889b3662d..3b4befb89f 100644 --- a/zerver/migrations/0001_initial.py +++ b/zerver/migrations/0001_initial.py @@ -103,7 +103,7 @@ CREATE TRIGGER zerver_message_update_search_tsvector_async ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), ('token', models.CharField(unique=True, max_length=255)), ('last_updated', models.DateTimeField(default=django.utils.timezone.now, auto_now=True)), - ('user', models.ForeignKey(to=settings.AUTH_USER_MODEL)), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), ], options={ }, @@ -188,7 +188,7 @@ CREATE TRIGGER zerver_message_update_search_tsvector_async ('token', models.CharField(unique=True, max_length=4096)), ('last_updated', models.DateTimeField(default=django.utils.timezone.now, auto_now=True)), ('ios_app_id', models.TextField(null=True)), - ('user', models.ForeignKey(to=settings.AUTH_USER_MODEL)), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), ], options={ }, @@ -219,7 +219,7 @@ CREATE TRIGGER zerver_message_update_search_tsvector_async fields=[ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), ('domain', models.CharField(unique=True, max_length=80, db_index=True)), - ('realm', models.ForeignKey(to='zerver.Realm', null=True)), + ('realm', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='zerver.Realm', null=True)), ], options={ }, @@ -231,7 +231,7 @@ CREATE TRIGGER zerver_message_update_search_tsvector_async ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), ('name', models.TextField()), ('img_url', models.TextField()), - ('realm', models.ForeignKey(to='zerver.Realm')), + ('realm', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='zerver.Realm')), ], options={ }, @@ -243,7 +243,7 @@ CREATE TRIGGER zerver_message_update_search_tsvector_async ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), ('pattern', models.TextField()), ('url_format_string', models.TextField()), - ('realm', models.ForeignKey(to='zerver.Realm')), + ('realm', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='zerver.Realm')), ], options={ }, @@ -266,7 +266,7 @@ CREATE TRIGGER zerver_message_update_search_tsvector_async ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), ('email', models.EmailField(max_length=75)), ('timestamp', models.DateTimeField(auto_now_add=True)), - ('user_profile', models.ForeignKey(to=settings.AUTH_USER_MODEL)), + ('user_profile', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), ], options={ }, @@ -296,7 +296,7 @@ CREATE TRIGGER zerver_message_update_search_tsvector_async ('description', models.CharField(default='', max_length=1024)), ('date_created', models.DateTimeField(default=django.utils.timezone.now)), ('deactivated', models.BooleanField(default=False)), - ('realm', models.ForeignKey(to='zerver.Realm')), + ('realm', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='zerver.Realm')), ], options={ }, @@ -322,8 +322,8 @@ CREATE TRIGGER zerver_message_update_search_tsvector_async ('desktop_notifications', models.BooleanField(default=True)), ('audible_notifications', models.BooleanField(default=True)), ('notifications', models.BooleanField(default=False)), - ('recipient', models.ForeignKey(to='zerver.Recipient')), - ('user_profile', models.ForeignKey(to=settings.AUTH_USER_MODEL)), + ('recipient', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='zerver.Recipient')), + ('user_profile', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), ], options={ }, @@ -336,8 +336,8 @@ CREATE TRIGGER zerver_message_update_search_tsvector_async ('query', models.CharField(max_length=50, db_index=True)), ('count', models.IntegerField()), ('last_visit', models.DateTimeField(verbose_name='last visit')), - ('client', models.ForeignKey(to='zerver.Client')), - ('user_profile', models.ForeignKey(to=settings.AUTH_USER_MODEL)), + ('client', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='zerver.Client')), + ('user_profile', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), ], options={ }, @@ -349,7 +349,7 @@ CREATE TRIGGER zerver_message_update_search_tsvector_async ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), ('start', models.DateTimeField(verbose_name='start time', db_index=True)), ('end', models.DateTimeField(verbose_name='end time', db_index=True)), - ('user_profile', models.ForeignKey(to=settings.AUTH_USER_MODEL)), + ('user_profile', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), ], options={ }, @@ -360,8 +360,8 @@ CREATE TRIGGER zerver_message_update_search_tsvector_async fields=[ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), ('flags', bitfield.models.BitField(['read', 'starred', 'collapsed', 'mentioned', 'wildcard_mentioned', 'summarize_in_home', 'summarize_in_stream', 'force_expand', 'force_collapse', 'has_alert_word', 'historical', 'is_me_message'], default=0)), - ('message', models.ForeignKey(to='zerver.Message')), - ('user_profile', models.ForeignKey(to=settings.AUTH_USER_MODEL)), + ('message', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='zerver.Message')), + ('user_profile', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), ], options={ }, @@ -373,8 +373,8 @@ CREATE TRIGGER zerver_message_update_search_tsvector_async ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), ('timestamp', models.DateTimeField(verbose_name='presence changed')), ('status', models.PositiveSmallIntegerField(default=1)), - ('client', models.ForeignKey(to='zerver.Client')), - ('user_profile', models.ForeignKey(to=settings.AUTH_USER_MODEL)), + ('client', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='zerver.Client')), + ('user_profile', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), ], options={ }, @@ -399,7 +399,7 @@ CREATE TRIGGER zerver_message_update_search_tsvector_async migrations.AddField( model_name='streamcolor', name='subscription', - field=models.ForeignKey(to='zerver.Subscription'), + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='zerver.Subscription'), preserve_default=True, ), migrations.AlterUniqueTogether( @@ -421,19 +421,19 @@ CREATE TRIGGER zerver_message_update_search_tsvector_async migrations.AddField( model_name='realm', name='notifications_stream', - field=models.ForeignKey(related_name='+', blank=True, to='zerver.Stream', null=True), + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='+', blank=True, to='zerver.Stream', null=True), preserve_default=True, ), migrations.AddField( model_name='preregistrationuser', name='realm', - field=models.ForeignKey(to='zerver.Realm', null=True), + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='zerver.Realm', null=True), preserve_default=True, ), migrations.AddField( model_name='preregistrationuser', name='referred_by', - field=models.ForeignKey(to=settings.AUTH_USER_MODEL, null=True), + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, null=True), preserve_default=True, ), migrations.AddField( @@ -445,31 +445,31 @@ CREATE TRIGGER zerver_message_update_search_tsvector_async migrations.AddField( model_name='message', name='recipient', - field=models.ForeignKey(to='zerver.Recipient'), + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='zerver.Recipient'), preserve_default=True, ), migrations.AddField( model_name='message', name='sender', - field=models.ForeignKey(to=settings.AUTH_USER_MODEL), + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL), preserve_default=True, ), migrations.AddField( model_name='message', name='sending_client', - field=models.ForeignKey(to='zerver.Client'), + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='zerver.Client'), preserve_default=True, ), migrations.AddField( model_name='defaultstream', name='realm', - field=models.ForeignKey(to='zerver.Realm'), + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='zerver.Realm'), preserve_default=True, ), migrations.AddField( model_name='defaultstream', name='stream', - field=models.ForeignKey(to='zerver.Stream'), + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='zerver.Stream'), preserve_default=True, ), migrations.AlterUniqueTogether( @@ -479,13 +479,13 @@ CREATE TRIGGER zerver_message_update_search_tsvector_async migrations.AddField( model_name='userprofile', name='default_events_register_stream', - field=models.ForeignKey(related_name='+', to='zerver.Stream', null=True), + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='+', to='zerver.Stream', null=True), preserve_default=True, ), migrations.AddField( model_name='userprofile', name='default_sending_stream', - field=models.ForeignKey(related_name='+', to='zerver.Stream', null=True), + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='+', to='zerver.Stream', null=True), preserve_default=True, ), migrations.AddField( @@ -497,7 +497,7 @@ CREATE TRIGGER zerver_message_update_search_tsvector_async migrations.AddField( model_name='userprofile', name='realm', - field=models.ForeignKey(to='zerver.Realm'), + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='zerver.Realm'), preserve_default=True, ), migrations.AddField( diff --git a/zerver/migrations/0015_attachment.py b/zerver/migrations/0015_attachment.py index f74624c2e7..44e60f043f 100644 --- a/zerver/migrations/0015_attachment.py +++ b/zerver/migrations/0015_attachment.py @@ -21,7 +21,7 @@ class Migration(migrations.Migration): ('path_id', models.TextField(db_index=True)), ('create_time', models.DateTimeField(default=django.utils.timezone.now, db_index=True)), ('messages', models.ManyToManyField(to='zerver.Message')), - ('owner', models.ForeignKey(to=settings.AUTH_USER_MODEL)), + ('owner', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), ], ), ] diff --git a/zerver/migrations/0020_add_tracking_attachment.py b/zerver/migrations/0020_add_tracking_attachment.py index 598bf920ed..b137cae867 100644 --- a/zerver/migrations/0020_add_tracking_attachment.py +++ b/zerver/migrations/0020_add_tracking_attachment.py @@ -2,6 +2,7 @@ from __future__ import unicode_literals from django.db import models, migrations +import django.db.models.deletion from django.conf import settings class Migration(migrations.Migration): @@ -19,6 +20,6 @@ class Migration(migrations.Migration): migrations.AddField( model_name='attachment', name='realm', - field=models.ForeignKey(blank=True, to='zerver.Realm', null=True), + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, blank=True, to='zerver.Realm', null=True), ), ] diff --git a/zerver/migrations/0044_reaction.py b/zerver/migrations/0044_reaction.py index e59b6905e1..d0758ddfe1 100644 --- a/zerver/migrations/0044_reaction.py +++ b/zerver/migrations/0044_reaction.py @@ -2,6 +2,7 @@ from __future__ import unicode_literals from django.db import migrations, models +import django.db.models.deletion from django.conf import settings import zerver.lib.str_utils @@ -17,8 +18,8 @@ class Migration(migrations.Migration): name='Reaction', fields=[ ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('user_profile', models.ForeignKey(to=settings.AUTH_USER_MODEL)), - ('message', models.ForeignKey(to='zerver.Message')), + ('user_profile', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ('message', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='zerver.Message')), ('emoji_name', models.TextField()), ], bases=(zerver.lib.str_utils.ModelReprMixin, models.Model), diff --git a/zerver/models.py b/zerver/models.py index 7f220cbfd2..6ac4ce4101 100644 --- a/zerver/models.py +++ b/zerver/models.py @@ -138,7 +138,7 @@ class Realm(ModelReprMixin, models.Model): org_type = models.PositiveSmallIntegerField(default=COMMUNITY) # type: int date_created = models.DateTimeField(default=timezone_now) # type: datetime.datetime - notifications_stream = models.ForeignKey('Stream', related_name='+', null=True, blank=True) # type: Optional[Stream] + notifications_stream = models.ForeignKey('Stream', related_name='+', null=True, blank=True, on_delete=CASCADE) # type: Optional[Stream] deactivated = models.BooleanField(default=False) # type: bool default_language = models.CharField(default=u'en', max_length=MAX_LANGUAGE_ID_LENGTH) # type: Text authentication_methods = BitField(flags=AUTHENTICATION_FLAGS, @@ -312,7 +312,7 @@ def name_changes_disabled(realm): return settings.NAME_CHANGES_DISABLED or realm.name_changes_disabled class RealmDomain(models.Model): - realm = models.ForeignKey(Realm) # type: Realm + realm = models.ForeignKey(Realm, on_delete=CASCADE) # type: Realm # should always be stored lowercase domain = models.CharField(max_length=80, db_index=True) # type: Text allow_subdomains = models.BooleanField(default=False) @@ -396,8 +396,8 @@ def get_realm_domains(realm): return list(realm.realmdomain_set.values('domain', 'allow_subdomains')) class RealmEmoji(ModelReprMixin, models.Model): - author = models.ForeignKey('UserProfile', blank=True, null=True) - realm = models.ForeignKey(Realm) # type: Realm + author = models.ForeignKey('UserProfile', blank=True, null=True, on_delete=CASCADE) + realm = models.ForeignKey(Realm, on_delete=CASCADE) # type: Realm # Second part of the regex (negative lookbehind) disallows names ending with one of the punctuation characters name = models.TextField(validators=[MinLengthValidator(1), RegexValidator(regex=r'^[0-9a-z.\-_]+(? Text @@ -861,7 +861,7 @@ def generate_email_token_for_stream(): class Stream(ModelReprMixin, models.Model): MAX_NAME_LENGTH = 60 name = models.CharField(max_length=MAX_NAME_LENGTH, db_index=True) # type: Text - realm = models.ForeignKey(Realm, db_index=True) # type: Realm + realm = models.ForeignKey(Realm, db_index=True, on_delete=CASCADE) # type: Realm invite_only = models.NullBooleanField(default=False) # type: Optional[bool] # Used by the e-mail forwarder. The e-mail RFC specifies a maximum # e-mail length of 254, and our max stream length is 30, so we @@ -1055,14 +1055,14 @@ def sew_messages_and_reactions(messages, reactions): class AbstractMessage(ModelReprMixin, models.Model): - sender = models.ForeignKey(UserProfile) # type: UserProfile - recipient = models.ForeignKey(Recipient) # type: Recipient + sender = models.ForeignKey(UserProfile, on_delete=CASCADE) # type: UserProfile + recipient = models.ForeignKey(Recipient, on_delete=CASCADE) # type: Recipient subject = models.CharField(max_length=MAX_SUBJECT_LENGTH, db_index=True) # type: Text content = models.TextField() # type: Text rendered_content = models.TextField(null=True) # type: Optional[Text] rendered_content_version = models.IntegerField(null=True) # type: Optional[int] pub_date = models.DateTimeField('date published', db_index=True) # type: datetime.datetime - sending_client = models.ForeignKey(Client) # type: Client + sending_client = models.ForeignKey(Client, on_delete=CASCADE) # type: Client last_edit_time = models.DateTimeField(null=True) # type: Optional[datetime.datetime] edit_history = models.TextField(null=True) # type: Optional[Text] has_attachment = models.BooleanField(default=False, db_index=True) # type: bool @@ -1227,8 +1227,8 @@ def get_context_for_message(message): post_save.connect(flush_message, sender=Message) class Reaction(ModelReprMixin, models.Model): - user_profile = models.ForeignKey(UserProfile) # type: UserProfile - message = models.ForeignKey(Message) # type: Message + user_profile = models.ForeignKey(UserProfile, on_delete=CASCADE) # type: UserProfile + message = models.ForeignKey(Message, on_delete=CASCADE) # type: Message emoji_name = models.TextField() # type: Text class Meta(object): @@ -1255,7 +1255,7 @@ class Reaction(ModelReprMixin, models.Model): # UserMessage is the largest table in a Zulip installation, even # though each row is only 4 integers. class AbstractUserMessage(ModelReprMixin, models.Model): - user_profile = models.ForeignKey(UserProfile) # type: UserProfile + user_profile = models.ForeignKey(UserProfile, on_delete=CASCADE) # type: UserProfile # We're not using the archived field for now, but create it anyway # since this table will be an unpleasant one to do schema changes # on later @@ -1280,12 +1280,12 @@ class AbstractUserMessage(ModelReprMixin, models.Model): class ArchivedUserMessage(AbstractUserMessage): - message = models.ForeignKey(ArchivedMessage) # type: Message + message = models.ForeignKey(ArchivedMessage, on_delete=CASCADE) # type: Message archive_timestamp = models.DateTimeField(default=timezone_now, db_index=True) # type: datetime.datetime class UserMessage(AbstractUserMessage): - message = models.ForeignKey(Message) # type: Message + message = models.ForeignKey(Message, on_delete=CASCADE) # type: Message def parse_usermessage_flags(val): @@ -1305,8 +1305,8 @@ class AbstractAttachment(ModelReprMixin, models.Model): # If the path of a file is http://localhost:9991/user_uploads/a/b/abc/temp_file.py # then its path_id will be a/b/abc/temp_file.py. path_id = models.TextField(db_index=True, unique=True) # type: Text - owner = models.ForeignKey(UserProfile) # type: UserProfile - realm = models.ForeignKey(Realm, blank=True, null=True) # type: Optional[Realm] + owner = models.ForeignKey(UserProfile, on_delete=CASCADE) # type: UserProfile + realm = models.ForeignKey(Realm, blank=True, null=True, on_delete=CASCADE) # type: Optional[Realm] is_realm_public = models.BooleanField(default=False) # type: bool create_time = models.DateTimeField(default=timezone_now, db_index=True) # type: datetime.datetime @@ -1375,8 +1375,8 @@ def get_old_unclaimed_attachments(weeks_ago): return old_attachments class Subscription(ModelReprMixin, models.Model): - user_profile = models.ForeignKey(UserProfile) # type: UserProfile - recipient = models.ForeignKey(Recipient) # type: Recipient + user_profile = models.ForeignKey(UserProfile, on_delete=CASCADE) # type: UserProfile + recipient = models.ForeignKey(Recipient, on_delete=CASCADE) # type: Recipient active = models.BooleanField(default=True) # type: bool in_home_view = models.NullBooleanField(default=True) # type: Optional[bool] @@ -1523,8 +1523,8 @@ def clear_database(): Session.objects.all().delete() class UserActivity(models.Model): - user_profile = models.ForeignKey(UserProfile) # type: UserProfile - client = models.ForeignKey(Client) # type: Client + user_profile = models.ForeignKey(UserProfile, on_delete=CASCADE) # type: UserProfile + client = models.ForeignKey(Client, on_delete=CASCADE) # type: Client query = models.CharField(max_length=50, db_index=True) # type: Text count = models.IntegerField() # type: int @@ -1536,14 +1536,14 @@ class UserActivity(models.Model): class UserActivityInterval(models.Model): MIN_INTERVAL_LENGTH = datetime.timedelta(minutes=15) - user_profile = models.ForeignKey(UserProfile) # type: UserProfile + user_profile = models.ForeignKey(UserProfile, on_delete=CASCADE) # type: UserProfile start = models.DateTimeField('start time', db_index=True) # type: datetime.datetime end = models.DateTimeField('end time', db_index=True) # type: datetime.datetime class UserPresence(models.Model): - user_profile = models.ForeignKey(UserProfile) # type: UserProfile - client = models.ForeignKey(Client) # type: Client + user_profile = models.ForeignKey(UserProfile, on_delete=CASCADE) # type: UserProfile + client = models.ForeignKey(Client, on_delete=CASCADE) # type: Client # Valid statuses ACTIVE = 1 @@ -1679,14 +1679,14 @@ class UserPresence(models.Model): unique_together = ("user_profile", "client") class DefaultStream(models.Model): - realm = models.ForeignKey(Realm) # type: Realm - stream = models.ForeignKey(Stream) # type: Stream + realm = models.ForeignKey(Realm, on_delete=CASCADE) # type: Realm + stream = models.ForeignKey(Stream, on_delete=CASCADE) # type: Stream class Meta(object): unique_together = ("realm", "stream") class Referral(models.Model): - user_profile = models.ForeignKey(UserProfile) # type: UserProfile + user_profile = models.ForeignKey(UserProfile, on_delete=CASCADE) # type: UserProfile email = models.EmailField(blank=False, null=False) # type: Text timestamp = models.DateTimeField(auto_now_add=True, null=False) # type: datetime.datetime @@ -1704,10 +1704,10 @@ class ScheduledJob(models.Model): filter_string = models.CharField(max_length=100) # type: Text class RealmAuditLog(models.Model): - realm = models.ForeignKey(Realm) # type: Realm - acting_user = models.ForeignKey(UserProfile, null=True, related_name='+') # type: Optional[UserProfile] - modified_user = models.ForeignKey(UserProfile, null=True, related_name='+') # type: Optional[UserProfile] - modified_stream = models.ForeignKey(Stream, null=True) # type: Optional[Stream] + realm = models.ForeignKey(Realm, on_delete=CASCADE) # type: Realm + acting_user = models.ForeignKey(UserProfile, null=True, related_name='+', on_delete=CASCADE) # type: Optional[UserProfile] + modified_user = models.ForeignKey(UserProfile, null=True, related_name='+', on_delete=CASCADE) # type: Optional[UserProfile] + modified_stream = models.ForeignKey(Stream, null=True, on_delete=CASCADE) # type: Optional[Stream] event_type = models.CharField(max_length=40) # type: Text event_time = models.DateTimeField(db_index=True) # type: datetime.datetime # If True, event_time is an overestimate of the true time. Can be used @@ -1716,7 +1716,7 @@ class RealmAuditLog(models.Model): extra_data = models.TextField(null=True) # type: Optional[Text] class UserHotspot(models.Model): - user = models.ForeignKey(UserProfile) # type: UserProfile + user = models.ForeignKey(UserProfile, on_delete=CASCADE) # type: UserProfile hotspot = models.CharField(max_length=30) # type: Text timestamp = models.DateTimeField(default=timezone_now) # type: datetime.datetime @@ -1789,7 +1789,7 @@ class Service(models.Model): # Bot user corresponding to the Service. The bot_type of this user # deterines the type of service. If non-bot services are added later, # user_profile can also represent the owner of the Service. - user_profile = models.ForeignKey(UserProfile) # type: UserProfile + user_profile = models.ForeignKey(UserProfile, on_delete=CASCADE) # type: UserProfile base_url = models.TextField() # type: Text token = models.TextField() # type: Text # Interface / API version of the service.