kan
kan

Reputation: 45

Django: How do I include username in url?

Django2.1

My application wants to include twitter username in url, but an error occurs. I can get uesrname correctly, but I can not connect to url correctly. What is the cause?

An error occurs when accessing detail.

ValueError at /Temporary username/detail
invalid literal for int() with base 10: 'Temporary username'
#views.py
class MyDetailView(DetailView):
    model = Mymodel

class MyCreateView(LoginRequiredMixin, CreateView):
    model = Mymodel
    form_class = MyForm

    def form_valid(self, form):
        obj = form.save(commit=False)
        obj.user = self.request.user
        return super(MyCreateView, self).form_valid(form)

    def get_success_url(self):
        return reverse_lazy('detail', kwargs={"pk": self.request.user.username})
#urls.py
urlpatterns = [
    path('<slug:pk>/detail', MyDetailView.as_view(), name="detail"),
    path('create/', MyCreateView.as_view(), name="create"),
]

Thank you

Upvotes: 1

Views: 2446

Answers (1)

ruddra
ruddra

Reputation: 51978

By default DetailView uses get_object() method to fetch the object from queryset. get_object() uses pk_url_kwarg. Meaning it looks for primary key in url with url parameter pk. Here you are sending the username as pk but in you Mymodel class, primary key is integer id. That is why the error is occuring.

So there are two possible solutions, one is you can change the primary key to username in Mymodel:

class Mymodel(models.Model):  # Please use CamelCase when defining class name
    username = models.CharField(max_length=255, unique=True, primary_key=True)

Another solution is to override the the get_object method inside MyDetailView to get the object:

Its better to rename url parameter anything other than pk, because username is not your pk. You can do it like this:

# view
class MyDetailView(DetailView):
    model = Mymodel

    def get_object(self):
        return get_object_or_404(Mymodel, username=self.kwargs['username'])
# url
path('<str:username>/detail', MyDetailView.as_view(), name="detail"),

# get_success_url in MyCreateView
def get_success_url(self):
    return reverse_lazy('detail', kwargs={"username": self.request.user.username})

Upvotes: 1

Related Questions