Skip to content

Commit

Permalink
Create new file for abstract models
Browse files Browse the repository at this point in the history
  • Loading branch information
gunthercox committed Oct 5, 2017
1 parent 051f4f9 commit 20eab67
Show file tree
Hide file tree
Showing 2 changed files with 259 additions and 233 deletions.
253 changes: 253 additions & 0 deletions chatterbot/ext/django_chatterbot/abstract_models.py
@@ -0,0 +1,253 @@
from django.db import models
from django.apps import apps
from django.utils import timezone
from chatterbot import constants
from django.conf import settings


DJANGO_APP_NAME = constants.DEFAULT_DJANGO_APP_NAME
STATEMENT_MODEL = 'Statement'
RESPONSE_MODEL = 'Response'

if hasattr(settings, 'CHATTERBOT'):
"""
Allow related models to be overridden in the project settings.
Default to the original settings if one is not defined.
"""
DJANGO_APP_NAME = settings.CHATTERBOT.get(
'django_app_name',
DJANGO_APP_NAME
)
STATEMENT_MODEL = settings.CHATTERBOT.get(
'statement_model',
STATEMENT_MODEL
)
RESPONSE_MODEL = settings.CHATTERBOT.get(
'response_model',
RESPONSE_MODEL
)


class AbstractBaseStatement(models.Model):
"""
The abstract base statement allows other models to
be created using the attributes that exist on the
default models.
"""

text = models.CharField(
unique=True,
blank=False,
null=False,
max_length=constants.STATEMENT_TEXT_MAX_LENGTH
)

extra_data = models.CharField(
max_length=500,
blank=True
)

# This is the confidence with which the chat bot believes
# this is an accurate response. This value is set when the
# statement is returned by the chat bot.
confidence = 0

class Meta:
abstract = True

def __str__(self):
if len(self.text.strip()) > 60:
return '{}...'.format(self.text[:57])
elif len(self.text.strip()) > 0:
return self.text
return '<empty>'

def __init__(self, *args, **kwargs):
super(AbstractBaseStatement, self).__init__(*args, **kwargs)

# Responses to be saved if the statement is updated with the storage adapter
self.response_statement_cache = []

@property
def in_response_to(self):
"""
Return the response objects that are for this statement.
"""
ResponseModel = apps.get_model(DJANGO_APP_NAME, RESPONSE_MODEL)
return ResponseModel.objects.filter(statement=self)

def add_extra_data(self, key, value):
"""
Add extra data to the extra_data field.
"""
import json

if not self.extra_data:
self.extra_data = '{}'

extra_data = json.loads(self.extra_data)
extra_data[key] = value

self.extra_data = json.dumps(extra_data)

def add_response(self, statement):
"""
Add a response to this statement.
"""
self.response_statement_cache.append(statement)

def remove_response(self, response_text):
"""
Removes a response from the statement's response list based
on the value of the response text.
:param response_text: The text of the response to be removed.
:type response_text: str
"""
is_deleted = False
response = self.in_response.filter(response__text=response_text)

if response.exists():
is_deleted = True

return is_deleted

def get_response_count(self, statement):
"""
Find the number of times that the statement has been used
as a response to the current statement.
:param statement: The statement object to get the count for.
:type statement: chatterbot.conversation.statement.Statement
:returns: Return the number of times the statement has been used as a response.
:rtype: int
"""
return self.in_response.filter(response__text=statement.text).count()

def serialize(self):
"""
:returns: A dictionary representation of the statement object.
:rtype: dict
"""
import json
data = {}

if not self.extra_data:
self.extra_data = '{}'

data['text'] = self.text
data['in_response_to'] = []
data['extra_data'] = json.loads(self.extra_data)

for response in self.in_response.all():
data['in_response_to'].append(response.serialize())

return data


class AbstractBaseResponse(models.Model):
"""
The abstract base response allows other models to
be created using the attributes that exist on the
default models.
"""

statement = models.ForeignKey(
STATEMENT_MODEL,
related_name='in_response'
)

response = models.ForeignKey(
STATEMENT_MODEL,
related_name='responses'
)

created_at = models.DateTimeField(
default=timezone.now,
help_text='The date and time that this statement was created at.'
)

created_at = models.DateTimeField(
default=timezone.now,
help_text='The date and time that this response was created at.'
)

class Meta:
abstract = True

@property
def occurrence(self):
"""
Return a count of the number of times this response has occurred.
"""
ResponseModel = apps.get_model(DJANGO_APP_NAME, RESPONSE_MODEL)

return ResponseModel.objects.filter(
statement__text=self.statement.text,
response__text=self.response.text
).count()

def __str__(self):
statement = self.statement.text
response = self.response.text
return '{} => {}'.format(
statement if len(statement) <= 20 else statement[:17] + '...',
response if len(response) <= 40 else response[:37] + '...'
)

def serialize(self):
"""
:returns: A dictionary representation of the statement object.
:rtype: dict
"""
data = {}

data['text'] = self.response.text
data['created_at'] = self.created_at.isoformat()
data['occurrence'] = self.occurrence

return data


class AbstractBaseConversation(models.Model):
"""
The abstract base conversation allows other models to
be created using the attributes that exist on the
default models.
"""

responses = models.ManyToManyField(
RESPONSE_MODEL,
related_name='conversations',
help_text='The responses in this conversation.'
)

class Meta:
abstract = True

def __str__(self):
return str(self.id)


class AbstractBaseTag(models.Model):
"""
The abstract base tag allows other models to
be created using the attributes that exist on the
default models.
"""

name = models.SlugField(
max_length=50
)

statements = models.ManyToManyField(
STATEMENT_MODEL,
related_name='tags'
)

class Meta:
abstract = True

def __str__(self):
return self.name

0 comments on commit 20eab67

Please sign in to comment.