Commit 8efb80b4 authored by Давид Ли's avatar Давид Ли

lesson 70

parent 0edc3494
......@@ -19,6 +19,9 @@ class User(AbstractUser):
)
password = models.CharField(max_length=128, verbose_name='password', null=True)
def is_moderator(self):
return 'Moderators' in self.groups.values_list('name', flat=True)
# Pillow
# sudo apt-get install libjpeg-dev zlib1g-dev
......
from django.contrib import admin
# Register your models here.
from django.apps import AppConfig
class ApiConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'api'
from django.db import models
# Create your models here.
from rest_framework import serializers
from webapp import models
class _ArticleSerializer(serializers.Serializer):
id = serializers.IntegerField(read_only=True)
title = serializers.CharField(max_length=200, required=True)
text = serializers.CharField(max_length=3000, required=True)
author_id = serializers.IntegerField(write_only=True)
author = serializers.PrimaryKeyRelatedField(read_only=True)
created_at = serializers.DateTimeField(read_only=True)
updated_at = serializers.DateTimeField(read_only=True)
def create(self, validated_data):
return models.Article.objects.create(**validated_data)
def update(self, instance, validated_data):
for key, value in validated_data.items():
setattr(instance, key, value)
instance.save()
return instance
class ArticleSerializer(serializers.ModelSerializer):
class Meta:
model = models.Article
fields = ['id', 'title', 'text', 'author', 'created_at', 'updated_at']
import json
from django.views.generic import View
from rest_framework.views import APIView
from rest_framework.response import Response
from api import serializers
from webapp import models
class ArticleListView(APIView):
def get(self, request, *args, **kwargs):
articles = models.Article.objects.all()
serializer = serializers.ArticleSerializer(articles, many=True)
return Response(serializer.data, safe=False)
class ArticleCreateView(APIView):
def post(self, request, *args, **kwargs):
serializer = serializers.ArticleSerializer(data=json.loads(request.body))
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status=400)
......@@ -38,6 +38,9 @@ INSTALLED_APPS = [
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'api',
'webapp',
'accounts',
]
......@@ -143,5 +146,6 @@ MEDIA_ROOT = BASE_DIR / 'uploads'
MEDIA_URL = '/images/'
# localhost:1025/uploads/avatars/user_1.jpg
SESSION_COOKIE_AGE = 5 * 60
# DATE_INPUT_FORMATS = ('%d.%m.%Y',)
"""ap_12 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.contrib import admin
from django.urls import path, include
from django.conf.urls.static import static
from django.conf import settings
from api import views as api_views
from webapp import views
urlpatterns = [
path('admin/', admin.site.urls),
path('', views.IndexRedirectView.as_view(), name='redirect_to_index'),
path('articles/', include('webapp.urls')),
path('accounts/', include('accounts.urls')),
path('api/articles/', api_views.ArticleListView.as_view()),
path('api/articles/create', api_views.ArticleCreateView.as_view()),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
......@@ -3,6 +3,12 @@
{% block content %}
<h1>Article</h1>
{% for message in messages %}
<div class="alert alert-success">
{{ message }}
</div>
{% endfor %}
<h2>{{ article.title }}</h2>
<p>{{ article.text }}</p>
<p>By: {{ article.author }}</p>
......
......@@ -14,11 +14,18 @@
<p>Дата Рождения: {{ user_obj.profile.birth_date|date:'d.m.Y' }}</p>
<p>Почта: {{ user_obj.email }}</p>
{% if user_obj.is_moderator %}
<ul>
<li>Active: {{ user.is_active }}</li>
<li>Staff: {{ user.is_staff }}</li>
<li>Superuser: {{ user.is_superuser }}</li>
</ul>
{% endif %}
<a href="{% url 'user_update' %}" class="btn btn-warning mt-3">Обновить</a>
<a href="{% url 'change_password' %}" class="btn btn-primary mt-3">Сменить пароль</a>
<h2 class="text-center">Статьи</h2>
{{page_obj.has_other_pages}}
<h2 class="text-center mb-5">Статьи</h2>
{% include 'partial/article_list.html' with articles=page_obj.object_list is_paginated=page_obj.has_other_pages %}
{% endblock %}
\ No newline at end of file
......@@ -56,5 +56,10 @@
{% endblock %}
</div>
<script>
let a = 1
</script>
</body>
</html>
\ No newline at end of file
......@@ -2,6 +2,13 @@
{% block content %}
<div class="text-center">
<!-- {% for message in messages %}
<div class="alert alert-success">
{{ message }}
</div>
{% endfor %} -->
<h1>Articles</h1>
<p><a href="{% url 'articles_add' %}">Добавить</a></p>
......
......@@ -5,6 +5,7 @@ from webapp import views
urlpatterns = [
path('', views.IndexListView.as_view(), name='index'),
path('add', views.ArticleCreateView.as_view(), name='articles_add'),
path('echo', views.articles.json_echo_view),
path('<int:id>', views.ArticleDetailView.as_view(), name='articles_detail'),
path('<int:id>/update', views.ArticleUpdateView.as_view(), name='articles_update'),
path('<int:id>/delete', views.ArticleDeleteView.as_view(), name='articles_delete'),
......@@ -19,4 +20,20 @@ urlpatterns = [
views.CommentDeleteView.as_view(),
name='comments_delete',
),
# path('api/', views.articles.index_api_view, name='index_api_view'),
path('api/', views.articles.articles_create_api_view, name='articles_create_api_view'),
# path('', views.art.as_view(), name='articles_add'), # POST
# path('<int:id>', views.ArticleDetailView.as_view(), name='articles_detail'), # GET
# path('<int:id>', views.ArticleUpdateView.as_view(), name='articles_update'), # PUT PATCH
# path('<int:id>', views.ArticleDeleteView.as_view(), name='articles_delete'), # DELETE
]
# Safe URLs: list, detail
# Unsafe URLs: create, update, delete
# list GET /articles/
# create POST /articles/
# detail GET /articles/123
# update PUT/PATCH /articles/123
# delete DELETE /articles/123
from urllib.parse import urlencode
from django.http.response import HttpResponse as HttpResponse
from django.contrib import messages
from django.views import generic
from django.db.models import Q
......@@ -46,6 +47,21 @@ class IndexListView(generic.ListView):
if self.search_value:
context['query_params'] = urlencode({'search': self.search_value})
# DEBUG - Отладка
# INFO - Информационное
# SUCCESS - Успех
# WARNING - Предупреждение
# ERROR - Ошибка
messages.add_message(self.request, messages.SUCCESS, 'Вы молодец!')
# list comp
self.request.session['index:messages'] = [vars(m) for m in self.request._messages]
res = []
for m in self.request._messages:
res.append(vars(m)['message'])
return context
def get_queryset(self):
......
import json
from typing import Any
from django.http import HttpRequest
from django.http.response import HttpResponse as HttpResponse
from datetime import datetime as dt
from django.http import HttpRequest, HttpResponse, HttpResponseNotAllowed, JsonResponse
from django.shortcuts import get_object_or_404, redirect, render
from django.urls import reverse, reverse_lazy
from django.core import serializers
from django.views import generic
from django.views.decorators.csrf import ensure_csrf_cookie
from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin, UserPassesTestMixin
from django.core.exceptions import PermissionDenied
......@@ -19,10 +23,12 @@ class ArticleDetailView(PermissionRequiredMixin, generic.DetailView):
def get_context_data(self, **kwargs):
comments = self.object.comments.order_by('-created_at')
return super().get_context_data(
**kwargs,
comments=comments,
comments_form=CommentForm,
messages=self.request.session.get('index:messages', []),
)
......@@ -100,3 +106,43 @@ class ArticleDeleteView(generic.DeleteView):
model = Article
pk_url_kwarg = 'id'
success_url = reverse_lazy('index')
@ensure_csrf_cookie
def get_token_view(request, *args, **kwargs):
if request.method == 'GET':
return HttpResponse()
return HttpResponseNotAllowed('Only GET requests allowed')
def json_echo_view(request, *args, **kwargs):
answer = {
'time': dt.now().strftime('%d-%m-%Y %H:%M:%S'),
'method': request.method,
}
if request.body:
answer['content'] = json.loads(request.body)
return JsonResponse(answer)
def index_api_view(request, *args, **kwargs):
if request.method == 'GET':
articles = Article.objects.all()
serialized_articles = serializers.serialize('json', articles)
return HttpResponse(serialized_articles)
def articles_create_api_view(request, *args, **kwargs):
if request.method == 'POST':
if request.body:
article_data = json.loads(request.body)
article = Article.objects.create(**article_data)
return HttpResponse(serializers.serialize('json', [article]))
else:
return JsonResponse({'error': 'No data provided!'}, status_code=400)
Когда используют ветки:
1. 2 дефолтных ветки - develop (код на стадии разработки), master (код на проде)
2. Для выполнения задач
Пример задачи: Реализовать CRUD для статей
Что мы делаем: Создаем отдельную ветку и называем по такому принципу
dkasmgkasdgnadsgndlash
Далее: Задачу выполнили => заливаем в develop
gitlab: merge request
github: pull request
Django==3.2.23
djangorestframework==3.14.0
Pillow==10.0.0
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