Виды в виде классов(Class Based Views) и использование миксинов

👁 33 просмотров
1 Звезда2 Звезды3 Звезды4 Звезды5 Звезд (Пока оценок нет)
Загрузка...

Теория

В данном посте рассмотрим возможность обернуть методы вида в классы, иначе говоря в Class Based Views и воспользуемся миксинами, чтобы осуществить принцип DRY на уровне кода Python для Django.

В данном посте не будем добавлять в приложение новых фитч, а будем усовершенстововать код, который используется в файле blog/views.py.

Это усовершенствование преследует 2 цели:

  • расширить возможности функций-обработчиков видов заменив их классами;
  • уменьшить повторяемость.

Для расширения возможности видов в Django есть специальный класс Views в модуле django.views.generic, а уменьшение повторяемости можно достичь используя миксин в виде отдельного универсального класса для однотипных задач, которые имеют всего лишь разные значения.

Примечание. Mixin — это особый вид наследования в Python (и других объектно-ориентированных языках), и он начинает получать большую популярность в разработке Django / Web Application. Вы можете использовать Mixin, чтобы позволить классам на Python делиться методами между любым другим классом, который наследует от этого Mixin.

Использование наследуемых видов виде классов в дальнейшем нам потребуется, чтобы выполнять операции добавления и сохранения через формы в базу данных через POST — метод, учитывая, что за чтение данных из БД отвечает GET -метод. Без CBW мы использовали просто функции с методом GET.

В дополнении ко всему рассмотрим, как на уровне вида выдать ошибку 404, вместо стандартного Traceback Django.

Практика

Процесс перехода будем выполнять в несколько этапов, чтобы не пропустить промежуточные итоги усовершенствования кода.

Этап 1. Переход к CBV

На этом этапе заменим функции post_detail() и tag_detail() в blog/view.py на аналогичные по функциональности классы и поправим код в blog/urls.py.

Открываем файл blog/view.py и правим код. Сохраним все предыдущее состояние кода,для наглядности того, что поменяли

from django.shortcuts import render
from django.http import HttpResponse
from .models import Post, Tag
from django.views.generic import View
# Create your views here.
def posts_list(request):
    posts = Post.objects.all()
    return render(request, 'blog/index.html', context = {'posts' : posts})
    #return HttpResponse("<h1>Hello! Hello!</h1>")
    
class PostDetail(View):
    def get(self, request, slug):
        post = Post.objects.get(slug__iexact=slug)
        return render(request, 'blog/post_detail.html', context={"post" : post})
    
# def post_detail(request, slug):
#     post = Post.objects.get(slug__iexact = slug)
#     return render(request, 'blog/post_detail.html', context = {'post' : post})

def tags_list(request):
    tags = Tag.objects.all()
    return render(request, 'blog/tags_list.html', context={'tags': tags})

class TagDetail(View):
      def get(self, request, slug):
          tag = Tag.objects.get(slug__iexact = slug)
          return render(request, 'blog/tag_detail.html', context={'tag': tag})
          
# def tag_detail(request, slug):
#     tag = Tag.objects.get(slug__iexact = slug)
#     return render(request, 'blog/tag_detail.html', context={'tag': tag})

Что делает данный код? Мы подключаем модуль django.views.generic и импортируем оттуда класс View, далее создаем 2 класса, которых наследуем от класса View, для переопределения функции get() в них. Этот метод соответствует методу запроса GET, поэтому он должен возвращать рендер шаблона вида с значениям постов и тегов, чтобы показать в браузере пользователя, отправившего этот запрос.

Теперь открываем файл blog/urls.py и правим метод передачи обработки по шаблону запроса маршрутизации с post_detail и tag_detail на PostDetail.as_view() и TagDetail.as_view() соответственно

from django.urls import path
from .views import *

urlpatterns = [
    path('', posts_list, name='posts_list_url'),
    #path('post/<str:slug>', post_detail, name='post_detail_url'),
    path('post/<str:slug>', PostDetail.as_view(), name='post_detail_url'),
    path('tags/', tags_list, name='tags_list_url'),
    #path('tag/<str:slug>', tag_detail, name='tag_detail_url'),
    path('tag/<str:slug>', TagDetail.as_view(), name='tag_detail_url'),
]

Перезапускаем и убеждаемся, что все запускается ровно также, как и при старом коде.

Этап 2. Генерация страницы 404

Открываем файл blog/views.py и меняем содержимое на такое

from django.shortcuts import render, get_object_or_404
from django.http import HttpResponse
from .models import Post, Tag
from django.views.generic import View
# Create your views here.
def posts_list(request):
    posts = Post.objects.all()
    return render(request, 'blog/index.html', context = {'posts' : posts})
    #return HttpResponse("<h1>Hello! Hello!</h1>")
    
class PostDetail(View):
    def get(self, request, slug):
        #post = Post.objects.get(slug__iexact=slug)
        post = get_object_or_404(Post, slug__iexact=slug)
        #return render(request, 'blog/post_detail.html', context={"post" : post})
        return render(request, 'blog/post_detail.html', context={Post.__name__.lower(): post})
    
# def post_detail(request, slug):
#     post = Post.objects.get(slug__iexact = slug)
#     return render(request, 'blog/post_detail.html', context = {'post' : post})

def tags_list(request):
    tags = Tag.objects.all()
    return render(request, 'blog/tags_list.html', context={'tags': tags})

class TagDetail(View):
      def get(self, request, slug):
          #tag = Tag.objects.get(slug__iexact = slug)
          tag = get_object_or_404(Tag, slug__iexact=slug)
          #return render(request, 'blog/tag_detail.html', context={'tag': tag})
          return render(request, 'blog/tag_detail.html', context={Tag.__name__.lower(): tag})
      
# def tag_detail(request, slug):
#     tag = Tag.objects.get(slug__iexact = slug)
#     return render(request, 'blog/tag_detail.html', context={'tag': tag})

В общем, в данном файле мы все запросы к БД выполняем через функцию get_object-or_404(…), который внутри себя реализует запрос к БД и если ничего не найдено, то выдает страницу 404 вместо Traceback, который не понятен бывалому пользователю сайта

Генерация ошибки 404 для несуществующей страницы Django
Генерация ошибки 404 для несуществующей страницы Django

Конструкция Tag.__name__.lower() возвращает название класса(в данном случае название модели) с заглавной буквы, но нам нужны только строчные буквы и поэтому используем функцию lower() и далее передаем его в виде названием параметра словаря контекста. Это нам пригодится, что на следующем этапе определить для этих классов общий миксин.

Этап 3. Создание Миксина

Теперь создадим еще один файл blog/utils.py, в котором определим наш миксин в виде универсального класса для уменьшения кода, который будет унаследован классами с переопределенными свойствами

from django.shortcuts import render, get_object_or_404
from django.views.generic import View
from .models import *

class ObjecDetailMixin(View):
    model = None
    template = None
    
    def get(self, request, slug):
        obj = get_object_or_404(self.model, slug__iexact=slug)
        return render(request, self.template, context={self.model.__name__.lower(): obj})
        

В данном классе мы определили 2 свойства:

  • model — класс модели;
  • template — шаблон модели.

Как мы видим, данный класс-миксин не содержит в себе каких-то индивидуальных параметров, которые бы его ограничивали в использовании. Он универсален для вывода и поста и для тега и это для нас может разыграть отличное условие, чтобы соответствовать принципу DRY в коде Python/Django.

