lesson 47

parents
lesson_41_venv
.idea
venv
db.sqlite3
**/__pycache__
\ No newline at end of file
* {
margin: 0;
padding: 0;
}
.box {
width: 100px;
height: 100px;
}
body {
font-family: Arial, sans-serif;
font-size: 16px;
color: #444444;
background-color: pink;
}
.container {
margin: 0 auto;
width: 100%;
max-width: 900px;
text-align: center;
}
.field-error {
border: solid 1px red;
box-shadow: red 0 0 3px;
}
.form-error {
color: red;
font-size: 12px;
margin: 5px 0 0 0;
}
"""
ASGI config for core project.
It exposes the ASGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/3.2/howto/deployment/asgi/
"""
import os
from django.core.asgi import get_asgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'core.settings')
application = get_asgi_application()
"""
Django settings for core project.
Generated by 'django-admin startproject' using Django 3.2.19.
For more information on this file, see
https://docs.djangoproject.com/en/3.2/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/3.2/ref/settings/
"""
import os
from pathlib import Path
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/3.2/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'django-insecure-@fz8szm5kt0)7x6upuw(lanx3#m^gr7kdh$9$d&+26e%jvj43b'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = []
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'web'
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'core.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'core.wsgi.application'
# Database
# https://docs.djangoproject.com/en/3.2/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
# Password validation
# https://docs.djangoproject.com/en/3.2/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
# {
# 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
# },
# {
# 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
# },
# {
# 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
# },
# {
# 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
# },
]
# Internationalization
# https://docs.djangoproject.com/en/3.2/topics/i18n/
LANGUAGE_CODE = 'ru-ru'
TIME_ZONE = 'Asia/Almaty'
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/3.2/howto/static-files/
STATIC_URL = '/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'banana')
]
#
#
# # Media files
#
# MEDIA_URL = '/media/'
# MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
# Default primary key field type
# https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
"""core URL Configuration
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/3.2/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.conf import settings
from django.conf.urls.static import static
from django.contrib import admin
from django.urls import path
from web import views
urlpatterns = [
path('admin/', admin.site.urls),
path('', views.index_view, name='main-page'),
path('articles/add/', views.ArticleCreateView.as_view(), name='articles-add'),
# /articles/1/ OR /articles/?id=1
# article_details_view(request, id)
path('articles/<int:id>/', views.article_detail_view, name='articles-detail'),
path('articles/<int:id>/edit', views.article_update_view, name='article_update'),
path('articles/<int:id>/delete', views.delete_article, name='delete_article')
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
"""
WSGI config for core project.
It exposes the WSGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/3.2/howto/deployment/wsgi/
"""
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'core.settings')
application = get_wsgi_application()
#!/usr/bin/env python
"""Django's command-line utility for administrative tasks."""
import os
import sys
def main():
"""Run administrative tasks."""
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'core.settings')
try:
from django.core.management import execute_from_command_line
except ImportError as exc:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
) from exc
execute_from_command_line(sys.argv)
if __name__ == '__main__':
main()
asgiref==3.7.2
Django==3.2.19
pytz==2023.3
sqlparse==0.4.4
from django.contrib import admin
from web.models import Article
class ArticleAdmin(admin.ModelAdmin):
list_display = ['id', 'title', 'author', 'created_at']
list_filter = ['author']
search_fields = ['title', 'text']
fields = ['title', 'author', 'text', 'created_at', 'updated_at']
readonly_fields = ['created_at', 'updated_at']
admin.site.register(Article, ArticleAdmin)
from django.apps import AppConfig
class WebConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'web'
[
{
"model": "web.article",
"pk": 2,
"fields": {
"title": "Война и Мир",
"text": "Много текста",
"author": "Л. Толстой",
"created_at": "2023-06-15T11:08:41.578Z",
"updated_at": "2023-06-15T11:08:41.578Z"
}
},
{
"model": "web.article",
"pk": 3,
"fields": {
"title": "Анегин",
"text": "Евгений Анегин",
"author": "А. Пушкин",
"created_at": "2023-06-15T11:09:39.149Z",
"updated_at": "2023-06-15T11:09:39.150Z"
}
},
{
"model": "web.article",
"pk": 1,
"fields": {
"title": "У лукоморья",
"text": "У лукоморья дуб зеленый",
"author": "А. Пушкин",
"created_at": "2023-06-15T11:11:36.213Z",
"updated_at": "2023-06-15T11:20:02.767Z"
}
},
{
"model": "web.article",
"pk": 7,
"fields": {
"title": "Бородино",
"text": "Скажи ка дядя ведь не даром ...",
"author": "М. Лермонтов",
"created_at": "2023-06-15T11:21:23.882Z",
"updated_at": "2023-06-15T11:21:34.525Z"
}
}
]
[
{
"model": "auth.permission",
"pk": 1,
"fields": {
"name": "Can add log entry",
"content_type": 1,
"codename": "add_logentry"
}
},
{
"model": "auth.permission",
"pk": 2,
"fields": {
"name": "Can change log entry",
"content_type": 1,
"codename": "change_logentry"
}
},
{
"model": "auth.permission",
"pk": 3,
"fields": {
"name": "Can delete log entry",
"content_type": 1,
"codename": "delete_logentry"
}
},
{
"model": "auth.permission",
"pk": 4,
"fields": {
"name": "Can view log entry",
"content_type": 1,
"codename": "view_logentry"
}
},
{
"model": "auth.permission",
"pk": 5,
"fields": {
"name": "Can add permission",
"content_type": 2,
"codename": "add_permission"
}
},
{
"model": "auth.permission",
"pk": 6,
"fields": {
"name": "Can change permission",
"content_type": 2,
"codename": "change_permission"
}
},
{
"model": "auth.permission",
"pk": 7,
"fields": {
"name": "Can delete permission",
"content_type": 2,
"codename": "delete_permission"
}
},
{
"model": "auth.permission",
"pk": 8,
"fields": {
"name": "Can view permission",
"content_type": 2,
"codename": "view_permission"
}
},
{
"model": "auth.permission",
"pk": 9,
"fields": {
"name": "Can add group",
"content_type": 3,
"codename": "add_group"
}
},
{
"model": "auth.permission",
"pk": 10,
"fields": {
"name": "Can change group",
"content_type": 3,
"codename": "change_group"
}
},
{
"model": "auth.permission",
"pk": 11,
"fields": {
"name": "Can delete group",
"content_type": 3,
"codename": "delete_group"
}
},
{
"model": "auth.permission",
"pk": 12,
"fields": {
"name": "Can view group",
"content_type": 3,
"codename": "view_group"
}
},
{
"model": "auth.permission",
"pk": 13,
"fields": {
"name": "Can add user",
"content_type": 4,
"codename": "add_user"
}
},
{
"model": "auth.permission",
"pk": 14,
"fields": {
"name": "Can change user",
"content_type": 4,
"codename": "change_user"
}
},
{
"model": "auth.permission",
"pk": 15,
"fields": {
"name": "Can delete user",
"content_type": 4,
"codename": "delete_user"
}
},
{
"model": "auth.permission",
"pk": 16,
"fields": {
"name": "Can view user",
"content_type": 4,
"codename": "view_user"
}
},
{
"model": "auth.permission",
"pk": 17,
"fields": {
"name": "Can add content type",
"content_type": 5,
"codename": "add_contenttype"
}
},
{
"model": "auth.permission",
"pk": 18,
"fields": {
"name": "Can change content type",
"content_type": 5,
"codename": "change_contenttype"
}
},
{
"model": "auth.permission",
"pk": 19,
"fields": {
"name": "Can delete content type",
"content_type": 5,
"codename": "delete_contenttype"
}
},
{
"model": "auth.permission",
"pk": 20,
"fields": {
"name": "Can view content type",
"content_type": 5,
"codename": "view_contenttype"
}
},
{
"model": "auth.permission",
"pk": 21,
"fields": {
"name": "Can add session",
"content_type": 6,
"codename": "add_session"
}
},
{
"model": "auth.permission",
"pk": 22,
"fields": {
"name": "Can change session",
"content_type": 6,
"codename": "change_session"
}
},
{
"model": "auth.permission",
"pk": 23,
"fields": {
"name": "Can delete session",
"content_type": 6,
"codename": "delete_session"
}
},
{
"model": "auth.permission",
"pk": 24,
"fields": {
"name": "Can view session",
"content_type": 6,
"codename": "view_session"
}
},
{
"model": "auth.permission",
"pk": 25,
"fields": {
"name": "Can add article",
"content_type": 7,
"codename": "add_article"
}
},
{
"model": "auth.permission",
"pk": 26,
"fields": {
"name": "Can change article",
"content_type": 7,
"codename": "change_article"
}
},
{
"model": "auth.permission",
"pk": 27,
"fields": {
"name": "Can delete article",
"content_type": 7,
"codename": "delete_article"
}
},
{
"model": "auth.permission",
"pk": 28,
"fields": {
"name": "Can view article",
"content_type": 7,
"codename": "view_article"
}
},
{
"model": "auth.user",
"pk": 1,
"fields": {
"password": "pbkdf2_sha256$260000$cUTyu2bXGpA5G3OvGNIbrA$91PaHsudIfSxWq4gp8iQH7XtH5HW7TMgPXt0lNRkXYo=",
"last_login": "2023-06-05T10:42:44.554Z",
"is_superuser": true,
"username": "davidlee",
"first_name": "",
"last_name": "",
"email": "",
"is_staff": true,
"is_active": true,
"date_joined": "2023-06-05T10:40:57.228Z",
"groups": [],
"user_permissions": []
}
},
{
"model": "auth.user",
"pk": 2,
"fields": {
"password": "pbkdf2_sha256$260000$LmPUwtCla9xfjukIydXWT4$NBJcl2eZdjvwhRaDfiNXgX2Fj/HJzTroyfvMsRg746s=",
"last_login": null,
"is_superuser": false,
"username": "admin",
"first_name": "",
"last_name": "",
"email": "",
"is_staff": false,
"is_active": true,
"date_joined": "2023-06-05T10:43:18.831Z",
"groups": [],
"user_permissions": []
}
},
{
"model": "auth.user",
"pk": 3,
"fields": {
"password": "pbkdf2_sha256$260000$GJw0btzLKy9YEdrNoRScps$xvfyVJqSxI+06Qd46osGoeQhk/1Q4ffdIryjplvrR1Y=",
"last_login": "2023-06-15T11:17:33.472Z",
"is_superuser": true,
"username": "root",
"first_name": "",
"last_name": "",
"email": "root@root.root",
"is_staff": true,
"is_active": true,
"date_joined": "2023-06-15T11:17:26.554Z",
"groups": [],
"user_permissions": []
}
}
]
from django import forms
from django.forms import widgets
class ArticleForm(forms.Form):
title = forms.CharField(max_length=200, required=True, label='Title')
author = forms.CharField(max_length=40, required=True, label='Author')
status = forms.CharField(required=True, label='Status')
text = forms.CharField(max_length=3000, required=True, label='Text', widget=widgets.Textarea)
\ No newline at end of file
# Generated by Django 3.2.19 on 2023-06-15 10:30
from django.db import migrations, models
# squash migrations
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')),
('test', models.CharField(max_length=200, verbose_name='Заголовок')),
('title', models.CharField(max_length=200, verbose_name='Заголовок')),
('text', models.TextField(max_length=3000, verbose_name='Текст')),
('author', models.CharField(default='Unknown', max_length=100, verbose_name='Автор')),
('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Дата создания')),
('updated_at', models.DateTimeField(auto_now=True, verbose_name='Дата обновления')),
],
),
]
# Generated by Django 3.2.19 on 2023-06-15 10:41
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('web', '0001_initial'),
]
operations = [
migrations.RemoveField(
model_name='article',
name='test',
),
]
# Generated by Django 3.2.19 on 2023-06-15 11:27
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('web', '0002_remove_article_test'),
]
operations = [
migrations.AlterModelOptions(
name='article',
options={'verbose_name': 'статью', 'verbose_name_plural': 'статьи'},
),
]
# Generated by Django 3.2.19 on 2023-06-21 10:06
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('web', '0003_alter_article_options'),
]
operations = [
migrations.AddField(
model_name='article',
name='status',
field=models.CharField(choices=[['accepted', 'Разрешено'], ['unaccepted', 'Не разрешено'], ['check', 'На проверке']], default='check', max_length=100),
),
]
# Generated by Django 3.2.19 on 2023-06-21 10:17
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('web', '0004_article_status'),
]
operations = [
migrations.AlterField(
model_name='article',
name='status',
field=models.CharField(choices=[('accepted', 'Разрешено'), ('unaccepted', 'Не разрешено'), ('check', 'На проверке')], default='check', max_length=100),
),
]
from django.db import models
from django.db.models import TextChoices
class StatusChoices(TextChoices):
ACCEPTED = 'accepted', 'Разрешено'
UNACCEPTED = 'unaccepted', 'Не разрешено'
CHECK = 'check', 'На проверке'
class Article(models.Model):
# CharField = varchar
# title varchar(200) not null
title = models.CharField(
max_length=200,
null=False, # <null>
blank=False, # ''
verbose_name='Заголовок'
)
# accepted, check, unaccepted
status = models.CharField(
max_length=100,
choices=StatusChoices.choices,
default='check'
)
text = models.TextField(
max_length=3000,
null=False,
blank=False,
verbose_name='Текст'
)
author = models.CharField(
max_length=100,
null=False,
blank=False,
default='Unknown',
verbose_name='Автор'
)
created_at = models.DateTimeField(
auto_now_add=True,
verbose_name='Дата создания'
)
updated_at = models.DateTimeField(
auto_now=True,
verbose_name='Дата обновления'
)
class Meta:
verbose_name = 'статью'
verbose_name_plural = 'статьи'
def __str__(self):
return f'{self.author}: {self.title}'
{% extends 'base.html' %}
{% block title %}
<h1>Article checkout</h1>
{% endblock %}
{% block content %}
<h2>{{ article.title }}</h2>
<p>{{ article.text }}</p>
<h5>Status: {{ article.status }}</h5>
<h5>By: {{ article.author }}</h5>
<h4>Created: {{ article.created_at }}</h4>
<h4>Updated: {{ article.updated_at }}</h4>
<a href="{% url 'article_update' article.pk %}">Edit</a>
<a href="{% url 'delete_article' article.pk %}">Delete</a>
{% endblock %}
{% extends 'base.html' %}
{% load static %}
{% block title %}
<h1>Create Article</h1>
{% endblock %}
{% block content %}
<form action="/articles/add/" method="post">
{% include 'partial/article_form.html' with button_text='Create' %}
</form>
{% endblock %}
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.0.1/css/bootstrap.min.css"
integrity="sha512-Ez0cGzNzHR1tYAv56860NLspgUGuQw16GiOOp/I2LuTmpSK9xDXlgJz3XN4cnpXWDmkNBKXR/VDMTCnAaEooxA=="
crossorigin="anonymous" referrerpolicy="no-referrer"/>
<link rel="stylesheet" href="{% static 'css/styles.css' %}">
<title>Title</title>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container">
<a class="navbar-brand" href="{% url 'main-page' %}">Articles</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse flex-grow-0" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link active" aria-current="page" href="{% url 'articles-add' %}">
Create
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Features</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">Pricing</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="container">
{% block title %}{% endblock %}
{% block content %}{% endblock %}
</div>
{% block script %}{% endblock %}
</body>
</html>
\ No newline at end of file
{% extends 'base.html' %}
{% block title %}
<h1>Article delete</h1>
{% endblock %}
{% block content %}
<h1>Are you sure you want to delete article: {{ article.title }}?</h1>
<form action="{% url 'delete_article' article.pk %}" method="POST">
{% csrf_token %}
<p><input type="submit" value="Confirm"></p>
<p><a href="{% url 'articles-detail' article.pk %}">Cancel</a></p>
</form>
{% endblock %}
\ No newline at end of file
{% extends 'base.html' %}
{% load static %}
{% block content %}
<h1>Articles</h1>
<a href="{% url 'articles-add' %}" class="btn btn-primary">Создать</a>
{% for article in articles %}
<br>
<hr>
<br>
<h2>{{ article.title }}</h2>
<p>
<a href="{% url 'articles-detail' id=article.id %}">
Подробнее
</a>
</p>
<br>
<hr>
<br>
{% endfor %}
{% endblock %}
\ No newline at end of file
{% csrf_token %}
<!-- <div class="mb-3">
<label for="titleId" class="form-label">Title</label>
{% if errors.title %}
<p class="form-error">{{ errors.title }}</p>
<input type="text" name="title" class="form-control field-error" id="titleId" aria-describedby="title" value="{{ article.title }}">
{%else%}
<input type="text" name="title" class="form-control" id="titleId" aria-describedby="title" value="{{ article.title }}">
{%endif%}
</div>
<div class="mb-3">
<label for="statusId" class="form-label">Status</label>
<select name="status" id="statusId" class="form-select">
{% for choice in status_choices %}
{% if article.status == choice.0 %}
<option value="{{ choice.0 }}" selected>{{ choice.1 }}</option>
{% else %}
<option value="{{ choice.0 }}">{{ choice.1 }}</option>
{% endif %}
{% endfor %}
</select>
</div>
<div class="mb-3">
<label for="textId" class="form-label">Text</label>
{% if errors.text %}
<p class="form-error">{{ errors.text }}</p>
<textarea name="text" class="form-control field-error" id="textId" cols="30" rows="10">{{article.text}}</textarea>
{% else %}
<textarea name="text" class="form-control" id="textId" cols="30" rows="10">{{article.text}}</textarea>
{%endif%}
</div>
<div class="mb-3">
<label for="authorId" class="form-label">Author</label>
{% if errors.author %}
<p class="form-error">{{ errors.author }}</p>
<input type="text" name="author" class="form-control field-error" id="authorId" aria-describedby="author" value="{{article.author}}">
{%else%}
<input type="text" name="author" class="form-control" id="authorId" aria-describedby="author" value="{{article.author}}">
{%endif%}
</div> -->
{% for error in form.non_field_errors %}
<p class="form-error">{{error}}</p>
{%endfor%}
<p><label for="{{form.title.id_for_label}}">{{form.title.label}}</label></p>
{% for error in form.title.errors %}
<p class="form-error"> {{ error }} </p>
{% endfor %}
<p>{{ form.title }}</p>
<p><label for="{{form.author.id_for_label}}">{{form.author.label}}</label></p>
{% for error in form.author.errors %}
<p class="form-error"> {{ error }} </p>
{% endfor %}
<p>{{ form.author }}</p>
<p><label for="{{form.status.id_for_label}}">{{form.status.label}}</label></p>
{% for error in form.status.errors %}
<p class="form-error"> {{ error }} </p>
{% endfor %}
<p>{{ form.status }}</p>
<p><label for="{{form.text.id_for_label}}">{{form.text.label}}</label></p>
{% for error in form.text.errors %}
<p class="form-error"> {{ error }} </p>
{% endfor %}
<p>{{ form.text }}</p>
<button type="submit" class="btn btn-primary">{{ button_text }}</button>
\ No newline at end of file
{% extends 'base.html' %}
{% block title %}
<h1>Update Article</h1>
{% endblock %}
{% block content %}
<form action="{% url 'article_update' article.pk %}" method="post">
{% include 'partial/article_form.html' with button_text='Update' abc='123' %}
</form>
{% endblock %}
from django.test import TestCase
# Create your tests here.
from django.shortcuts import render, redirect, get_object_or_404
from django.urls import reverse
from django.views import View
from web.forms import ArticleForm
from web.models import Article, StatusChoices
def index_view(request):
return render(
request, 'index.html', context={
'articles': Article.objects.order_by('title'),
'reverse': reverse('articles-detail', kwargs={'id': 1})
}
)
# Class-based views
class ArticleCreateView(View):
def get(self, request, *args, **kwargs):
form = ArticleForm()
return render(
self.request,
'article_create.html',
context={
'status_choices': StatusChoices.choices,
'form': form
}
)
def post(self, request, *args, **kwargs):
errors = {}
data = request.POST
form = ArticleForm(data=data)
if form.is_valid():
article = Article.objects.create(
title=form.cleaned_data['title'],
status=form.cleaned_data['status'],
text=form.cleaned_data['text'],
author=form.cleaned_data['author'],
)
return redirect(redirect('articles-detail', id=article.id))
else:
return render(self.request, 'article_create.html', context={'form': form, 'status_choices': StatusChoices.choices})
# title = request.POST.get('title')
# if not title:
# errors['title'] = 'Title should not be empty!'
# elif len(title) > 200:
# errors['title'] = 'Title should be 200 symbols or less'
# author = request.POST.get('author')
# if not author:
# errors['author'] = 'Author should not be empty!'
# elif len(author) > 40:
# errors['author'] = 'Author should be 40 symbols or less'
# text = request.POST.get('text')
# if not text:
# errors['text'] = 'Text should not be empty!'
# elif len(text) > 3000:
# errors['text'] = 'Text should be 3000 symbols or less'
# status = request.POST.get('status')
# if not status:
# errors['status'] = 'Status should not be empty!'
# if len(errors) > 0:
# article_not_saved = Article(title=title, status=status, text=text, author=author)
# return render(self.request,
# 'article_create.html',
# context={
# 'status_choices': StatusChoices.choices,
# 'errors': errors,
# 'article': article_not_saved
# })
article = Article.objects.create(title=title, author=author, status=status, text=text)
return redirect('articles-detail', id=article.id)
# def article_create_view(request):
# if request.method == 'GET':
# return render(
# request,
# 'article_create.html',
# context={
# 'status_choices': StatusChoices.choices
# }
# )
#
# elif request.method == 'POST':
# data = request.POST
# article_data = {
# 'title': data.get('title'),
# 'text': data.get('text'),
# 'author': data.get('author'),
# 'status': data.get('status')
# }
#
# article = Article.objects.create(**article_data)
#
# return redirect('articles-detail', id=article.id)
# /articles/{id}
def article_detail_view(request, id: int):
article = get_object_or_404(Article, id=id)
return render(request, 'article.html', context={'article': article})
def article_update_view(request, id):
article = get_object_or_404(Article, pk=id)
if request.method == 'GET':
form = ArticleForm(initial={
'title': article.title,
'status': article.status,
'author': article.author,
'text': article.text
})
return render(request, 'update.html', context={'article': article, 'form': form, 'status_choices': StatusChoices.choices})
elif request.method == 'POST':
form = ArticleForm(data=request.POST)
if form.is_valid():
article.title = request.POST.get('title')
article.author = request.POST.get('author')
article.text = request.POST.get('text')
article.status = request.POST.get('status')
article.save()
return redirect('articles-detail', id=article.pk)
else:
return render(request, 'update.html', context={'article': article, 'form': form, 'status_choices': StatusChoices.choices}))
def delete_article(request, id):
article = get_object_or_404(Article, pk=id)
if request.method == 'GET':
return render(request, 'delete.html', context={'article': article})
elif request.method == 'POST':
article.delete()
return redirect('main-page')
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment