django URLs MultipleObjectsReturned error

Viewed 96

I am making a simple webapp with Django. A user can have a profile, and under that profile create a blog post.

For example:

"path('profile/<int:pk>/',profile, name='profile')" 

Returns the URL

"http://127.0.0.1:8000/profile/1/"

A user can then write blog posts which have the name in the URL

Example:

path('profile/<int:pk>/blog/<str:name>',Blogs, name='Blogs'),

Returns the URL

"http://127.0.0.1:8000/profile/1/blog/HelloWOrld"

However, IF two different users both name their blogs the same exact name, i get a 'MultipleObjectsReturned' Error.

I thought that by having the user PK earlier in the URL it would ensure that it would be unique, even if two blogs were called the exact same thing.

Views.py

def Blog(request, pk, name):
    blog = Restaurant.objects.get(name=name)
    user = CustomUser.objects.get(pk=pk)
    if not user.id == request.user.pk:
        raise PermissionDenied()
    else:
        context = {
            'user': user,
            'blog': blog,
        }
        return render(request, 'blog/blogs.html',context)

IS there any way to work around this without using the PK of the blog as well? And if anyone could explain why my logic was wrong and it wasn't working in the first place.

Thanks.

2 Answers

You need to make sure you get the blog of that name of that user. I don't know exactly how your blog models look, but it's going to be something like

user = CustomUser.objects.get(pk=pk)
blog = Restaurant.objects.get(name=name, user=user)

And on the model, use the 'unique_together' property to ensure that the combination of user and blog name are unique, otherwise these URLs aren't going to work. Having the name completely unique as in George's answer isn't necessary and would mean that users couldn't create blog posts with titles already made by another user.

You need to make name field unique, and use SlugField for this if you want to use clean url:

class Restaurant(models.Model):
    name = models.CharField(unique=True, ...)
    slug = models.SlugField(unique=True, ...)
    ...
Related