Теперь открываем файл blog/views.py  перезаписываем вьюшки с наследованием нашего миксина. Старый код закоментирован, чтобы лучше можно было понять шаги и изменение кода

from django.shortcuts import render, get_object_or_404
from django.http import HttpResponse
from .models import Post, Tag
from django.views.generic import View
from .utils import ObjecDetailMixin

# Create your views here.
def posts_list(request):
    posts = Post.objects.all()
    return render(request, 'blog/index.html', context = {'posts' : posts})
    #return HttpResponse("<h1>Hello! Hello!</h1>")

class PostDetail(ObjecDetailMixin, View):
        model = Post
        template = 'blog/post_detail.html'
'''   
class PostDetail(View):
    def get(self, request, slug):
        #post = Post.objects.get(slug__iexact=slug)
        post = get_object_or_404(Post, slug__iexact=slug)
        #return render(request, 'blog/post_detail.html', context={"post" : post})
        return render(request, 'blog/post_detail.html', context={Post.__name__.lower(): post})
''' 
      
# def post_detail(request, slug):
#     post = Post.objects.get(slug__iexact = slug)
#     return render(request, 'blog/post_detail.html', context = {'post' : post})

def tags_list(request):
    tags = Tag.objects.all()
    return render(request, 'blog/tags_list.html', context={'tags': tags})

class TagDetail(ObjecDetailMixin, View):
        model = Tag
        template = 'blog/tag_detail.html'
        
'''
class TagDetail(View):
      def get(self, request, slug):
          #tag = Tag.objects.get(slug__iexact = slug)
          tag = get_object_or_404(Tag, slug__iexact=slug)
          #return render(request, 'blog/tag_detail.html', context={'tag': tag})
          return render(request, 'blog/tag_detail.html', context={Tag.__name__.lower(): tag})
'''
         
# def tag_detail(request, slug):
#     tag = Tag.objects.get(slug__iexact = slug)
#     return render(request, 'blog/tag_detail.html', context={'tag': tag})

Перезапускаем сервер и убеждаемся, что все работает также, как и прежде.

Облако тегов через связь ManyToMany и принцип DRY в Django

👁 35 просмотров
1 Звезда2 Звезды3 Звезды4 Звезды5 Звезд (Пока оценок нет)
Загрузка...

Теория

Настало время добавить к постам tags(теги), которые бы сгруппировали наши посты по определенным тематикам. Плюс ко всему сделаем, чтобы все связанные посты могли выходить списком при нажатии на тег и чтобы все теги тоже выходили списком при нажатии на ссылку.

Т.е., для этого нам понадобиться добавить еще одну таблицу в blog/models.py и выполнить еще раз процесс миграции, чтобы изменения локальных моделей обновились в базе данных.

Практика

Файл models.py

Откроем blog/models.py и добавим новую таблицу Tag . Выделенные строки соответствуют местам изменения кода

from django.db import models
from django.shortcuts import reverse

# Create your models here.
class Post(models.Model):
    title = models.CharField(max_length=150, db_index = True)
    slug = models.SlugField(max_length=150, unique = True)
    body = models.TextField(blank=True, db_index = True)
    date_pub = models.DateTimeField(auto_now_add = True)
    tags = models.ManyToManyField('Tag', blank=True, related_name = 'posts')
    
    def get_absolute_url(self):
        return reverse('post_detail_url', kwargs={'slug': self.slug})
    
    def __str__(self):
        return '{}'.format(self.title)

class Tag(models.Model):
    title = models.CharField(max_length=50)
    slug = models.SlugField(max_length=50, unique = True)
    
    def get_absolute_url(self):
        return reverse('tag_detail_url', kwargs = {'slug': self.slug})
    def __str__(self):
        return '{}'.format(self.title)
        

После обновления файла моделей нужно их отразить в  реальной БД, поэтому выполняем команды миграции в консоли

python3 manage.py makemigrations
python3 manage.py migrate

 

После выполнения миграции можно поэксперементировать в консоли. Для этого заходим в shell python, через команду

python3 manage.py shell

И потренеруемся с добавлением и связкой тегов к постам

>>> from blog.models import *
>>> t = Tag.objects.create(title='Django', slug='django')
>>> t
<Tag: Django>
>>> Post.objects.values()
<QuerySet [{'id': 1, 'title': 'New post title 1', 'slug': 'new-post-1', 'body': 'Body text 1 ...', 'date_pub': datetime.datetime(2018, 11, 11, 18, 56, 18, 127958, tzinfo=<UTC>)}, {'id': 2, 'title': 'New post title 2', 'slug': 'new-post-2', 'body': 'Body text 2 ...', 'date_pub': datetime.datetime(2018, 11, 11, 19, 8, 32, 411534, tzinfo=<UTC>)}, {'id': 3, 'title': 'New post title 3', 'slug': 'new-post-3', 'body': 'Body text 3 ...', 'date_pub': datetime.datetime(2018, 11, 11, 19, 24, 47, 409418, tzinfo=<UTC>)}, {'id': 4, 'title': 'New post title 4', 'slug': 'new-post-4', 'body': 'Body text 4 ...', 'date_pub': datetime.datetime(2018, 11, 11, 19, 25, 15, 533403, tzinfo=<UTC>)}, {'id': 5, 'title': 'New post title 5', 'slug': 'new-post-5', 'body': 'Body text 5 ...', 'date_pub': datetime.datetime(2018, 11, 11, 19, 25, 30, 460405, tzinfo=<UTC>)}, {'id': 6, 'title': 'New post title 6', 'slug': 'new-post-6', 'body': 'Body text 6 ...', 'date_pub': datetime.datetime(2018, 11, 11, 19, 25, 47, 309093, tzinfo=<UTC>)}, {'id': 7, 'title': 'New post title 7', 'slug': 'new-post-7', 'body': 'Body text 7 ...', 'date_pub': datetime.datetime(2018, 11, 11, 19, 26, 1, 493016, tzinfo=<UTC>)}]>
>>> p = Post.objects.get(slug='new-post-1')
>>> p.title
'New post title 1'
>>> p.title = 'Post width tag'
>>> p.save()
>>> p.tags.add(t)
>>> p.tags.all()
<QuerySet [<Tag: Django>]>

Опишем некоторые команды

  • from blog.models import * — импортируем все модели;
  • t = Tag.objects.create(title=’Django’, slug=’django’) — создаем новый эксземпляр(для таблицы это будет строка) сущности
  • Post.objects.values() — выводим все значения в модели Post;
  • p = Post.objects.get(slug=’new-post-1′) — ищем посты по соответствию;
  • p.title — выводим заголовок поста;
  • p.title = ‘Post width tag’ — задаем новый заголовок для поста;
  • p.save() — сохраняем экземпляр с новым изменениями и перезаписываем в БД, как строку;
  • p.tags.add(t) — добавляем новый экземпляр тега к посту;
  • p.tags.all() — выводим все теги экземпляра поста.

 

Файл urls.py

Открываем файл blog/urls.py и задаем 2 дополнительных маршрутизации для вывода постов по тегу и списка всех тегов и плюс к этому добавим к ним обработчики для видов

from django.urls import path
from .views import *

