Add basis to work on articles

This commit is contained in:
Gabriel Augendre 2020-08-14 15:53:42 +02:00
parent ec31d838c1
commit 75e1bec1d0
13 changed files with 324 additions and 4 deletions

View file

@ -1,6 +1,37 @@
from django.contrib import admin from django.contrib import admin
from django.contrib.admin import register
from django.contrib.auth.admin import UserAdmin from django.contrib.auth.admin import UserAdmin
from .models import User from .models import Article, User
admin.site.register(User, UserAdmin) admin.site.register(User, UserAdmin)
@register(Article)
class ArticleAdmin(admin.ModelAdmin):
list_display = [
"title",
"status",
"author",
"created_at",
"published_at",
"updated_at",
]
list_display_links = ["title"]
list_filter = ["status"]
date_hierarchy = "created_at"
fieldsets = [
(
"Metadata",
{
"fields": (
"title",
"status",
("created_at", "published_at", "updated_at"),
"author",
)
},
),
("Content", {"fields": ("content",)}),
]
readonly_fields = ["created_at", "updated_at"]

View file

@ -0,0 +1,130 @@
# Generated by Django 3.1 on 2020-08-14 12:56
import django.contrib.auth.models
import django.contrib.auth.validators
import django.utils.timezone
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
("auth", "0012_alter_user_first_name_max_length"),
]
operations = [
migrations.CreateModel(
name="User",
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("password", models.CharField(max_length=128, verbose_name="password")),
(
"last_login",
models.DateTimeField(
blank=True, null=True, verbose_name="last login"
),
),
(
"is_superuser",
models.BooleanField(
default=False,
help_text="Designates that this user has all permissions without explicitly assigning them.",
verbose_name="superuser status",
),
),
(
"username",
models.CharField(
error_messages={
"unique": "A user with that username already exists."
},
help_text="Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.",
max_length=150,
unique=True,
validators=[
django.contrib.auth.validators.UnicodeUsernameValidator()
],
verbose_name="username",
),
),
(
"first_name",
models.CharField(
blank=True, max_length=150, verbose_name="first name"
),
),
(
"last_name",
models.CharField(
blank=True, max_length=150, verbose_name="last name"
),
),
(
"email",
models.EmailField(
blank=True, max_length=254, verbose_name="email address"
),
),
(
"is_staff",
models.BooleanField(
default=False,
help_text="Designates whether the user can log into this admin site.",
verbose_name="staff status",
),
),
(
"is_active",
models.BooleanField(
default=True,
help_text="Designates whether this user should be treated as active. Unselect this instead of deleting accounts.",
verbose_name="active",
),
),
(
"date_joined",
models.DateTimeField(
default=django.utils.timezone.now, verbose_name="date joined"
),
),
(
"groups",
models.ManyToManyField(
blank=True,
help_text="The groups this user belongs to. A user will get all permissions granted to each of their groups.",
related_name="user_set",
related_query_name="user",
to="auth.Group",
verbose_name="groups",
),
),
(
"user_permissions",
models.ManyToManyField(
blank=True,
help_text="Specific permissions for this user.",
related_name="user_set",
related_query_name="user",
to="auth.Permission",
verbose_name="user permissions",
),
),
],
options={
"verbose_name": "user",
"verbose_name_plural": "users",
"abstract": False,
},
managers=[("objects", django.contrib.auth.models.UserManager()),],
),
]

View file

@ -0,0 +1,50 @@
# Generated by Django 3.1 on 2020-08-14 13:16
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("articles", "0001_initial"),
]
operations = [
migrations.CreateModel(
name="Article",
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("title", models.CharField(max_length=255)),
("content", models.TextField()),
(
"status",
models.CharField(
choices=[("draft", "Draft"), ("published", "Published")],
default="draft",
max_length=15,
),
),
("published_at", models.DateTimeField(null=True)),
("created_at", models.DateTimeField(auto_now_add=True)),
("updated_at", models.DateTimeField(auto_now=True)),
(
"author",
models.ForeignKey(
on_delete=django.db.models.deletion.PROTECT,
to=settings.AUTH_USER_MODEL,
),
),
],
options={"ordering": ["-published_at"],},
),
]

