feat: article creation
This commit is contained in:
18
articles/migrations/0002_alter_article_title.py
Normal file
18
articles/migrations/0002_alter_article_title.py
Normal file
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 5.2.6 on 2025-10-08 17:49
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('articles', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='article',
|
||||
name='title',
|
||||
field=models.CharField(max_length=200, unique=True),
|
||||
),
|
||||
]
|
||||
@@ -2,7 +2,7 @@ from django.db import models
|
||||
from django.contrib.auth.models import User
|
||||
|
||||
class Article(models.Model):
|
||||
title = models.CharField(max_length=200)
|
||||
title = models.CharField(max_length=200, unique=True)
|
||||
author = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||
text = models.TextField()
|
||||
created_date = models.DateField(auto_now_add=True)
|
||||
|
||||
@@ -56,4 +56,18 @@ a {
|
||||
|
||||
.article-header {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px
|
||||
}
|
||||
|
||||
.submit {
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.text {
|
||||
min-height: 500px;
|
||||
}
|
||||
@@ -13,6 +13,11 @@
|
||||
<img src="{% static 'logo.svg' %}" />
|
||||
<h1>Всё про IT</h1>
|
||||
</div>
|
||||
{% block write %}
|
||||
{% if not user.is_anonymous %}
|
||||
<a href="/article/new">Написать статью</a>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
<div class="archive">
|
||||
{% for post in posts %}
|
||||
<a class="post-link" href="/article/{{ post.id }}">
|
||||
|
||||
21
articles/templates/article_invalid_name.html
Normal file
21
articles/templates/article_invalid_name.html
Normal file
@@ -0,0 +1,21 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Новая статья</title>
|
||||
{% load static %}
|
||||
<link rel="stylesheet" href="{% static 'index.css' %}">
|
||||
<link rel="shortcut icon" type="image/png" href="{% static 'favicon.ico' %}"/>
|
||||
</head>
|
||||
<body>
|
||||
<div class="header">
|
||||
<img src="{% static 'logo.svg' %}" />
|
||||
<h1>Всё про IT</h1>
|
||||
</div>
|
||||
<div class="content">
|
||||
<h1>Название сатьи должно быть уникально!</h1>
|
||||
</div>
|
||||
<p><a href="javascript:history.back()">← Назад к редакированию статьи</a></p>
|
||||
</body>
|
||||
</html>
|
||||
27
articles/templates/new_article.html
Normal file
27
articles/templates/new_article.html
Normal file
@@ -0,0 +1,27 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Новая статья</title>
|
||||
{% load static %}
|
||||
<link rel="stylesheet" href="{% static 'index.css' %}">
|
||||
<link rel="shortcut icon" type="image/png" href="{% static 'favicon.ico' %}"/>
|
||||
</head>
|
||||
<body>
|
||||
<div class="header">
|
||||
<img src="{% static 'logo.svg' %}" />
|
||||
<h1>Всё про IT</h1>
|
||||
</div>
|
||||
<div class="content">
|
||||
<h1>Написать статью</h1>
|
||||
<form method="POST">{% csrf_token %}
|
||||
<input class="title" type="text" name="title" placeholder="Название статьи" value="{{ form.title }}">
|
||||
<textarea class="text" name="text" placeholder="Текст статьи">{{ form.text }}</textarea>
|
||||
<input class="submit" type="submit" value="Сохранить">
|
||||
</form>
|
||||
{{ form.errors }}
|
||||
</div>
|
||||
<p><a href="/">← Назад к списку статей</a></p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,6 +1,7 @@
|
||||
from .models import Article
|
||||
from django.shortcuts import render
|
||||
from django.http import Http404
|
||||
from django.http import Http404, HttpResponse
|
||||
from django.shortcuts import redirect
|
||||
|
||||
def archive(request):
|
||||
return render(request, 'archive.html', {"posts": Article.objects.all()})
|
||||
@@ -8,6 +9,23 @@ def archive(request):
|
||||
def get_article(request, article_id):
|
||||
try:
|
||||
post = Article.objects.get(id=article_id)
|
||||
return render(request, 'article.html', {"post": post})
|
||||
return render(request, 'article.html', {"post": post, "user": request.user})
|
||||
except Article.DoesNotExist:
|
||||
raise Http404
|
||||
|
||||
def create_post(request):
|
||||
if request.method == "POST":
|
||||
form = {
|
||||
'text': request.POST["text"], 'title': request.POST["title"]
|
||||
}
|
||||
if form["text"] and form["title"]:
|
||||
try:
|
||||
article = Article.objects.create(text=form["text"], title=form["title"], author=request.user)
|
||||
return redirect('get_article', article_id=article.id)
|
||||
except:
|
||||
return render(request, 'article_invalid_name.html')
|
||||
|
||||
if not request.user.is_anonymous:
|
||||
return render(request, 'new_article.html')
|
||||
else:
|
||||
return HttpResponse('Unauthorized', status=401)
|
||||
|
||||
@@ -22,4 +22,5 @@ urlpatterns = [
|
||||
path('admin/', admin.site.urls),
|
||||
path('', views.archive),
|
||||
re_path(r'^article/(?P<article_id>\d+)$', views.get_article, name='get_article'),
|
||||
path('article/new/', views.create_post),
|
||||
]
|
||||
|
||||
BIN
db.sqlite3
BIN
db.sqlite3
Binary file not shown.
1
delete.sql
Normal file
1
delete.sql
Normal file
@@ -0,0 +1 @@
|
||||
DELETE FROM articles_article WHERE id > 18
|
||||
Reference in New Issue
Block a user