urlpatterns = [
    path('', posts_list, name='posts_list_url'),
    path('post/<str:slug>', post_detail, name='post_detail_url'),
    path('tags/', tags_list, name='tags_list_url'),
    path('tag/<str:slug>', tag_detail, name='tag_detail_url'),
]

В данном случае, мы добавили 2 шаблона URL

  • tags — выведет все существующие теги в базе;
  • tag/<str:slug> —  выведет все посты, прикрепленные к этому тегу.

 

Файл views.py

Открываем файл blog/views.py и пишем обработчики для шаблонов ссылок маршрутизации, которые выведут в шаблоны вида список тегов и список связанных постов

from django.shortcuts import render
from django.http import HttpResponse
from .models import Post, Tag
# Create your views here.
def posts_list(request):
    posts = Post.objects.all()
    return render(request, 'blog/index.html', context = {'posts' : posts})
    #return HttpResponse("<h1>Hello! Hello!</h1>")
    
def post_detail(request, slug):
    post = Post.objects.get(slug__iexact = slug)
    return render(request, 'blog/post_detail.html', context = {'post' : post})

def tags_list(request):
    tags = Tag.objects.all()
    return render(request, 'blog/tags_list.html', context={'tags': tags})

def tag_detail(request, slug):
    tag = Tag.objects.get(slug__iexact = slug)
    return render(request, 'blog/tag_detail.html', context={'tag': tag})
    

Как мы видим, нам потребуется создать еще 2 шаблона вида

  • tags_list.html — шаблон страницы списка всех тегов;
  • tag_detail.html — шаблон страницы всех постов с тем или иным конкретным тегом.

 

Принцип DRY в шаблонах Django

Как было в предыдущей части упомянуто, нам нужно создать еще 2 шаблона вида: tags_list.html и tag_detail.html.

Тут важно учитывать, что вывод постов по ссылке mysite.com/blog и по ссылке mysite.com/blog/tag/tagname идентичны и нам нужно для этого создать карточку для поста, чтобы не копипастить один и тот же код и для этого в шаблонах Django есть возможность подключать куски кода html друг в друга и это соответствует принципу DRY.

Don’t repeat yourselfDRY (рус. не повторяйся) — это принцип разработки программного обеспечения, нацеленный на снижение повторения информации различного рода, особенно в системах со множеством слоёв абстрагирования. Принцип DRY формулируется как: «Каждая часть знания должна иметь единственное, непротиворечивое и авторитетное представление в рамках системы».

Т.е., помимо шаблонов tags_list.html и tag_detail.html мы еще создадим папку blog/templates/blog/includes, в которой будет карточка поста post_card.html, который будет подключен к файлу blog/templates/blog/index.html и к файлу blog/templates/blog/tag_detail.html

Файл blog/templates/blog/index.html

{% extends 'blog/base_blog.html'%}
{% block title %}
	Site Blog
{% endblock %}
{% block content %}
	<div>
		<div class="grid-x">
		    {% for post in posts %}
				{% include 'blog/includes/post_card.html'%}
			{% endfor %}
		</div>
	</div>
{% endblock %}

Файл blog/templates/blog/tags_list.html

{% extends 'blog/base_blog.html'%}
{% block title %}
	Site Blog - Tags list
{% endblock %}
{% block content %}
	<div>
		<div class="grid-x">
		    {% for tag in tags %}
			    <div class="cell small-12 medium-3 large-3">
				      <div class="card">
					        <div class="card-section">
					        	<h4>
						        	<a href="{{ tag.get_absolute_url }}" class="button">
						        		{{ tag.title }}
						        	</a>
					        	</h4>
					        </div>
				      </div>
			    </div>
			{% endfor %}
		</div>
	</div>
{% endblock %}

Файл blog/templates/blog/tag_detail.html

{% extends 'blog/base_blog.html'%}
{% block title %}
	Site Blog - Tag detail
{% endblock %}
{% block content %}
	<div>
		<h3>Posts with tag <b>{{tag.title|title}}</b>:</h3>
		<br/>
		<div class="grid-x">
		    {% for post in tag.posts.all %}
				{% include 'blog/includes/post_card.html'%}
			{% endfor %}
		</div>
	</div>
{% endblock %}

Файл blog/templates/blog/includes/post_card.html

 <div class="cell small-12 medium-3 large-3">
    <div class="card">
       <img src="https://foundation.zurb.com/sites/docs/assets/img/generic/rectangle-1.jpg">
       <div class="card-section">
       	<h4>{{ post.title }}</h4>
         	<p>{{ post.body | truncatewords:15 }}</p>
		<!-- <a href="{% url 'post_detail_url' slug=post.slug %}" class="button">Learn More</a> -->
		<a href="{{ post.get_absolute_url }}" class="button">Learn More</a>
		<h6>{{ post.date_pub }}</h6>
       </div>
       <div>
           Tags: 
	    {% for tag in post.tags.all %}
        	<a href="{{ tag.get_absolute_url }}">
        		{{ tag.title }}
        	</a>
        {% empty %}
            none
		{% endfor %}
       </div>
    </div>
 </div>

В карте поста важно отметить обновления, связанные с выводом тегов к посту в футере карточки.

В итоге карточки постов должны получиться, как на скриншотах внизу

Карточки постов с тегом и без тега
Карточки постов с тегом и без тега

Список тегов должно получиться, как внизу

Страница списка тегов. Пока один тег
Страница списка тегов (пока в базе один тег)

Список постов по определенному тегу

Список постов по определенному тегу
Список постов по определенному тегу

 

Создание модели ORM, вывод из базы данных в шаблоны Django

👁 84 просмотров
1 Звезда2 Звезды3 Звезды4 Звезды5 Звезд (Пока оценок нет)
Загрузка...

Теория

В данном посте будем работать с базой данных в Django и в частности, рассмотрим такой механизм работы с БД, как ORM.

ORM(Object Relation Mapping) — Объектно ориентированное наложение базы данных. Т.е., это означает, что мы создаем в базе данных таблицы и связи на основе классов и их свойств, которых мы определяем в файле models.py в приложении Django.

Примечание. Процесс экспорта из models.py в базу данных в Django называется миграцией БД.

Плюс ORM  в том, что вам не обязательно вникать в суть того, какие именно БД вы будете использовать. Достаточно установить в систему сервер БД и указать в файлах настройки, что мы будем использовать эту БД, а все ньюансы CRUD с базой данных возьмет на себя общий интерфейс ORM.

В дальнейшем, чтобы, делать выборку или чтобы хранить, редактировать или удалить данные мы будем использовать только функции ORM.

Каждый объект класса в models.py — это отдельная таблица в БД, который, после миграции используется в файле views.py для вывода в шаблон приложения.

 

Практика

Файл models.py

Сначала нам нужно создать таблицу постов с полями, для этого нужно открыть файл blog/models.py и создать там класс таблицы постов с полями

from django.db import models
from django.shortcuts import reverse

# Create your models here.
class Post(models.Model):
    title = models.CharField(max_length=150, db_index = True)
    slug = models.SlugField(max_length=150, unique = True)
    body = models.TextField(blank=True, db_index = True)
    date_pub = models.DateTimeField(auto_now_add = True)
    
    def get_absolute_url(self):
        return reverse('post_detail_url', kwargs={'slug': self.slug})
    
    def __str__(self):
        return '{}'.format(self.title)
        