View file

@ -0,0 +1,18 @@
# Generated by Django 3.1 on 2020-08-14 13:22
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("articles", "0002_article"),
]
operations = [
migrations.AlterField(
model_name="article",
name="published_at",
field=models.DateTimeField(blank=True, null=True),
),
]

View file

@ -1,6 +1,35 @@
import markdown
from django.contrib.auth.models import AbstractUser from django.contrib.auth.models import AbstractUser
from django.db import models from django.db import models
class User(AbstractUser): class User(AbstractUser):
pass pass
class Article(models.Model):
DRAFT = "draft"
PUBLISHED = "published"
STATUS_CHOICES = [
(DRAFT, "Draft"),
(PUBLISHED, "Published"),
]
title = models.CharField(max_length=255)
content = models.TextField()
status = models.CharField(max_length=15, choices=STATUS_CHOICES, default=DRAFT)
published_at = models.DateTimeField(null=True, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
author = models.ForeignKey(User, on_delete=models.PROTECT)
class Meta:
ordering = ["-published_at"]
def get_abstract(self):
md = markdown.Markdown(extensions=["extra"])
html = md.convert(self.content)
return html.split("<!--more-->")[0]
def get_formatted_content(self):
md = markdown.Markdown(extensions=["extra"])
return md.convert(self.content)

View file

@ -0,0 +1,6 @@
.content {
max-width: 640px;
margin-left: auto;
margin-right: auto;
font-family: Arial, sans-serif;
}

View file

@ -0,0 +1,12 @@
{% extends 'articles/base.html' %}
{% block content %}
<h1>{{ article.title }}</h1>
<p>By: {{ article.author }}</p>
<p>Published at: {{ article.published_at }}</p>
<p>Updated at: {{ article.updated_at }}</p>
<div>
{{ article.get_formatted_content|safe }}
</div>
{% endblock %}

View file

@ -0,0 +1,12 @@
{% extends 'articles/base.html' %}
{% block content %}
<h1>Articles list</h1>
{% for article in articles %}
<article>
<h2>{{ article.title }}</h2>
<p>{{ article.get_abstract|safe }}</p>
<p><a href="{% url 'article-detail' pk=article.pk %}">Read more</a></p>
</article>
{% endfor %}
{% endblock %}

View file

@ -0,0 +1,15 @@
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Gabnotes</title>
<link rel="stylesheet" href="{% static 'style.css' %}" type="text/css">
</head>
<body>
<div class="content">
{% block content %}
{% endblock %}
</div>
</body>
</html>

View file

@ -1,3 +1,14 @@
from django.shortcuts import render from django.views import generic
# Create your views here. from articles.models import Article
class ArticlesListView(generic.ListView):
model = Article
paginate_by = 15
context_object_name = "articles"
class ArticleDetailView(generic.DetailView):
model = Article
context_object_name = "article"

View file

@ -37,6 +37,7 @@ INSTALLED_APPS = [
"django.contrib.sessions", "django.contrib.sessions",
"django.contrib.messages", "django.contrib.messages",
"django.contrib.staticfiles", "django.contrib.staticfiles",
"articles",
] ]
MIDDLEWARE = [ MIDDLEWARE = [
@ -99,7 +100,7 @@ AUTH_PASSWORD_VALIDATORS = [
LANGUAGE_CODE = "en-us" LANGUAGE_CODE = "en-us"
TIME_ZONE = "UTC" TIME_ZONE = "Europe/Paris"
USE_I18N = True USE_I18N = True

View file

@ -16,6 +16,10 @@ Including another URLconf
from django.contrib import admin from django.contrib import admin
from django.urls import path from django.urls import path
from articles import views
urlpatterns = [ urlpatterns = [
path("admin/", admin.site.urls), path("admin/", admin.site.urls),
path("", views.ArticlesListView.as_view(), name="articles-list"),
path("<int:pk>", views.ArticleDetailView.as_view(), name="article-detail"),
] ]

View file

@ -1,2 +1,3 @@
django==3.1 django==3.1
pre-commit==2.6.0 pre-commit==2.6.0
markdown==3.2.2