This commit is contained in:
Gabriel Augendre 2020-08-16 19:45:38 +02:00
parent 54d8d989be
commit 0fb2ff99bd
5 changed files with 35 additions and 5 deletions

View file

@ -27,7 +27,7 @@ class ArticleAdmin(admin.ModelAdmin):
"Metadata", "Metadata",
{ {
"fields": ( "fields": (
"title", ("title", "slug"),
("author", "status"), ("author", "status"),
("published_at", "created_at", "updated_at"), ("published_at", "created_at", "updated_at"),
"views_count", "views_count",
@ -42,6 +42,7 @@ class ArticleAdmin(admin.ModelAdmin):
"widget": forms.Textarea(attrs={"cols": "100", "rows": "50"}) "widget": forms.Textarea(attrs={"cols": "100", "rows": "50"})
}, },
} }
prepopulated_fields = {"slug": ("title",)}
def publish(self, request, queryset): def publish(self, request, queryset):
if not request.user.has_perm("articles.change_article"): if not request.user.has_perm("articles.change_article"):

View file

@ -0,0 +1,22 @@
# Generated by Django 3.1 on 2020-08-16 17:37
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("articles", "0004_article_views_count"),
]
operations = [
migrations.AddField(
model_name="article",
name="slug",
field=models.SlugField(
default="designing-and-3d-printing-a-wall-mount-for-my-isp-modem",
unique=True,
),
preserve_default=False,
),
]

View file

@ -4,6 +4,7 @@ import markdown
from django.contrib.auth.models import AbstractUser from django.contrib.auth.models import AbstractUser
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.db import models from django.db import models
from django.template.defaultfilters import slugify
from django.urls import reverse from django.urls import reverse
from django.utils import timezone from django.utils import timezone
@ -27,6 +28,7 @@ class Article(models.Model):
updated_at = models.DateTimeField(auto_now=True) updated_at = models.DateTimeField(auto_now=True)
author = models.ForeignKey(User, on_delete=models.PROTECT) author = models.ForeignKey(User, on_delete=models.PROTECT)
views_count = models.IntegerField(default=0) views_count = models.IntegerField(default=0)
slug = models.SlugField(unique=True)
class Meta: class Meta:
ordering = ["-published_at"] ordering = ["-published_at"]
@ -42,7 +44,7 @@ class Article(models.Model):
) )
def get_absolute_url(self): def get_absolute_url(self):
return reverse("article-detail", kwargs={"pk": self.pk}) return reverse("article-detail", kwargs={"slug": self.slug})
def get_abstract(self): def get_abstract(self):
html = self.get_formatted_content() html = self.get_formatted_content()
@ -64,3 +66,8 @@ class Article(models.Model):
self.published_at = None self.published_at = None
self.status = self.DRAFT self.status = self.DRAFT
self.save() self.save()
def save(self, *args, **kwargs): # new
if not self.slug:
self.slug = slugify(self.title)
return super().save(*args, **kwargs)

View file

@ -4,10 +4,10 @@
<h1>{{ title }} list</h1> <h1>{{ title }} list</h1>
{% for article in articles %} {% for article in articles %}
<article> <article>
<h2><a href="{% url 'article-detail' pk=article.pk %}">{{ article.title }}</a></h2> <h2><a href="{% url 'article-detail' slug=article.slug %}">{{ article.title }}</a></h2>
{% include "articles/metadata_snippet.html" %} {% include "articles/metadata_snippet.html" %}
<p>{{ article.get_abstract|safe }}</p> <p>{{ article.get_abstract|safe }}</p>
<p><a href="{% url 'article-detail' pk=article.pk %}">Read more</a></p> <p><a href="{% url 'article-detail' slug=article.slug %}">Read more</a></p>
</article> </article>
{% empty %} {% empty %}
<p>No article here. Come back later 🙂</p> <p>No article here. Come back later 🙂</p>

View file

@ -22,6 +22,6 @@ urlpatterns = [
path("admin/", admin.site.urls), path("admin/", admin.site.urls),
path("", html.ArticlesListView.as_view(), name="articles-list"), path("", html.ArticlesListView.as_view(), name="articles-list"),
path("drafts/", html.DraftsListView.as_view(), name="drafts-list"), path("drafts/", html.DraftsListView.as_view(), name="drafts-list"),
path("<int:pk>", html.ArticleDetailView.as_view(), name="article-detail"), path("<slug:slug>", html.ArticleDetailView.as_view(), name="article-detail"),
path("feed/", feeds.CompleteFeed(), name="complete-feed"), path("feed/", feeds.CompleteFeed(), name="complete-feed"),
] ]