This commit is contained in:
2024-07-20 11:36:35 +02:00
commit 74b43cd8fa
81 changed files with 3131 additions and 0 deletions

0
blog/__init__.py Normal file
View File

26
blog/admin.py Normal file
View File

@@ -0,0 +1,26 @@
from django.contrib import admin
from ordered_model.admin import OrderedModelAdmin
from .models import Article, Tag, Category
from .forms import ArticleForm
@admin.register(Article)
class ArticleAdmin(admin.ModelAdmin):
form = ArticleForm
list_display = ('title', 'description', 'author')
exclude = ["author"]
def save_model(self, request, obj, form, change):
obj.author = request.user
return super().save_model(request, obj, form, change)
@admin.register(Category)
class CategoryAdmin(OrderedModelAdmin):
list_display = ('name', 'move_up_down_links')
admin.site.register(Tag)

6
blog/apps.py Normal file
View File

@@ -0,0 +1,6 @@
from django.apps import AppConfig
class BlogConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'blog'

13
blog/forms.py Normal file
View File

@@ -0,0 +1,13 @@
from django import forms
from tinymce.widgets import TinyMCE
from blog.models import Article
class ArticleForm(forms.ModelForm):
class Meta:
model = Article
exclude = "__all__"
widgets = {
"content": TinyMCE()
}

View File

@@ -0,0 +1,32 @@
{% extends "blog/layout.html" %}
{% block css %}
{{ super() }}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/themes/prism.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/plugins/toolbar/prism-toolbar.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/plugins/line-numbers/prism-line-numbers.min.css">
{% endblock %}
{% block js %}
{{ super() }}
<script src="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/components/prism-core.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/plugins/autoloader/prism-autoloader.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/plugins/line-numbers/prism-line-numbers.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/plugins/toolbar/prism-toolbar.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/plugins/show-language/prism-show-language.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/plugins/copy-to-clipboard/prism-copy-to-clipboard.min.js"></script>
{% endblock %}
{% block content %}
<article>
<header>
<h2>
{{ article.title }}
</h2>
</header>
<p>{{ article.description.replace("\n", "<br />")|safe }}</p>
<div class="blog_content line-numbers">
{{ article.content|safe }}
</div>
</article>
{% endblock %}

View File

@@ -0,0 +1,34 @@
{% extends "blog/layout.html" %}
{% block content %}
<div id="article_list">
{% for article in articles %}
<a href="{{ url("blog:article_detail", args=[article.pk, slugify(article.title)]) }}">
<article>
{% set article_image %}
<section class="article_image">
{# <img src="{{ static("images/no_mage_600_x_400.svg") }}">#}
<img src="{{ static("images/no_image.png") }}" alt="No image"/>
</section>
{% endset %}
{% set article_text %}
<section class="article_text">
<header>
<h2>{{ article.title }}</h2>
</header>
<p>{{ article.description.replace("\n", "<br/>")|safe }}</p>
</section>
{% endset %}
{{ article_image }}
{{ article_text }}
</article>
</a>
{% else %}
<p>Aucun article</p>
{% endfor %}
</div>
{% endblock %}

View File

@@ -0,0 +1,11 @@
{% extends "base.html" %}
{% block css %}
{{ super() }}
{{ stylesheet_pack("blog") }}
{% endblock %}
{% block js %}
{{ super() }}
{{ javascript_pack("blog") }}
{% endblock %}

View File

@@ -0,0 +1,54 @@
# Generated by Django 5.0.7 on 2024-07-19 08:31
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='Article',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(max_length=255)),
('description', models.TextField()),
('content', models.TextField()),
('date_created', models.DateTimeField(auto_now_add=True)),
('date_modified', models.DateTimeField(auto_now=True)),
],
),
migrations.CreateModel(
name='Category',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('order', models.PositiveIntegerField(db_index=True, editable=False, verbose_name='order')),
('name', models.CharField(max_length=255)),
],
options={
'verbose_name_plural': 'Categories',
'ordering': ('order',),
'abstract': False,
},
),
migrations.CreateModel(
name='Comment',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('content', models.TextField()),
('date_created', models.DateTimeField(auto_now_add=True)),
('date_modified', models.DateTimeField(auto_now=True)),
],
),
migrations.CreateModel(
name='Tag',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=255)),
],
),
]

View File

@@ -0,0 +1,48 @@
# Generated by Django 5.0.7 on 2024-07-19 08:31
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
('blog', '0001_initial'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.AddField(
model_name='article',
name='author',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='article',
name='category',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='blog.category'),
),
migrations.AddField(
model_name='comment',
name='article',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='blog.article'),
),
migrations.AddField(
model_name='comment',
name='author',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='comment',
name='response_to',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='blog.comment'),
),
migrations.AddField(
model_name='article',
name='tags',
field=models.ManyToManyField(blank=True, to='blog.tag'),
),
]