Класс Post имеет 6 членов. 4 свойства и 2 — метода:

  • title — поле заголовка;
  • slug — поле URL;
  • body — поле текста;
  • date_pub — поле даты;
  • get_absolute_url() — абсолютный URL на текущий пост;
  • __str__() — переопределение объекта на вывод нужного значения.

Значения полям устанавливаются при помощи объекта models, который реализует при помощи методов функционал ORM. В данном примере используются 4 видов данных:

  • models.CharField(…) — значение символьного поля;
  • models.SlugField(…) — значение поля постоянной ссылки;
  • models.TextField(…) — значение многострочного поля;
  • models.DateTimeField(…) — значение поля даты и времени.

Когда модель таблицы в виде класса готова, то самое время наложить эту модель на реальную БД и этим занимается процесс миграции Django. Миграция состоит из 2-х шагов операций и команд:

  • makemigrations — который отвечает за создание новых миграций на основе изменений, внесенных вами в ваши модели. После этой команды в корневой папке приложения, где есть изменения в моделях появится папка migrations, в которой будут все нужные файлы для дальнейшего их отражения в БД;
  • migrate — который несет ответственность за применение и неприменение миграций.

В консоли это выглядит так

python3 manage.py makemigrations
python3 manage.py migrate

 

После миграций можно эксперементировать в  консоли с работой с созданной БД. Для входа в консоль shell можно выполнить команду

python3 manage.py shell

После данной команды консоль будет принимать уже команды python через >>> в пределах текущего проекта.

Некоторые команды работы с БД:

  • p=Post(title=’New post title 1′, slug = ‘new-post-1’, body = ‘Body text 1 …’) — заполнение нового экземпляра(строки) таблицы;
  • p.save() — сохранение экземпляра(строки) таблицы;
  • p.id — вывод какой-либо колонки(ID, к примеру);
  • print(p) — выведет то, что мы переопределили в методе __str__(self);
  • dir(p) — вывод всех свойств и методов, доступных у экземпляра строки;
  • p1=Post.objects.create(title=’New post title 2′, slug = ‘new-post-2’, body = ‘Body text 2 …’) — заполнение нового экземпляра(строки) таблицы через метода объекта;
  • Post.objects.all() — получение списка всех экземпляров(строк) в таблице;
  • Post.objects.get(slug__iexact = ‘new-post-1’) — получение какого-то экземпляра(строки) через регистронезависимую выборку;
  • Post.objects.filter(slug__contains = ‘new’) — выборка через фильтр.

Пример работы в консоли

