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
|
from django.contrib.auth.models import User
|
||||||
|
|
||||||
class Article(models.Model):
|
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)
|
author = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||||
text = models.TextField()
|
text = models.TextField()
|
||||||
created_date = models.DateField(auto_now_add=True)
|
created_date = models.DateField(auto_now_add=True)
|
||||||
|
|||||||
@@ -56,4 +56,18 @@ a {
|
|||||||
|
|
||||||
.article-header {
|
.article-header {
|
||||||
margin: 0;
|
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' %}" />
|
<img src="{% static 'logo.svg' %}" />
|
||||||
<h1>Всё про IT</h1>
|
<h1>Всё про IT</h1>
|
||||||
</div>
|
</div>
|
||||||
|
{% block write %}
|
||||||
|
{% if not user.is_anonymous %}
|
||||||
|
<a href="/article/new">Написать статью</a>
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
||||||
<div class="archive">
|
<div class="archive">
|
||||||
{% for post in posts %}
|
{% for post in posts %}
|
||||||
<a class="post-link" href="/article/{{ post.id }}">
|
<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 .models import Article
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
from django.http import Http404
|
from django.http import Http404, HttpResponse
|
||||||
|
from django.shortcuts import redirect
|
||||||
|
|
||||||
def archive(request):
|
def archive(request):
|
||||||
return render(request, 'archive.html', {"posts": Article.objects.all()})
|
return render(request, 'archive.html', {"posts": Article.objects.all()})
|
||||||
@@ -8,6 +9,23 @@ def archive(request):
|
|||||||
def get_article(request, article_id):
|
def get_article(request, article_id):
|
||||||
try:
|
try:
|
||||||
post = Article.objects.get(id=article_id)
|
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:
|
except Article.DoesNotExist:
|
||||||
raise Http404
|
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('admin/', admin.site.urls),
|
||||||
path('', views.archive),
|
path('', views.archive),
|
||||||
re_path(r'^article/(?P<article_id>\d+)$', views.get_article, name='get_article'),
|
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