WannaInternet
WannaInternet

Reputation: 424

Django- how to hyphenate TextField in URLs

I am trying to make my model so that the URL slug is hyphenated between spaces in the slug field by default. The slug should be limited to only the first six words in TextField. The TextField() called questionToProblem in the same model. Here's what I have:

class Problem(models.Model):
    free = models.CharField(max_length = 1, choices = Free)


    questionToProblem = models.TextField()
    solutionToProblem = models.TextField()

slug = models.CharField(max_length = 250, unique = True)
topic = models.ForeignKey(Topic, on_delete = models.CASCADE)

plainText = models.TextField(default= 'temp')
profile = models.JSONField(default=dict, blank=True) #default is assigned on the recommendation of django docs. DO NOT CHANGE
comments = GenericRelation(Comment)

def save(self, *args, **kwargs):
    super().save(*args, **kwargs) #create the problem
    cosine = Cosine(2)

    self.plainText = LatexNodes2Text().latex_to_text(str(self))
    self.profile = cosine.get_profile(self.plainText)
    super().save(update_fields=['plainText', 'profile',]) #update the neccessary fields

    for query in SavedQuery.objects.all():
        query_profile = cosine.get_profile(query.query)
        similarity = cosine.similarity_profiles(query_profile, self.profile)

        if similarity >= 0.25 and self not in query.results.all():
            query.results.add(self)
            query.save()

class Meta:
    ordering = ('questionToProblem',)

def get_url(self):
    return reverse('solution_details', args = [self.topic.slug, self.slug])

def __str__(self):
    return self.questionToProblem

My views.py:

def displaySolution(request, topic_slug, problem_slug):
    try:
        solution = Problem.objects.get(topic__slug = topic_slug, slug = problem_slug)
    except Exception as e:
        raise e
    return render(request, 'solution.html', {'solution' : solution})

Ideally, here's what I want the URL to look like, if the questionToProblem was "How many bananas do I have in total?", and the Topic key was "modeltopic":

http://127.0.0.1:8000/modeltopic/How-many-bananas-do-I-have

Upvotes: 0

Views: 154

Answers (1)

AMG
AMG

Reputation: 1646

Alter your slug field to include blank will help you out with the autosaving bit in the admin. Otherwise the form will complain that it needs a value.

slug = models.CharField(max_length = 250, unique = True, blank=True)

Add a method for the save something like the following. This may not be the best way given you want to use the TextField as the slug source - this may become a performance issue, but if your text is relatively short, and there are few 'new' Problems on a relative basis you may be alright. Use Django's slugify to deal with alphanumerics, trailing spaces, underscores, hyphens and the like, then split the text on space hyphen, taking a max of six words (https://docs.python.org/3/library/stdtypes.html#str.split) which then get joined (https://docs.python.org/3/library/stdtypes.html#str.join) back together as a string each separated with a hyphen.

def save(self):
    if not self.slug:
        # self.slug = slugify(' '.join(self.questionToProblem.split(' ')[:6]))
        # or take advantage of split's second argument
        # self.slug = slugify(' '.join(self.questionToProblem.split(' ', 5)))
        # or to take Selcuk's suggestion:
        # coding on the fly here in S/O so no guarantee on this syntax :)
        self.slug = '-'.join(slugify(self.questionToProblem).split('-', 5))
    return super().save(*args, **kwargs)

Note the use of slugify which you can import with:

from django.utils.text import slugify

Upvotes: 2

Related Questions