>>> from blog.models import Post
>>> p=Post(title='New post title 1', slug = 'new-post-1', body = 'Body text 1 ...')
>>> p
<Post: New post title 1>
>>> p.id
>>> p.save()
>>> p.id
1
>>> p.id
1
>>> print(p)
New post title 1
>>> p
<Post: New post title 1>
>>> dir(p)
['DoesNotExist', 'MultipleObjectsReturned', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getstate__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_check_column_name_clashes', '_check_field_name_clashes', '_check_fields', '_check_id_field', '_check_index_together', '_check_indexes', '_check_local_fields', '_check_long_column_names', '_check_m2m_through_same_relationship', '_check_managers', '_check_model', '_check_model_name_db_lookup_clashes', '_check_ordering', '_check_property_name_related_field_accessor_clashes', '_check_single_primary_key', '_check_swappable', '_check_unique_together', '_do_insert', '_do_update', '_get_FIELD_display', '_get_next_or_previous_by_FIELD', '_get_next_or_previous_in_order', '_get_pk_val', '_get_unique_checks', '_meta', '_perform_date_checks', '_perform_unique_checks', '_save_parents', '_save_table', '_set_pk_val', '_state', 'body', 'check', 'clean', 'clean_fields', 'date_error_message', 'date_pub', 'delete', 'from_db', 'full_clean', 'get_deferred_fields', 'get_next_by_date_pub', 'get_previous_by_date_pub', 'id', 'objects', 'pk', 'prepare_database_save', 'refresh_from_db', 'save', 'save_base', 'serializable_value', 'slug', 'title', 'unique_error_message', 'validate_unique']
>>> p1=Post.objects.create(title='New post title 2', slug = 'new-post-2', body = 'Body text 2 ...')
>>> p1
<Post: New post title 2>

>>> Post.objects.all()
<QuerySet [<Post: New post title 1>, <Post: New post title 2>]>

>>> p1=Post.objects.create(title='New post title 3', slug = 'new-post-3', body = 'Body text 3 ...')
>>> p1=Post.objects.create(title='New post title 4', slug = 'new-post-4', body = 'Body text 4 ...')
>>> p1=Post.objects.create(title='New post title 5', slug = 'new-post-5', body = 'Body text 5 ...')
>>> p1=Post.objects.create(title='New post title 6', slug = 'new-post-6', body = 'Body text 6 ...')
>>> p1=Post.objects.create(title='New post title 7', slug = 'new-post-7', body = 'Body text 7 ...')

>>> Post.objects.get(slug__iexact = 'new-post-1')
<Post: New post title 1>
>>> Post.objects.filter(slug__contains = 'new')
<QuerySet [<Post: New post title 1>, <Post: New post title 2>, <Post: New post title 3>, <Post: New post title 4>, <Post: New post title 5>, <Post: New post title 6>, <Post: New post title 7>]>
>>>

 

Файл views.py

Файл views.py является связующим звеном между моделью и шаблоном. Открываем файл blog/views.py  редактируем. Обновления в файле выделены

from django.shortcuts import render
from django.http import HttpResponse
from .models import Post
# Create your views here.
def posts_list(request):
    posts = Post.objects.all()
    return render(request, 'blog/index.html', context = {'posts' : posts})
    #return HttpResponse("<h1>Hello! Hello!</h1>")
    
def post_detail(request, slug):
    post = Post.objects.get(slug__iexact = slug)
    return render(request, 'blog/post_detail.html', context = {'post' : post})

До этого мы грузили все посты из списка, теперь грузим из реального БД в виде posts_list(), а видом отдельного активного поста будет заниматься метод post_detail().

Файл urls.py

Открываем blog/urls.py существующему списку URL добавляем новы шаблон, по которому будет открываться отдельный пост. причем, в данном случае, в параметре slug будет хранить URL — поста. Этот параметр указан в угловых скобках, это означает на то, что оно будет переменной и попадется вторым параметром в метод вида, а в виде уже по этому уникальному slug будет сделана выборка из БД, данные которого потом через контекст передачи данных попадет в шаблон открытого поста

from django.urls import path
from .views import *

urlpatterns = [
    path('', posts_list, name='posts_list_url'),
    path('<str:slug>', post_detail, name='post_detail_url'),
]

Файлы шаблонов

Открываем blog/templates/blog/index.html переписываем

{% extends 'blog/base_blog.html'%}
{% block title %}
	Site Blog
{% endblock %}
{% block content %}
	<div>
		<div class="grid-x">
		    {% for post in posts %}
			    <div class="cell small-12 medium-3 large-3">
				      <div class="card">
					        <img src="https://foundation.zurb.com/sites/docs/assets/img/generic/rectangle-1.jpg">
					        <div class="card-section">
					        	<h4>{{ post.title }}</h4>
					          	<p>{{ post.body | truncatewords:15 }}</p>
								<!-- <a href="{% url 'post_detail_url' slug=post.slug %}" class="button">Learn More</a> -->
								<a href="{{ post.get_absolute_url }}" class="button">Learn More</a>
								<h6>{{ post.date_pub }}</h6>
					        </div>
				      </div>
			    </div>
			{% endfor %}
		</div>
	</div>
{% endblock %}

Создаем новый файл blog/templates/blog/post_detail.html и вставляем

{% extends 'blog/base_blog.html'%}
{% block title %}
	Site Blog
{% endblock %}
{% block content %}
	<div>
		<div class="grid-x">
		    <div class="cell medium-1 large-2">
		    <div class="cell small-12 medium-5 large-4">
			      <div class="card">
				        <img src="https://foundation.zurb.com/sites/docs/assets/img/generic/rectangle-1.jpg">
				        <div class="card-section">
				        	<h4>{{ post.title }} <b>{{ post.date_pub }}</b></h4>
				          	<p>{{ post.body}}</p>
				        </div>
			      </div>
		    </div>
		    <div class="cell medium-1 large-2">
		</div>
	</div>
{% endblock %}

Маршрутизация и генерация ответа пользователю в Django

👁 33 просмотров
1 Звезда2 Звезды3 Звезды4 Звезды5 Звезд (Пока оценок нет)
Загрузка...

Теория

В данном посте рассмотрим, как Django работает с URL — адресами и как подключаются приложения к маршрутизации для обработки входящих запросов их выдача.

В проекте Django нужно акцентировать внимание на нескольких файлах:

  • urls.py — файл маршрутизации;
  • views.py — файл контроллера и выдачи рендера страница;
  • models.py — файл работы с базой данных на основе ORM.

Они, как правило, должны быть в каждом приложении, за счет чего реализуется обмен и обработка данными по принципу MTV. Каждый из этих файлов выполняет свою роль в обработке по принципу MTV, который наследует свою идею от MVC.

Концептуальный принцип MVC реализован из таких частей:

  • M — доступ к данным, обрабатывается слоем работы с базой данных.
  • V — эта часть, которая определяет какие данные получать и как их отображать, обрабатывается представлениями и шаблонами.
  • C — эта часть, которая выбирает представление в зависимости от пользовательского ввода, обрабатывается самой средой разработки, следуя созданной вами схемой URL, и вызывает соответствующую функцию Python для указанного URL.

Но в Django это работает чуть иначе. Так как «C» обрабатывается средой разработки и всё интересное в Django происходит в моделях, шаблонах и представлениях, на Django ссылаются как на MTV-ориентированную среду разработки. В MTV-подходе к разработке:

  • M — определено для «Модели» (Model), слоя доступа к данным. Этот слой знает всё о данных: как получить к ним доступ, как проверить их, как с ними работать и как данные связаны между собой.
  • T — определено для «Шаблона» (Template), слоя представления данных. Этот слой принимает решения относительно представления данных: как и что должно отображаться на странице или в другом типе документа.
  • V — определено для «Представления» (View), слоя бизнес-логики. Этот слой содержит логику, как получать доступ к моделям и применять соответствующий шаблон. Вы можете рассматривать его как мост между моделями и шаблонами.

В общем, ниже представлена схема того, как Django представляет для себя MVC в виде MTV

Шаблон VMC в понимании Django в виде MTV
Шаблон VMC в понимании Django в виде MTV

 

Практика

В прошлом посте мы обсудили тему создания проекта Django и приложения к проекту. Теперь давайте сделаем следующее:

  • интегрируем приложение с проектом;
  • сделаем маршрутизация на созданное приложение;
  • добавим вид.

На данный момент у нас есть такая структура

[myproject]/
├── [myproject]/
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── [blog]/
│   ├── __init__.py
│   ├── admin.py
│   ├── apps.py
│   ├── moddels.py 
│   ├── views.py 
│   └── tests.py 
└── manage.py

По умолчанию в проекте создается главное приложение с тем же именем, что и у проекта. Данное приложение  содержит файл конфигурации settings.py и файл маршрутизации urls.py, которые нам будут необходимы в данном разборе.

Открываем файл settings.py и добавляем приложение blog к проекту, дописав значение для INSTALLED_APPS

...
INSTALLED_APPS = [
    ...,
    'blog',
]
...

Далее открываем файл маршрутизации urls.py и добавляем шаблон URL для нашего приложения, добавиви параметр для переменной urlpatterns

...
from django.path import include

...
urlpatterns = [
    path('admin/', admin.site.urls),
    path('blog/', include('blog.urls')),
]
...

Строка path(‘blog/’, include(‘blog.urls’)) означает, что мы задаем для нашего приложения новый маршрут, по которому оно будет доступно и записываем его в виде шаблона URL. Это означает, что если после домена мы введем www.mysite.com/blog/, то запустится наше приложение и путь запуска указано вторым параметром в функции path(url_pattern, function_or_app_path). Путь к приложению указывается через функцию include() из стандартного модуля django.path, который тоже нужно включить.

Значение ‘blog.urls’ говорит, что перенаправлять нужно на маршрутизатор приложения, т.е. замысел в том, чтобы из маршрутизатора главного приложения мы перешли в маршрутизатор того приложения, которое соответствует шаблону адреса URL, которую мы набираем в строке браузера после домена.

Примечание. В функции path(…) кода выше представлены только 2 обязательные значения, но у нее есть еще 2 необязательные(в общем 4), которыми мы воспользуемся чуть позже.

Теперь идем в папку нашего приложения blog и создаем файл urls.py(по умолчанию Django его не добавляет). Пишем в нем такой код и сохраняем

from django.path import include
from .views import posts_list

urlpatterns = [
    path('', posts_list),
]

Теперь открываем файл views.py нашего проекта и добавляем туда новую функцию posts_list

from django.shortcuts import render
from django.http import HttpResponse
# Create your views here.
def posts_list(request):
    
    return HttpResponse("<h1>Hello! Hello!</h1>")

Что мы сделали выше? Во первых, если в предыдущем myproject/urls.py в функции path(…) вторым параметром мы указывали на приложение blog, то в blog/urls.py мы вторым параметром этой функции указываем функцию, которую грузим из вида этого приложения blog/views.py и если теперь перезапустить сервер и посмотреть по адресу 127.0.0.1:5000/blog, то мы увидим

Результат вывода приложения blog
Результат вывода приложения blog

Установка Django и создание первого приложения

👁 41 просмотров
1 Звезда2 Звезды3 Звезды4 Звезды5 Звезд (Пока оценок нет)
Загрузка...

Создаем новую виртуальную среду

virtualenv venv

Активируем созданную виртуальную среду

cd venv
source bin/activate

Устанавливаем Django

pip3 install django

Создаем новый проект Django

django-admin startproject myblog

Выполняем миграцию баз данных в SQLite(он по умолчанию в Django)

cd myblog
python3 manage.py migrate

Запуск созданного проекта

python3 manage.py runserver 5000

Переходим по адресу 127.0.0.1:5000 и удостоверяемся, что проект запускается удачно

Создаем новое приложение в составе проекта Django

python3 manage.py startapp blog

Данное приложение пока нигде не задействовано. Работа с ним будет произведена в следующих шагах.

Резюме

В данном посте мы создали виртуальную среду Python, установили в эту среду фреймворк Django, создали проект Django и создали приложение для проекта Django.

Примечание 1. По умолчанию проект Django содержит одно единственное приложение с тем же названием, что и название проекта.

Примечание 2. Приложений в составе проекта Django может быть сколько угодно и они между собой слабо связаны.

Примечание 3. Связь между приложениями и обработка данных выполняются по принципу шаблона проектирования MVC/MTV.

Примечание 4. По умолчанию Django мигрирует данные в БД SQLite, поэтому, если есть необходимость в других видах БД, к примеру в PostgreSQL, то можно посмотреть этот пост.

Примечание 5. По умолчанию, команда

python3 manage.py runserver 5000

запустит сервер WSGI на хосте 12.0.0.1 и на порту 5000. Если Django запускается на VPS/VDS, то чтобы был доступ через внешний IP нужно явно указать IP, как 0:5000 или 0.0.0.0:5000. Установку домена и прочие настройки можно узнать из этого поста.

 

 

Деплой проекта Django в продакшн с Nginx + Gunicorn + Supervisor

👁 158 просмотров
1 Звезда2 Звезды3 Звезды4 Звезды5 Звезд (Пока оценок нет)
Загрузка...

В данном посте рассмотрим один из современных вариантов деплоя готового проекта Django в готовый режим работы. В посте будет рассмотрены моменты настройки и интеграции с Django таких инструментов, как:

  • Nginx — WEB-сервер;
  • Gunicorn — HTTP-сервер Python WSGI;
  • Supervisor — менеджер процессов.

Исходные данные

Для использования данного поста требуются следующие исходные данные по ПО:

  • готовый удаленный сервер Linux в виде VPS/VDS с выделенным IP;
  • установленный и настроенный Python 3 c виртуальными средами и разрабатываемым проектом на Django;

Исходные данные по неймингу:

  • /home/myprojectenv/ — абсолютный путь к папке виртуальной среды;
  • /home/myprojectenv/myproject/ — абсолютный путь к папке проекта на Django;
  • (myprojectenv)user@host: /myprojectenv/ —  вид строки запроса в консоли под активной виртуальной средой Python;
  • 11.22.33.44IP нашего удаленного сервера VDS/VPS;
  • 8000 — порт, на котором будет подвешен наш проект.

 

Установка и настройка Nginx и Gunicorn

Для начала нужно сделать апгрейд

sudo apt-get update
sudo apt-get upgrade

Ставим Nginx

sudo apt-get install nginx

Теперь заходим под виртуальную среду нашего(или вашего) проекта

cd /home/myprojectenv/
source bin/activate

Под активной виртуальной средой ставим Gunicorn

(myprojectenv)user@host: /home/myprojectenv# pip[pip3] install gunicorn

Замечание. Помните про версии pip. Если Python 2.x, то пишем pip, если Python 3.xpip3. Это по дефолту, если у вас не настроено иначе.

Теперь, перед тем, как идти дальше, протестируем удачную установку Gunicorn и интеграцию с проектом Django и для этого выполняем команду

(myprojectenv)user@host: /home/myprojectenv/myproject# gunicorn myproject.wsgi:application --bind 11.22.33.44:8000

Идем в браузер и запускаем по адресу страницу 11.22.33.44:8000 и убеждаемся, что все ок.

Далее настраиваем папку статических файлов и для этого открываем файл настроек проекта в папке /home/myprojectenv/myproject/myproject/settings.py

nano settings.py

Добавляем в этот файл параметр STATIC_ROOT, если его нет, со следующим значением

...
STATIC_ROOT = '/home/myprojectenv/myproject/static/'
...

Сохраняем, выходим и далее выполняем из папки проекта команду

(myprojectenv)user@host: /home/myprojectenv/myproject# python manage.py collectstatic

После чего в папке проекта появится новая папка с именем static.

Теперь идем и настраиваем Nginx по пути в файле

cd /etc/nginx/sites-available/

открываем файлик default

nano default

и перепишем некоторые моменты, как ниже

server {
    listen 80;
    server_name 11.22.33.44; #либо ip, либо доменное имя
    access_log  /var/log/nginx/example.log;

    location /static/ {
        root /home/myprojectenv/myproject/;
        expires 30d;
    }

    location / {
        proxy_pass http://127.0.0.1:8000; 
        proxy_set_header Host $server_name;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
  }

сохраняем и выходим.

Выполняем перезапуск Nginx, чтобы изменения вступили в силу

sudo service nginx restart

 

Активируем нашу среду и заходим в папку проекта для проверки запуска в связке Gunicon + Nginx

(myprojectenv)user@host: /home/myprojectenv/myproject# gunicorn myproject.wsgi:application

В браузере набираем 11.22.33.44:8000 и убеждаемся, что все ок.

Установка и настройка Supervisor

Чтобы ваше приложение стартовало после любого непредвиденного рестарта системы или сбоя, нам нужно использовать в деле supervisor.

Установим supervisor

apt-get install supervisor

Создадим конфигурационный файл для gunicorn в подпапке проекта (myproject/myproject/) рядом с settings.py

cd /home/myprojectenv/myproject/myproject
touch gunicorn.conf.py
nano gunicorn.conf.py

и записываем туда такие данные, которые означают, что данный проект будет запущен на IP и порте 0.0.0.0:8000, что будет означать внешний адрес нашего VPS. Если у вас сервер локальный, то ставим 127.0.0.1

bind = '0:8000'
workers = 3
user = "nobody"

Теперь создаем конфигурационный файл для supervisor

cd /etc/supervisor/conf.d/
touch myproject.conf
nano myproject.conf

и записываем туда такие данные

[program:myproject]
command=/home/myprojectenv/bin/gunicorn myproject.wsgi:application -c /home/myprojectenv/myproject/myproject/gunicorn.conf.py
directory=/home/myprojectenv/myproject
user=nobody
autorestart=true
redirect_stderr=true

 

Запускаем проект через supervisor

supervisorctl restart myproject

В браузере набираем 11.22.33.44:8000 и убеждаемся, что все ок.

Дополнительный тест. Можно также перезагрузить сервер

shutdown -r now

и убедиться, что наш проекта на Django сам автоматом встал и заработал при помощи supervisor.

При использовании Supervisor необходимо использовать его подпроцесс управления supervisorctl. Остальные основные команды supervisor

  • supervisorctl start myproject — запуск процесса;
  • supervisorctl reread — перезапуск системы;
  • supervisorctl update — обновить систему;
  • supervisorctl status myproject — узнать статус процесса;
  • supervisorctl remove myproject — удалить процесс.

 

Возможные ошибки использования Supervisor и Gunicorn

Ошибки в файлах конфигурации

Это с большей вероятностью, потому что конфигурационных файлов 2 и нужно, чтобы они были настроены слажено без ошибок. Напомним, что они у нас находятся по путям:

  • Файл конфигурации Gunicorn в пределах текущего проекта /home/myprojectenv/myproject/myproject/gunicorn.conf.py
  • Файл конфигурации проекта в виде управляемого процесса внутри Supervisor /etc/supervisor/conf.d/myproject.conf

 

Ошибка запуска из-за занятости стандартного порта Supervisor

Обычно, эта ошибка выглядит так, при запуске команды запуска supervisorctl start myproject

cloudApp: ERROR (spawn error)

или так, при запуске команды поиска ошибок supervisord -n

Error: Another program is already listening on a port that one of our HTTP servers is configured to use.  Shut this program down first before starting supervisord

Для решения этой проблемы сначала убиваем процесс Supervisor, который можно сделать несколькими способами.

Первый. Выводим весь список процессов Supervisor и убиваем нужный по PID(в списке он будет после первого)

ps -ef | grep supervisord
sudo kill -9 PID_OUR_PROJECT

или

ps -ef | grep supervisord
kill -s SIGTERM PID_OUR_PROJECT

 

Второй. Убиваем сам supervisord

sudo pkill supervisord

 

Третий. Удаляем файл supervisor.sock и запускаем supervisor обратно

sudo unlink /run/supervisor.sock
sudo /etc/init.d/supervisor start

Теперь перезапускаем проект

supervisorctl start cloudApp
Ошибка ERROR (no such process) при запуске нового процесса

Данная ошибка появляется, когда мы создали новый проект, но он не обновился в системе Supervisot и для решения этой проблемы нам нужно перезаписать все процессы и перезагрузить supervisorctl

supervisorctl reread
supervisorctl reload

 

Если не удается идентифицировать ошибку

Если проблему трудно найти или идентифицировать, то будет полезной использовать команду

supervisord -n

который выведет весь список ошибок в файлах или сервисах, которые мешают запускаться процессу Supervisor.

 

Использованные материалы:

  1. Django + Python3 + Nginx + Gunicorn + DO;
  2. Setting up Django with Nginx, Gunicorn, virtualenv, supervisor and PostgreSQL

 

Построение проекта Django с БД Postgre SQL и импорт данных из SQLite

👁 112 просмотров
1 Звезда2 Звезды3 Звезды4 Звезды5 Звезд (Пока оценок нет)
Загрузка...

Допустим, есть у нас такая ситуация, что проект на Django установлен а использованием локальной БД SQLite и нам необходимо это все экспортировать в реляционную БД на примере PostgreSQL.

Реляционные системы управления базами данных являются ключевым компонентом многих веб-сайтов и приложений. Они обеспечивают структурированный способ хранения, организации и доступа к информации.

PostgreSQL или Postgres — это система управления реляционными базами данных, которая обеспечивает реализацию языка запросов SQL. Это популярный выбор для многих небольших и крупных проектов и имеет то преимущество, что он совместим со стандартами и обладает множеством дополнительных функций, таких как надежные транзакции и параллелизм без блокировок чтения.

Установка и настройка PostgreSQL на Ubuntu

Репозитории Ubuntu по умолчанию содержат пакеты Postgres, поэтому их можно установить с помощью apt-системы. Перед этим обновим свой локальный индекс пакета. Затем установим пакет Postgres вместе с пакетом -contrib, который добавит некоторые дополнительные утилиты и функции

sudo apt-get update
sudo apt-get install libpq-dev postgresql postgresql-contrib

Запускаем PostgreeSQL

sudo su - postgres

Командная строка терминала теперь будет начинаться с postgres@yourserver.

Теперь заходим в режим команд SQL и интерфейса PostgreSQL

postgres@yourserver# psql

После команды выше командная строка теперь будет начинаться с postgres=#.

Создаем базу данных для проекта, обратите внимание, что в режиме SQL запрос должен оканчиваться «;»

postgres=# CREATE DATABASE projectdb;

 

Создаем пользователя для БД проекта

postgres=# CREATE USER dbuser WITH PASSWORD 'userpass';

Мы устанавливаем кодировку по умолчанию для UTF-8, которую ожидает Django. Мы также устанавливаем схему изоляции транзакций по умолчанию «read commit», которая блокирует чтение из незафиксированных транзакций. Наконец, мы устанавливаем часовой пояс. По умолчанию наши проекты Django будут настроены на использование UTC

postgres=# ALTER ROLE dbuser SET client_encoding TO 'utf8';
postgres=# ALTER ROLE dbuser SET default_transaction_isolation TO 'read committed';
postgres=# ALTER ROLE dbuser SET timezone TO 'UTC';

 

Теперь все, что нам нужно сделать, это предоставить нашим пользователям права доступа к базе данных, которую мы создали

postgres=# GRANT ALL PRIVILEGES ON DATABASE projectdb TO dbuser;

 

Выходим из режима ввода SQL, чтобы вернуться к сеансу оболочки postgres

\q

Выходим из сеанса оболочки postgres, чтобы вернуться к сеансу оболочки обычного пользователя

exit

Настройка проекта Django на использование

PostgreSQL

Теперь, когда наша база данных настроена, мы можем установить Django. Для большей гибкости мы установим Django и все его зависимости в виртуальной среде Python

Создание и настройка виртуальной среды

Создаем виртуальную среду для хранения зависимостей Python проекта Django, набрав команду

virtualenv myprojectenv

Это установит локальную копию Python и pip[pip3] в каталог myprojectenv

Прежде, чем создать проект Django нужно сначала активировать виртуальную среду, которую мы создали шагом выше

source myprojectenv/bin/activate

После этой команды строка запроса будет похожа на (myprojectenv)user@host.

В окружении проекта устанавливаем пакеты Django и psycopg2, который является бэкэндом для PostgreSQL

(myprojectenv)user@host: /myprojectenv# pip[pip3] install django psycopg2

 

Замечение. Тут еще один момент, связанный с psycopg2. Начиная с версии 2.8 данный пакет будет переименован в psycopg2-binary и поэтому нужно дополнительно установить данный пакет с этим названием

(myprojectenv)user@host: /myprojectenv# pip[pip3] install django psycopg2-binary

В противном случае, может возникнуть предупреждение такого рода

/home/websofter/lib/python3.6/site-packages/psycopg2/__init__.py:144: 
UserWarning: The psycopg2 wheel package will be renamed from release 2.8; 
in order to keep installing from binary please use "pip install psycopg2-binary" instead. 
For details see: <http://initd.org/psycopg/docs/install.html#binary-install-from-pypi>.

Дополнительно про это можно узнать по ссылке.

Создание и настройка проекта Django

Теперь мы можем запустить проект Django в нашей директории myprojectenv. Это создаст дочерний каталог с именем проекта myproject , в котором будет еще одна папка с тем же названием для хранения самого кода и создаст сценарий управления в текущем каталоге. Не забудьте добавить точку в конце команды, чтобы она была правильно настроена

(myprojectenv)user@host: /myprojectenv# pip[pip3] django-admin.py startproject myproject .

 

Теперь нам надо отредактировать файл настроек myproject/myproject/settings.py проекта на то, чтобы проект, вместо базы SQLite, который стоит по умолчанию начал работать с базой Postgre, который мы выше настроили и для этого открываем этот файл настроек и ищем там строки

. . .
ALLOWED_HOSTS = []
. . .
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}
. . .

и заменяем это все на

. . .
ALLOWED_HOSTS = ['server-domain_or_IP']
. . .
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'projectdb',
        'USER': 'dbuser',
        'PASSWORD': 'userpass',
        'HOST': 'localhost',
        'PORT': '',
    }
}
. . .

