How to reference a slug from a different model in get_success_url?

Viewed 402

Setup

I have two models in my app. One is for a Journal and the other one is for entries to that journal. I wrote a CreateView class that will allow user to create a Journal entry for any Journal id currently located in. Ideally I want the class to "refresh" with the updated entry or in other words the get_success_url should lead the page we are currently located at.

views.py

class ToJournalEntriesList(LoginRequiredMixin, CreateView):
    model = to_journal_entry
    template_name = 'to_journals/to_journal_entries_list.html'
    fields = ('body',)

    def get_success_url(self):
        return reverse('to-journals', kwargs={'slug':self.object.slug})

    def form_valid(self, form):
        current_journal = to_journal.objects.get(journal_user=self.request.user, slug=self.kwargs['slug'])
        form.instance.journal_user = self.request.user
        form.instance.journal_name = current_journal
        return super(ToJournalEntriesList, self).form_valid(form)

    def get_context_data(self, **kwargs):
        context = super(ToJournalEntriesList, self).get_context_data(**kwargs)
        context['to_journal_entries'] = to_journal_entry.objects.all()
        return context

models.py

class to_journal(models.Model):
    journal_name = models.CharField(max_length = 40)
    slug = AutoSlugField(populate_from='journal_name')
    date_created = models.DateTimeField(auto_now_add=True)
    journal_user = models.ForeignKey(get_user_model(), on_delete=models.CASCADE,)

    def __str__(self):
        return str(self.journal_user) + " " + self.journal_name

    def get_absolute_url(self):
        return reverse('to-journals')


class to_journal_entry(models.Model):
    body = models.TextField()
    entry_date = models.DateTimeField(auto_now_add=True)
    journal_name = models.ForeignKey(to_journal, on_delete=models.CASCADE,)
    journal_user = models.ForeignKey(get_user_model(), on_delete=models.CASCADE,)

    def __str__(self):
        return str(self.journal_name) + " " + str(self.entry_date)

    def get_absolute_url(self):
        return reverse('to-journal-entries', args=(self.slug))

urls.py

urlpatterns = [
    path('', CreateToJournal.as_view(), name='to-journals'),
    path('<slug:slug>', ToJournalEntriesList.as_view(), name='to-journal-entries'),
]

Error

With the current setup that I have I get:

enter image description here

Which makes sense, because the to_journal_entry model does not have that that field.

Question

I am sure both my get_success_url() in views.py and get_absolute_url() in models.py are done incorrectly, but I could not find a good explanation of how those work. How should I set them up to achieve desired result? Thanks a ton in advance!

I appreciate everyone taking a look. Best, Rasul.

2 Answers

You can just follow the relationship:

def get_success_url(self):
    return reverse('to-journals', kwargs={'slug': self.object.journal_name.slug})

Your self.object is a to_journal_entry. You probably want to use the to_journal, you can do that by obtaining the journal_name:

class ToJournalEntriesList(LoginRequiredMixin, CreateView):
    model = to_journal_entry
    template_name = 'to_journals/to_journal_entries_list.html'
    fields = ('body',)

    def get_success_url(self):
        return reverse('to-journals', kwargs={ 'slug': self.object.journal_name.slug })

Note: usually the names of the models are written in PerlCase, so JournalEntry instead of to_journal_entry.

Related