View File

44
blog/models.py Normal file
View File

@@ -0,0 +1,44 @@
from django.db import models
from ordered_model.models import OrderedModel
class Article(models.Model):
title = models.CharField(max_length=255)
description = models.TextField()
content = models.TextField()
date_created = models.DateTimeField(auto_now_add=True)
date_modified = models.DateTimeField(auto_now=True)
category = models.ForeignKey("Category", on_delete=models.CASCADE, null=True, blank=True)
tags = models.ManyToManyField("Tag", blank=True)
author = models.ForeignKey("user.User", on_delete=models.CASCADE, null=True, blank=True)
def __str__(self):
return self.title
class Category(OrderedModel):
name = models.CharField(max_length=255)
class Meta(OrderedModel.Meta):
verbose_name_plural = "Categories"
def __str__(self):
return self.name
class Tag(models.Model):
name = models.CharField(max_length=255)
def __str__(self):
return self.name
class Comment(models.Model):
author = models.ForeignKey("user.User", on_delete=models.CASCADE)
article = models.ForeignKey("Article", on_delete=models.CASCADE)
content = models.TextField()
date_created = models.DateTimeField(auto_now_add=True)
date_modified = models.DateTimeField(auto_now=True)
response_to = models.ForeignKey("self", on_delete=models.CASCADE, null=True, blank=True)

View File

@@ -0,0 +1,32 @@
{% extends "blog/layout.html" %}
{% block css %}
{{ super() }}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/themes/prism.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/plugins/toolbar/prism-toolbar.min.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/plugins/line-numbers/prism-line-numbers.min.css">
{% endblock %}
{% block js %}
{{ super() }}
<script src="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/components/prism-core.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/plugins/autoloader/prism-autoloader.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/plugins/line-numbers/prism-line-numbers.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/plugins/toolbar/prism-toolbar.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/plugins/show-language/prism-show-language.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/prismjs@1.29.0/plugins/copy-to-clipboard/prism-copy-to-clipboard.min.js"></script>
{% endblock %}
{% block content %}
<article>
<header>
<h2>
{{ article.title }}
</h2>
</header>
<p>{{ article.description.replace("\n", "<br />")|safe }}</p>
<div class="blog_content line-numbers">
{{ article.content|safe }}
</div>
</article>
{% endblock %}

View File

@@ -0,0 +1,34 @@
{% extends "blog/layout.html" %}
{% load static %}
{% block content %}
<div id="article_list">
{% for article in articles %}
<a href="{% url "blog:article_detail" article.pk article.title|slugify %}">
<article>
{# {% set article_image %}#}
{# <section class="article_image">#}
{# <img src="{{ static("images/no_mage_600_x_400.svg") }}">#}
{# <img src="{% static "images/no_image.png" %}" alt="No image"/>#}
{# </section>#}
{# {% endset %}#}
{##}
{# {% set article_text %}#}
{# <section class="article_text">#}
{# <header>#}
{# <h2>{{ article.title }}</h2>#}
{# </header>#}
{# <p>{{ article.description|safe|linebreaks }}</p>#}
{# </section>#}
{# {% endset %}#}
{# {{ article_image }}#}
{# {{ article_text }}#}
</article>
</a>
{% empty %}
<p>Aucun article</p>
{% endfor %}
</div>
{% endblock %}

View File

@@ -0,0 +1,11 @@
{% extends "base.html" %}
{% block css %}
{{ super }}
{# {{ stylesheet_pack("blog") }}#}
{% endblock %}
{% block js %}
{{ super }}
{# {{ javascript_pack("blog") }}#}
{% endblock %}

3
blog/tests.py Normal file
View File

@@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

9
blog/urls.py Normal file
View File

@@ -0,0 +1,9 @@
from django.urls import path
from . import views
app_name = 'blog'
urlpatterns = [
path("", views.ArticleListView.as_view(), name="article_list"),
path("<int:pk>-<str:slug>/", views.ArticleDetailView.as_view(), name="article_detail"),
]

15
blog/views.py Normal file
View File

@@ -0,0 +1,15 @@
from django.views.generic import ListView, DetailView
from blog.models import Article
class ArticleListView(ListView):
model = Article
template_name = 'blog/article_list.html'
context_object_name = 'articles'
class ArticleDetailView(DetailView):
model = Article
template_name = 'blog/article_detail.html'
context_object_name = 'article'