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.admin import register
from django.contrib.auth.admin import UserAdmin
from .models import User
from .models import Article, User
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.db import models
class User(AbstractUser):
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.messages",
"django.contrib.staticfiles",
"articles",
]
MIDDLEWARE = [
@ -99,7 +100,7 @@ AUTH_PASSWORD_VALIDATORS = [
LANGUAGE_CODE = "en-us"
TIME_ZONE = "UTC"
TIME_ZONE = "Europe/Paris"
USE_I18N = True

View file

@ -16,6 +16,10 @@ Including another URLconf
from django.contrib import admin
from django.urls import path
from articles import views
urlpatterns = [
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
pre-commit==2.6.0
markdown==3.2.2