Search code examples
pythondjangopython-3.xdjango-viewsdjango-apps

Managing to use data from one Django application in another but the urls are different


In this previous question I asked about using data from one Django application in another. I wanted to use blog data from my blog application in my pages application. The goal being that my site homepage would show the 3 most recent entries.

The answer provided was acceptable at the time. However, I've since wanted to now set the blog items that appear on my homepage to act as links to the blog item itself but the blog items on my homepage have a different url path. Is there any way around this?

Here is my code:

Blog

from .views import (
    BlogListView,
    BlogUpdateView,
    BlogDetailView,
    BlogDeleteView,
    BlogCreateView,
)


urlpatterns = [
    path('<int:pk>/edit/',
         BlogUpdateView.as_view(), name='Blog_edit'),
    path('<int:pk>/',
         BlogDetailView.as_view(), name='Blog_detail'),
    path('<int:pk>/delete/',
         BlogDeleteView.as_view(), name='Blog_delete'),
    path('new/', BlogCreateView.as_view(), name='Blog_new'),
    path('', BlogListView.as_view(), name='Blog_list'),
]

models.py

class Blog(models.Model):
    title = models.CharField(max_length=255)
    body = models.TextField()
    date = models.DateTimeField(auto_now_add=True)
    author = models.ForeignKey(
        get_user_model(),
        on_delete=models.CASCADE,
    )
    thumb = models.ImageField(blank=True, null=True)

    def __str__(self):
        return self.title

    def get_absolute_url(self):
        return reverse('Blog_detail', args=[str(self.id)])

views.py

class BlogListView(ListView):
    model = Blog
    template_name = 'blog_list.html'


class BlogDetailView(DetailView):
    model = Blog
    template_name = 'blog_detail.html'
    login_url = 'login'


class BlogUpdateView(LoginRequiredMixin, UpdateView):
    model = Blog
    fields = ('title', 'body', 'thumb')
    template_name = 'blog_edit.html'
    login_url = 'login'

    def test_func(self):
        obj = self.get_object()
        return obj.author == self.request.user


class BlogDeleteView(LoginRequiredMixin, DeleteView):
    model = Blog
    template_name = 'blog_delete.html'
    success_url = reverse_lazy('blog_list')
    login_url = 'login'

    def test_func(self):
        obj = self.get_object()
        return obj.author == self.request.user


class BlogCreateView(LoginRequiredMixin, CreateView):
    model = Blog
    template_name = 'blog_new.html'
    fields = ('title', 'body', 'thumb')
    login_url = 'login'

    def form_valid(self, form):
        form.instance.author = self.request.user
        return super().form_valid(form)

pages

urls.py

urlpatterns = [
    path('', HomePageView, name='home'),
]

views.py

def HomePageView(request):
    context = {}
    blog = Blog.objects.order_by('-date')[:3]
    context['blog']=blog
    return render(request,'home.html',context)

home.html

{% extends 'base.html' %}

{% block title %}Home{% endblock title %}

{% block content %}
    <div class="jumbotron">
        <h1 class="display-4">Lakeland Cycle Club</h1>
        <p class="lead">The home of cycling in Fermanagh.</p>
        <p class="lead">
            <a class="btn btn-primary btn-lg" href="{% url 'blog_list' %}" role="button">View All Club News</a>
        </p>
        {% for new in blog%}
            <div class="card" style="width: 300px; display: inline-block; margin: 5px; vertical-align: top;">
                <div class="card-header">
                    <span class="font-weight-bold">
                        {{ new.title }}
                    </span> &middot;
                    <span class="text-muted">by {{ new.author }} | {{ new.date }}</span>
                </div>
                <div class="card-body">
                    {% if blog.thumb %}
                        <p align="center"><img src="{{ new.thumb.url }}" /></p>
                    {% endif %}
                    <p>{{ new.body | linebreaks | truncatewords:30 }}
                </div>
            </div>
        {% endfor %}
{% endblock content %}

More info.

I think if I add a URL to my title({{ new.title }}) it might work as I want. I tried <a href="{% url 'blog_detail' %}">{{ new.title }}</a> but got this error:

django.urls.exceptions.NoReverseMatch: Reverse for 'blog_detail' with no arguments not found. 1 pattern(s) tried: ['blog/(?P<pk>[0-9]+)/$']

The reason is most likely because each item in my home page has no way of identifying the primary key for the specific blog entry. If I change the url to blog_list no primary key is required so I'm taken to the blog_lost page without any issue. How can I add a URL link and ensure it links to the correct blog_detail post?


Solution

  • I made the following changes:

    templates/home.html

    I changed

    <span class="font-weight-bold">
      {{ new.title }}
    </span> &middot;
    

    for

    <span class="font-weight-bold">
      <a href="{% url 'pages_blog_detail' new.pk %}">{{ new.title }}</a>
    </span> &middot;
    

    pages/urls.py

    I added

    from blog.views import BlogDetailView
    

    and changed

    urlpatterns = [
        path('', HomePageView, name='home'),
    ]
    

    to

    urlpatterns = [
        path('blog/<int:pk>/',
            BlogDetailView.as_view(), name='pages_blog_detail'),
        path('', HomePageView, name='home'),
    ]