Сохраняем и закрываем этот файл.

Миграция баз данных на использование Postgre и запуск проекта

Теперь, когда настройки Django настроены, мы можем перенести наши структуры данных в нашу базу данных и протестировать сервер.

(myprojectenv)user@host: /myprojectenv/myproject# python manage.py makemigrations
(myprojectenv)user@host: /myprojectenv/myproject# python manage.py migrate

После создания структуры базы данных мы можем создать учетную запись администратора проекта, набрав

(myprojectenv)user@host: /myprojectenv/myproject# python manage.py createsuperuser

Вам будет предложено выбрать имя пользователя, указать адрес электронной почты и выбрать и подтвердить пароль для учетной записи

(myprojectenv)user@host: /myprojectenv/myproject# python manage.py runserver 0.0.0.0:8001

На этом интеграция и запуск закончена. Остается любоваться результатом через адрес сервера и порт 8001, на котором запущен наш проект Django с БД Postgree

http://server_domain_or_IP:8000

 

Импорт данных из SQLite в PostgreSQL

в проекте Django

Окей. Выше мы рассмотрели, как интегрировать проект Django с Postgre, но что если в SQLite есть уже данные, которые нужно перенести в Postgre SQL?

Выгружаем существующие данные из SQLite, причем, в настройках settings.py нужно настроить на использование SQLite

