How can I configure these multiple slugs in my urls and views: Django

Question:

I’ve been trying to configure my urls and views for this password safe app

  • a site can have many accounts, and to edit an account I plan to use this url config:
    home/[sitename]/[accountusername]/edit/. but its bringing errors. How do I go about this?

views.py:

class SiteDetailView(DetailView):
    model = Site
    template_name = "site_detail.html"


class SiteDeleteView(DeleteView):
    model = Site
    template_name = "site_delete.html"
    success_url = reverse_lazy("home")


class SiteEditView(UpdateView):
    model = Site
    template_name = "site_edit.html"
    fields = ("siteName",)


class AccountDeleteView(DeleteView):
    model = Account
    template_name = "account_delete.html"

    # def get_success_url(self):
      #  return reverse_lazy("site_detail", kwargs={"slug": self.object.slug})


class AccountEditView(UpdateView):
    model = Account
    template_name = "account_edit.html"
    fields = (
        "username",
        "password",
    )

urls.py:

from django.urls import path
from .views import (
    IndexView,
    HomePageView,
    SiteDetailView,
    SiteDeleteView,
    AccountDeleteView,
    AccountEditView,
    SiteEditView,
)

urlpatterns = [
    path("home/<slug:slug>/edit/", SiteEditView.as_view(), name="site_edit"),
    path(
        "home/<slug:slug>/<slug:slug_field>/edit/",
        AccountEditView.as_view(),
        name="account_edit",
    ),
    path(
        "home/<slug:slug>/<slug:slug_field>/delete/",
        AccountDeleteView.as_view(),
        name="account_delete",
    ),
    path("home/<slug:slug>/delete/", SiteDeleteView.as_view(), name="site_delete"),
    path("home/<slug:slug>/", SiteDetailView.as_view(), name="site_detail"),
    path("home", HomePageView.as_view(), name="home"),
    path("", IndexView.as_view(), name="index"),
]

models.py:

from django.db import models
from django.urls import reverse
from django.conf import settings
from django.template.defaultfilters import slugify


class Site(models.Model):
    siteName = models.CharField(max_length=200)
    author = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
    )
    slug = models.SlugField(null=False, unique=True)
    date = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.siteName

    def get_absolute_url(self):
        return reverse("site_detail", kwargs={"slug": self.slug})

    def save(self, *args, **kwargs):
        if not self.slug:
            self.slug = slugify(self.siteName)
        return super().save(*args, **kwargs)


class Account(models.Model):
    site_name = models.ForeignKey(Site, on_delete=models.CASCADE)
    username = models.CharField(max_length=140)
    password = models.CharField(max_length=50)
    slug_field = models.SlugField(null=False, unique=True)

    def __str__(self):
        return self.username

    def get_absolute_url(self):
        return reverse("home")

    def save(self, *args, **kwargs):
        if not self.slug_field:
            self.slug_field = slugify(self.username)
        return super().save(*args, **kwargs)

my site_detail.html:

{% extends 'base.html' %}
{% block content %}
<h2>{{ object.siteName }}</h2>
<hr>
{% for username in object.account_set.all %}
<p>Username: {{ username.username }}</p>
<p>Password: {{ username.password }}</p>
<p><a href="{% url 'account_edit' object.slug username.slug_field %}"><button type="button">Edit account</button></a>
<a href="#"><button type="button">Delete account</button></a></p>
<hr>
{% endfor %}
<p><a href="{% url 'site_delete' object.slug %}"><button type="button">Delete site</button></a>
  <a href="{% url 'site_edit' object.slug %}"><button type="button">Edit site</button></a></p>
{% endblock content %}

The current error I am facing:

    raise FieldError(
django.core.exceptions.FieldError: Cannot resolve keyword 'site' into field. Choices are: id, password, site_name, site_name_id, slug_field, username

This is how a detail view looks at url http://127.0.0.1:8000/home/redditcom/
this is how a detail view looks at url http://127.0.0.1:8000/home/redditcom/

Asked By: Boluwatife Promise

||

Answers:

You use siteName in your Site model and site_name in your Account model. I’m not sure what code is generating the error since I don’t see anything referencing just site in what you posted here, but if you look at the error, you can see from the other fields listed that it’s referencing the Account model. So you need to replace site with site_name somewhere.

Answered By: mattsl

For me, when doing stuffs like this, you use use a unique slug. You can add a random unique number to the slug by generating it from uuid4, and using a while loop go make sure no slug repeats its self .

Just create a util.py file in your app and write the function to generate a random unique number the add it to your slug in the models

Answered By: Christian Glory

For Django to clearly handle the slug, the field name should be named as "slug", so, for your Site model there will be no problem, but, for account model you named it "slug_field", then, you have 2 options:

  1. Change the "slug_field" to just "slug".
  2. Override the slug field in the Account Views so Django takes them as the slug field, like this:
slug_field = "slug_field"
slug_url_kwarg = "slug_field" 
Answered By: Alejandro Franco