from banjo.models import Model, StringField, IntegerField, ForeignKey from banjo.http import BadRequest import pronouncing import re class Line(Model): text = StringField() clean_text = StringField() line_number = IntegerField() poem = ForeignKey("Poem", related_name="lines") rhyme = ForeignKey("Rhyme", related_name="lines", null=True) def __str__(self): "The string representation of a line is just its text" return self.text "Returns lowercase text without any punctuation" return re.sub('[^a-z ]', '', self.text.lower()) def last_word(self): "Gets the last word from a line, lower case and without punctuation." parts = self.clean_text.split() if parts: return parts[-1] def rhyming_lines(self): if self.rhyme: return self.rhyme.lines.exclude(clean_text__endswith=self.last_word()) else: return [] class Poem(Model): gutenberg_id = IntegerField(unique=True) def __str__(self): "The string representation of a poem is all its lines, in order" return '\n'.join(line.text for line in self.lines.order_by('line_number')) class Rhyme(Model): phones = StringField() @classmethod def get_rhyme_for_word(self, word): phones = pronouncing.phones_for_word(word) if not phones: raise BadRequest(f"Couldn't figure out how to pronounce {word}") rhyming_phones = pronouncing.rhyming_part(phones[0]) try: return Rhyme.objects.get(phones=rhyming_phones) except Rhyme.DoesNotExist: raise BadRequest(f"Sorry, no lines rhyme with {word}")