(myprojectenv)user@host: /myprojectenv/myproject# python manage.py dumpdata > datadump.json

Изменяем settings.py на использование Postgres backend. Выше мы это уже рассматривали как делать.

Убедитесь, что вы можете подключиться к PostgreSQL. Затем

(myprojectenv)user@host: /myprojectenv/myproject# python manage.py migrate --run-syncdb<br>

 

Использованные источники:

  1. How To Use PostgreSQL with your Django Application on Ubuntu 14.04
  2. How to migrate Django from SQLite to PostgreSQL

Часть 4. Python/Django и Hello World. Структура проекта Django и создание приложений

👁 251 просмотров
1 Звезда2 Звезды3 Звезды4 Звезды5 Звезд (Пока оценок нет)
Загрузка...

Цикл статей «Django шаг за шагом»

Информация, которая будет дана в данном посте, исходя из заголовка, будет актуальная для версий Django 1.9.x и Python 3.4.x, что будут соответствовать последним версиям на момент написания поста. Для проверки версии Django — фреймворка существует замечательная команда:

python -c "import django; print(django.get_version())"

В мире так принято, что перед делом, надо знать, что делаешь и подходить нужно со знанием дела и, поэтому, это тот самый момент, когда пора понимать основу структуры проекта на Django. И, как уже отмечали, проект на Django — целое, которое составлено из отдельных частей(приложений, модулей, пакетов и т.п.), что дает ему гибкость в работе и продуктивность в использовании кода, соответственно. Создав проект мы должны, далее, уже создать приложения, которые будут выполнять в проекте ту или иную функцию.

Перед тем, как добавить новое приложение к проекту мы должны проделать шаги из серии прошлых частей постов, а именно:

  • установить интерпретатор Python;
  • установить менеджер пакетов pip;
  • установить модуль создания виртуальных  сред virtualenv через менеджера пакетов pip, что поможет нам управлять проектом находясь в UNIX — подобной среде;
  • создать виртуальную среду (например, test) и активировать его;
  • установить фреймворк Django через менеджера пакетов pip из активированной виртуальной среды;
  • создать новый проект(например, mysite) в текущей виртуальной среде.

Итак, проект под названием mysite у нас есть, осталось только добавить приложения к этому проекту. Но, перед этим, нужно разобраться со структурой. На данный момент, структура пустого проекта такова

django-proj-structure-for-post

По порядку разберем каждую папку и файл начального проекта, который не содержит приложений:

  • Внешняя папка mysite/ — эта директория является корневой папкой нашего сайта и просто контейнером, где будут создаваться наши приложения и файлы для управления проектом. Название данной директории ничего не значит для Django и его можно поменять на свое усмотрение;
  • manage.py — инструмент управления из командной строки при помощи которого можно управлять проектом различными путями. В частности, при помощи данного инструмента запускается наш проект на сервере Python. Про этот инструмент можно почитать дополнительно вот тут;
  • внутренняя директория mysite/ — это текущий и единственный, на данный момент, пакет Python в нашем проекте. Имя данного пакета. в дальнейшем, будет использовано для импорта внутренней структуры кода, к примеру, для импорта mysite.urls;
  • mysite/__init__.py — этот пустой файл предназначен для указания и регистрации пакетов. Наличие данного файла в директории mysite/ говорит Python, чтобы он различал эту директорию в виде пакета. Дополнительно об этом можно почитать тут;
  • mysite/settings.py — это файл установок и конфигурации текущего проекта Django;
  • mysite/urls.py — это URL — декларации текущего Django — проекта или, иначе говоря,“таблица контента” вашего Django-проекта. Дополнительно об этом можно почитать тут;
  • mysite/wsgi.py — точки входа для WSGI-совместимого веб-сервера. Подробно об этом тут.

После того, как разобрали начальную структуру пустого проекта, давайте создадим какое-нибудь(например, блог) приложение через команду:

python manage.py startapp blog

После выполнения данной команды в корневой папке проекта появится новая директория blog/, которая будет содержать свой список файлов

django-proj-app-structure-for-post

Раскроем суть каждой папки и файла в приложении:

  • migrations/ — папка, в которой будут храниться миграции базы данных;
  • _init_.py — указание Python, чтобы он обработал папку приложения в виде пакета проекта;
  • admin.py — здесь хранятся настройки стандартной административной панели;
  • models.py — файл, в котором будут модели приложения;
  • test.py — песочница юнит-тестов;
  • views.py — файл для хранения видов.

Суть структуры приложения проекта на Django сводится к тому, что оно работает частично по образу MVC, но существенно отличается от этой модели хотябы потому, что контроллеры в MVC — это URL  Django.

Часть 3. Python/Django и Hello World. Настройка быстрого запуска проектов в виртуальных средах через обертки разделения под OS Windows.

👁 204 просмотров
1 Звезда2 Звезды3 Звезды4 Звезды5 Звезд (Пока оценок нет)
Загрузка...

Цикл статей «Django шаг за шагом»

После того, когда мы уже создали и запустили тестовый проект Python/Django под ОС Windows, то нам необходимо сделать несколько операций по упрощению управления и переключения между проектами через командную строку, чтобы не писать лишний раз однотипные команды. И тут мы подходим к стадию изучения оберток виртуальной среды для разделения проектов и быстрого их запуска.

Установка инструмента обертки виртуальной среды

Для установки инструмента виртуальной обертки заходим в папку пользователя, у меня это C:/Users/WebSofter, и запускаем команду установки:

pip install virtualenvwrapper-win

Далее проследует процесс установки и после установки надо создать новую переменную в переменных средах пользователя в виде WORKON со значением пути %USERPROFILE%\Envs, где Envs — это папка хранения для всех, создаваемых виртуальных сред
python-create-virt-param-wrapper-WORKON

Отныне, для создания виртуальной среды достаточно из любого места набрать команду:

mkvirtualenv MyEnv

где MyEnv — это название новой среды. При создании виртуальной среды они автоматически создаются в папке C:\WebSofter\Envs. А для деактивации текущей виртуальной среды достаточно набрать из любого места команду:

deactivate

А для переключения активации той или иной среды достаточно набрать команду:

WORKON MyEnv

где MyEnv — активируемая среда.
На этом установка и настройка оберток виртуальной среды окончено.