Nastya vor 1 Jahr
Ursprung
Commit
69a0373089
44 geänderte Dateien mit 1406 neuen und 2 gelöschten Zeilen
  1. 20 2
      .gitignore
  2. 55 0
      README.md
  3. 3 0
      bin/butler.sh
  4. 0 0
      butler/__init__.py
  5. 13 0
      butler/admin.py
  6. 6 0
      butler/apps.py
  7. 34 0
      butler/forms.py
  8. 25 0
      butler/models.py
  9. BIN
      butler/static/butler/img/bigimg.png
  10. BIN
      butler/static/butler/img/header-line.png
  11. BIN
      butler/static/butler/img/headerimage.png
  12. BIN
      butler/static/butler/img/letterlogo.png
  13. BIN
      butler/static/butler/img/main-logo.png
  14. BIN
      butler/static/butler/img/orderimg.png
  15. 36 0
      butler/templates/butler/base.html
  16. 52 0
      butler/templates/butler/footer.html
  17. 52 0
      butler/templates/butler/header.html
  18. 12 0
      butler/templates/butler/index.html
  19. 93 0
      butler/templates/butler/menu.html
  20. 36 0
      butler/templates/butler/pages/about.html
  21. 34 0
      butler/templates/butler/pages/contact.html
  22. 79 0
      butler/templates/butler/pages/faq.html
  23. 18 0
      butler/templates/butler/pages/in_work.html
  24. 59 0
      butler/templates/butler/pages/main.html
  25. 71 0
      butler/templates/butler/pages/order.html
  26. 105 0
      butler/templates/butler/pages/price.html
  27. 15 0
      butler/templates/butler/pages/simple.html
  28. 7 0
      butler/templates/butler/ser_btn.html
  29. 3 0
      butler/tests.py
  30. 28 0
      butler/urls.py
  31. 27 0
      butler/utils.py
  32. 136 0
      butler/views.py
  33. 0 0
      core/__init__.py
  34. 16 0
      core/asgi.py
  35. 9 0
      core/conf_gunicorn.py
  36. 39 0
      core/config_template.py
  37. 154 0
      core/settings.py
  38. 30 0
      core/urls.py
  39. 16 0
      core/wsgi.py
  40. 67 0
      dumpdb.sql
  41. 18 0
      install.sh
  42. 22 0
      manage.py
  43. BIN
      pages_pdf/main.pdf
  44. 16 0
      requirements.txt

+ 20 - 2
.gitignore

@@ -1,2 +1,20 @@
-# Desktop Services Store
-.DS_Store
+# Virtualenv
+env/
+venv/
+# VSCode
+.vscode
+
+# Python
+__pycache__/
+*.py[cod]
+*$py.class
+
+# Other
+*.sqlite3
+#djanog
+core/config.py
+staticfiles/
+!staticfiles/.gitkeep
+butler/migrations/
+!butler/migrations/.gitkeep
+!butler/migrations/__init__.py

+ 55 - 0
README.md

@@ -0,0 +1,55 @@
+# Butler
+
+## How install?
+
+1. Download or clone repository
+```bash
+git clone -b main https://git.sharix-app.org/Drinkertea/butler_django.git butler
+```
+2. Set up a configuration file
+```python
+#Create file config.py with this setting or rename this file to config.py
+
+#BASE
+DEBUG=True
+SECRET_KEY='secret-key(absolutely any character)'
+ALLOWED_HOSTS = ['127.0.0.1']
+CSRF_TRUSTED_ORIGINS = []
+
+#DATABSE
+DB_NAME=None
+DB_USER=None
+DB_PASSWORD=None
+DB_HOST=None
+
+#GUNICORN
+BIND = "127.0.0.1:8000"
+WORKERS = 1
+THREADS = 2
+
+#STATIC
+from pathlib import Path
+import os
+BASE_DIR = Path(__file__).resolve().parent.parent
+STATIC_URL = '/static/'
+STATICFILES_DIRS = [BASE_DIR / "SharixAdmin/static/", BASE_DIR / "tickets/static/"]
+STATIC_ROOT = os.path.join(BASE_DIR, "staticfiles")
+```
+3. Run a **install.sh**
+4. The system will prompt you to create a superuser
+```
+#Example
+7987654321
+admin
+pa$$w0rd
+pa$$w0rd
+```
+5. Set up the **bin/butler.sh** file with valid paths
+
+```bash
+#!/bin/bash
+cd /path/to/project
+exec /path/to/project/env/bin/gunicorn core.wsgi:application -c core/conf_gunicorn.py
+```
+6. It remains to configure Nginx conf and start the daemon
+

+ 3 - 0
bin/butler.sh

@@ -0,0 +1,3 @@
+#!/bin/bash
+cd /root/butler
+exec /root/butler/env/bin/gunicorn core.wsgi:application -c core/conf_gunicorn.py

+ 0 - 0
butler/__init__.py


+ 13 - 0
butler/admin.py

@@ -0,0 +1,13 @@
+from django.contrib import admin
+from butler.models import *
+from butler.utils import create_pages_clean_admin
+
+@admin.register(ButlerPage)
+class ButlerPageAdmin(admin.ModelAdmin):
+    list_display = ('title', 'slug')
+    actions = [create_pages_clean_admin]
+
+@admin.register(FAQmodel)
+class ButlerPageAdmin(admin.ModelAdmin):
+    list_display = ('question',)
+#admin.site.register(ButlerPage)

+ 6 - 0
butler/apps.py

@@ -0,0 +1,6 @@
+from django.apps import AppConfig
+
+
+class ButlerConfig(AppConfig):
+    default_auto_field = 'django.db.models.BigAutoField'
+    name = 'butler'

+ 34 - 0
butler/forms.py

@@ -0,0 +1,34 @@
+from django import forms
+from captcha.fields import CaptchaField
+import datetime
+class MyForm(forms.Form):
+    name = forms.CharField(label="", widget=forms.TextInput(attrs={'class':'form-control', 'placeholder':'Имя', 'id':'sendemailname'}))
+    email = forms.CharField(label="", widget=forms.TextInput(attrs={'class':'form-control', 'placeholder':'Email', 'type':'email', 'id':'sendemailemail'}))
+    message = forms.CharField(label="", widget=forms.Textarea(attrs={'class':'form-control', 'placeholder':'Сообщение', 'rows':'3', 'id':'sendemailmessage'}))
+    captcha = CaptchaField()
+
+SERVICE_CHOICES =(
+    (0, "xxxxxxxxxxxxxxxxxxxxxxxxxxxx"),
+    (1, "xxxxxxxxxxxxxxxxxxxxxxxx"),
+    (2, "xxxxxxxxxxxxxxxxxx"),
+    (3, "xxxxxxxxxxxxxxxxx"),
+    (4, "xxxxxxxxxxxxxxxxxxx"),
+    (5, "xxxxxxxxxxxxx"),
+    (6, "xxxxxx"),
+)
+number_errors = {
+    'required': 'Укажите номер в формате: +79876543210.',
+    'invalid': 'Номер должен быть в формате: +79876543210.'
+}
+service_errors = {
+    'required': 'Выберите хотя бы одну услугу.',
+    'invalid': 'Выберите хотя бы одну услугу.'
+}
+class OrderForm(forms.Form):
+    name = forms.CharField(label="", widget=forms.TextInput(attrs={'class':'form-control', 'placeholder':'Имя'}))
+    surname = forms.CharField(label="", widget=forms.TextInput(attrs={'class':'form-control', 'placeholder':'Фамилия'}))
+    service = forms.MultipleChoiceField( required=True, choices=SERVICE_CHOICES, widget=forms.CheckboxSelectMultiple(), error_messages=service_errors)
+    datetime = forms.DateTimeField(initial=datetime.date.today, widget=forms.DateTimeInput(attrs={'type':'datetime-local', 'class':'form-control', 'placeholder':'form-control'}) )
+    phone = forms.RegexField(regex=r'^\+?1?\d{9,15}$', error_messages=number_errors, widget=forms.TextInput(attrs={'class':'form-control', 'type':'tel', 'placeholder':'+79876543210'}))
+    comment = forms.CharField(label="", required=False, widget=forms.Textarea(attrs={'class':'form-control', 'placeholder':'Комментарий', 'rows':'5'}))
+    captcha = CaptchaField()

+ 25 - 0
butler/models.py

@@ -0,0 +1,25 @@
+from django.db import models
+from django.urls import reverse
+from ckeditor.fields import RichTextField
+
+class ButlerPage(models.Model):
+    title = models.CharField(max_length=150)
+    slug = models.SlugField(unique=True)
+    content = RichTextField(blank=True, null=True)
+
+    def __str__(self) -> str:
+        return self.title
+    
+    class Meta:
+        verbose_name = 'Простая страница'
+        verbose_name_plural = 'Простые страницы'
+    
+class FAQmodel(models.Model):
+    question = models.TextField(blank=True)
+    answer = models.TextField(blank=True)
+
+    def __str__(self) -> str:
+        return self.question
+    
+    class Meta:
+        verbose_name = 'FAQ'

BIN
butler/static/butler/img/bigimg.png


BIN
butler/static/butler/img/header-line.png


BIN
butler/static/butler/img/headerimage.png


BIN
butler/static/butler/img/letterlogo.png


BIN
butler/static/butler/img/main-logo.png


BIN
butler/static/butler/img/orderimg.png


+ 36 - 0
butler/templates/butler/base.html

@@ -0,0 +1,36 @@
+{% load static %}
+<!DOCTYPE html>
+<html lang="ru" class="h-100">
+<head>
+    <script async src="https://www.googletagmanager.com/gtag/js?id=G-Q1E14C3NE6"></script>
+    <script>
+    window.dataLayer = window.dataLayer || [];
+    function gtag(){dataLayer.push(arguments);}
+    gtag('js', new Date());
+
+    gtag('config', 'G-Q1E14C3NE6');
+    </script>
+    <meta charset="UTF-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <link rel="shortcut icon" type="image/png" href="{% static '/butler/img/letterlogo.png' %}">
+    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
+    
+    <title></title>
+    <style type="text/css">
+        @import url('https://fonts.googleapis.com/css2?family=Lobster&display=swap');
+        @import url('https://fonts.googleapis.com/css2?family=Forum&display=swap');
+        * { 
+         font-family: 'Forum', 'Lobster', cursive;
+        }
+    </style>
+</head>
+<body class="h-100">
+    {% block content %}
+    {% endblock %}
+    <script>
+        document.getElementById("date-year").innerHTML = new Date().getFullYear();
+    </script>
+    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
+</body>
+</html>

+ 52 - 0
butler/templates/butler/footer.html

@@ -0,0 +1,52 @@
+{% load static %} 
+<style>
+@media screen and (max-width: 860px) {
+  .mob-footer {
+    display: none;
+  }
+}
+</style>
+<footer class="footer mt-auto py-3">
+    <div class="container mob-footer">
+        <div class="row m-1 mx-4" style="font-size: 14px;">
+            <div class="col-3" style="font-family: Lobster;">© <span id="date-year" style="font-family: Lobster;">2022</span> <a href="#" style="text-decoration: none; color: black; font-family: Lobster;"></a>ссылка на сайт</div>
+            
+            <div class="col-6 text-center">
+              <img src="{% static 'butler/img/letterlogo.png' %}" style="width: 40px;" />
+              <img src="{% static 'butler/img/main-logo.png' %}" style="width: 100px;" />
+            </div>
+            <div class="col-3 text-end" style="font-family: Lobster;">
+                телефон
+                <br>
+                 e-mail:<a href="#" style="text-decoration: none; color: black; font-family: Lobster;">email</a>
+            </div>
+          </div>
+          <div class="row m-1">
+            <div class="col-12">
+              <img
+                src="{% static 'butler/img/headerimage.png' %}"
+                style="width: 100%; height: 100%"
+              />
+            </div>
+          </div>
+          <div class="row " style="margin-top: -9px;">
+            <ul class="nav justify-content-center">
+              <li class="nav-item my-1 m-sm-1 mx-lg-4">
+                <a class="nav-link" href="/" style="color: #060936;"><h4>УСЛУГИ</h4></a>
+              </li>
+              <li class="nav-item my-1 m-sm-1 mx-lg-4">
+                <a class="nav-link" href="{% url 'order' %}" style="color: #060936;"><h4>ЗАКАЗ ОНЛАЙН</h4></a>
+              </li>
+              <li class="nav-item my-1 m-sm-1 mx-lg-4">
+                <a class="nav-link" href="{% url 'faq' %}" style="color: #060936;"><h4>FAQ</h4></a>
+              </li>
+              <li class="nav-item my-1 m-sm-1 mx-lg-4">
+                <a class="nav-link" href="{% url 'price' %}" style="color: #060936;"><h4>ЦЕНЫ</h4></a>
+              </li>
+              <li class="nav-item my-1 m-sm-1 mx-lg-4">
+                <a class="nav-link" href="{% url 'contact' %}" style="color: #060936;"><h4>КОНТАКТЫ</h4></a>
+              </li>
+            </ul>
+          </div>
+    </div>
+  </footer>

+ 52 - 0
butler/templates/butler/header.html

@@ -0,0 +1,52 @@
+{% load static %} 
+<style>
+  .header-line{
+    font-family:Roboto;
+    background-image: url("{% static 'butler/img/header-line.png' %}");
+    background-repeat: no-repeat;
+    background-size: 100% 100%;
+  }
+</style>
+<div class="container-sm">
+    <div class="row m-3">
+      <div class="col-6" style="font-size: 22px; font-family: Lobster;">Москва</div>
+      <div class="col-6 text-end" style="font-size: 22px; font-family: Lobster;">телефон</div>
+    </div>
+    <div class="row m-3">
+      <div class="col-12" style="font-size: 22px; font-family: Lobster;">Lorem ipsum dolor sit amet consectetur adipisicing.</div>
+    </div>
+    <div class="row m-4">
+      <div class="col-12 text-center">
+        <img src="{% static 'butler/img/letterlogo.png' %}" alt="" />
+        <img src="{% static 'butler/img/main-logo.png' %}" alt="" />
+      </div>
+    </div>
+    <div class="row m-2">
+      <div class="col-12">
+        <img
+          src="{% static 'butler/img/headerimage.png' %}"
+          style="width: 100%; height: 100%"
+        />
+      </div>
+    </div>
+    <div class="row " style="margin-top: -9px;">
+      <ul
+        class="nav justify-content-center header-line">
+        <li class="nav-item my-1 m-sm-1 mx-lg-4">
+          <a class="nav-link" href="/" style="color: white; "><h4>УСЛУГИ</h4></a>
+        </li>
+        <li class="nav-item my-1 m-sm-1 mx-lg-4">
+          <a class="nav-link" href="{% url 'order' %}" style="color: white; "><h4>ЗАКАЗ ОНЛАЙН</h4></a>
+        </li>
+        <li class="nav-item my-1 m-sm-1 mx-lg-4">
+          <a class="nav-link" href="{% url 'faq' %}" style="color: white; "><h4>FAQ</h4></a>
+        </li>
+        <li class="nav-item my-1 m-sm-1 mx-lg-4">
+          <a class="nav-link" href="{% url 'price' %}" style="color: white; "><h4>ЦЕНЫ</h4></a>
+        </li>
+        <li class="nav-item my-1 m-sm-1 mx-lg-4">
+          <a class="nav-link" href="{% url 'contact' %}" style="color: white; "><h4>КОНТАКТЫ</h4></a>
+        </li>
+      </ul>
+    </div>
+  </div>

+ 12 - 0
butler/templates/butler/index.html

@@ -0,0 +1,12 @@
+{% extends 'butler/base.html' %} 
+
+{% block content %}
+
+{% include 'butler/header.html' %}
+
+<div class="container" style="min-height: 500px;">
+    {% block container %}
+    {% endblock container %}
+</div>
+{% include 'butler/footer.html' %}
+{% endblock %}

+ 93 - 0
butler/templates/butler/menu.html

@@ -0,0 +1,93 @@
+<style>
+    .menu-a li a {
+        font-family: Forum;
+        text-decoration: none;
+        color: black;
+        font-size: 18px;
+    }
+
+    .menu-a li a:hover {
+        text-shadow: 0.5px 0.5px black;
+    }
+</style>
+<div class="container">
+    <hr>
+    <h2 style="font-family: Forum; ">УСЛУГИ</h2>
+    <hr>
+    <ul class="menu-a" style="
+    list-style: none;
+    margin-left: -30px;
+    line-height: 25px;">
+    {% for item in menu %}
+    {% comment %} {% url item.slug %} {% endcomment %}
+        <li><a href="#"><h5>{{ item.title }}</h5></a></li>
+    {% endfor %}
+    </ul>
+    <hr>
+    <h2 style="font-family: Forum; ">ОТЗЫВЫ О НАС</h2>
+    <hr>
+    <figure class="text-end">
+        <blockquote class="blockquote">
+            <p style="
+                text-align: left;
+                font-family: Forum; 
+                font-size: 15px;">Lorem ipsum dolor sit amet consectetur adipisicing elit. A quis non autem eveniet consectetur quibusdam.</p>
+        </blockquote>
+        <figcaption class="blockquote-footer" style="font-family: Forum; font-size: 14px;">
+            Автор
+        </figcaption>
+    </figure>
+
+    <figure class="text-end">
+        <blockquote class="blockquote">
+            <p style="
+                font-family: Forum; 
+                text-align: left;
+                font-size: 15px;">Lorem, ipsum dolor sit amet consectetur adipisicing elit. Sequi doloremque, atque aliquam dignissimos aperiam hic.</p>
+        </blockquote>
+        <figcaption class="blockquote-footer" style="font-family: Forum; font-size: 14px;">
+            Автор
+        </figcaption>
+    </figure>
+    <hr>
+    <form method="post" style="font-family: Forum;" class="row g-2">
+        {% csrf_token %}
+        {{ form.name }}
+        {{ form.email }}
+        {{ form.message }}
+        {{ form.captcha}}
+        {% if form.captcha.errors %}
+            <div class="alert alert-danger" role="alert">
+                Неверный ответ на CAPTCHA
+            </div>  
+        {% endif %}
+        <button class="btn btn-light my-1" id="btnsend" type="submit" 
+        style="color: #060936;
+        box-shadow: 1px 1px 2px gray;">Отправить</button>
+    </form>
+   <script>
+    //Скрипт для отображения капчи после заполнения всех полей
+    var captchaImage = document.getElementsByClassName('captcha')[0]
+    var captcha = document.getElementById('id_captcha_1')
+    var name = document.getElementById('sendemailname')
+    var email = document.getElementById('sendemailemail')
+    var message = document.getElementById('sendemailmessage')
+    var btnsend = document.getElementById('btnsend')
+    function checkFields(){
+        if(name.value != "" && email.value != "" && message.value != ""){
+            captcha.style.display = "initial"
+            captchaImage.style.display = "initial"
+        }else{
+            captcha.style.display = "none"
+            captchaImage.style.display = "none"
+        }
+    }
+    checkFields()
+    btnsend.addEventListener("mouseenter", (event) => {
+        checkFields()
+    });
+    captcha.className += " form-control";
+    captcha.placeholder = "Ответ на капчу";
+   </script>
+
+</div>

+ 36 - 0
butler/templates/butler/pages/about.html

@@ -0,0 +1,36 @@
+{% extends 'butler/main.html' %}
+
+{% block about %}
+
+  <h3>&nbsp;</h3>
+
+  <h1>О КОМПАНИИ</h1>
+
+  <h4><span style="font-size:20px">Lorem ipsum dolor sit amet consectetur adipisicing elit. Dolor, culpa cum vel veniam, quaerat assumenda unde deserunt mollitia architecto nemo alias ullam omnis odit labore</span></h4>
+
+  <h2>&nbsp;</h2>
+
+  <h1>НАШИ ПРЕИМУЩЕСТВА</h1>
+
+  <h4><span style="font-size:20px">Lorem ipsum dolor sit amet consectetur, adipisicing elit.</span></h4>
+
+  <h4><span style="font-size:20px">Lorem ipsum dolor sit amet consectetur adipisicing elit.</span></h4>
+
+  <h4><span style="font-size:20px">Lorem ipsum, dolor sit amet consectetur adipisicing </span></h4>
+
+  <h4><span style="font-size:20px">Lorem ipsum, dolor sit amet consectetur adipisicing elit.</span></h4>
+
+  <h4><span style="font-size:20px">Lorem ipsum dolor sit amet consectetur adipisicing elit.</span></h4>
+
+  <h4><span style="font-size:20px">Lorem ipsum dolor sit amet consectetur adipisicing elit.</span></h4>
+
+  <h2>&nbsp;</h2>
+
+  {% comment %} <h1>ПАКЕТНОЕ ОБСЛУЖИВАНИЕ</h1>
+
+  <h4><span style="font-size:20px">Lorem ipsum dolor sit amet consectetur adipisicing elit. Placeat impedit quas iure eos pariatur deserunt facilis architecto animi ipsum, atque, distinctio iusto dolores deleniti q</span></h4>
+
+  <h4><span style="font-size:20px">Lorem ipsum dolor sit amet consectetur adipisicing elit. Alias aliquam amet ulla</span></h4>
+
+  <h4><span style="font-size:20px">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aliquam quas iusto autem fugiat aut architecto quidem sit totam fugit adipisci? Odio, dolor</span></h4> {% endcomment %}
+{% endblock %}

+ 34 - 0
butler/templates/butler/pages/contact.html

@@ -0,0 +1,34 @@
+{% extends 'butler/index.html' %}
+{% load static %} 
+{% block container %}
+
+<div class="row" style="min-height: 500px;">
+    <div class="container-fluid">
+        <div class="row">
+            <div class="col-12 col-md-7" style=" overflow-wrap: break-word;">
+                <div style="position:relative;overflow:hidden; border-radius: 15px;  box-shadow: 1px 1px 5px gray; margin: 30px 10px 40px 10px;">
+                    <iframe src="#" 
+                    width="100%" height="400" frameborder="1" allowfullscreen="true" style="position:relative;"></iframe>
+                </div>
+            </div>
+            <div class="col-12 col-md-5" style="overflow-wrap: break-word;">
+                <div style="margin: 30px 10px 40px 10px;">
+                    <h2>КОНТАКТЫ:</h2>
+                    
+                    <h6>&nbsp;</h6>
+                    <h5>Адреса:</h5>
+                    <span style="font-size:18px; font-weight: bold;">Lorem ipsum dolor sit amet consectetur adipisicing elit. Quae voluptatibus sunt nesciunt corporis fugit rem.</span>
+                    
+                    <h2>&nbsp;</h2>
+                    <h5>Телефон:</h5>
+                    <span style="font-size:18px; font-weight: bold;">телефон</span>
+                    
+                    <h2>&nbsp;</h2>
+                    <h5>E-mail:</h5>
+                    <span style="font-size:18px; font-weight: bold;"><a href="mailto:info@dvoretskii.ru" style="text-decoration: none; color: black;">email</a></span>
+                </div>    
+            </div>
+        </div>
+    </div>
+</div>
+{% endblock %}

+ 79 - 0
butler/templates/butler/pages/faq.html

@@ -0,0 +1,79 @@
+{% extends 'butler/index.html' %} {% load static %} {% block container %}
+<style>
+  .accordion-button:not(.collapsed) {
+    color: #000000;
+    background-color: #ffffff;
+    box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.125);
+  }
+  .accordion-button:focus {
+    z-index: 3;
+    border-color: #ffffff;
+    outline: 0;
+    box-shadow: 0 0 0 0.25rem transparent;
+  }
+</style>
+<div class="row" style="min-height: 500px">
+  <div class="container-fluid">
+    <div class="row mt-5">
+      <h2>ЧАСТО ЗАДАВАЕМЫЕ ВОПРОСЫ</h2>
+      <div class="accordion accordion-flush" id="accordionFlushExample">
+        {% for item in faq %}
+        <div class="accordion-item">
+            <h2 class="accordion-header" id="flush-headingOne">
+              <button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#flush-collapse{{item.id}}" aria-expanded="false" aria-controls="flush-collapse{{item.id}}">
+                <h5>{{ item.question }}</h5>
+              </button>
+            </h2>
+            <div id="flush-collapse{{item.id}}" class="accordion-collapse collapse" aria-labelledby="flush-heading{{item.id}}" data-bs-parent="#accordionFlushExample">
+              <div class="accordion-body" style="font-size: 18px">
+                {{ item.answer }}
+              </div>
+            </div>
+          </div>
+        {% endfor %}
+      </div>
+    </div>
+    <div class="row">
+      <hr />
+      <h2>ЗАДАТЬ СВОЙ ВОПРОС</h2>
+    </div>
+    <form method="post" style="font-family: Forum" class="row g-2">
+      {% csrf_token %}
+      <div class="row">
+        {% if form.captcha.errors %}
+        <div
+          class="alert alert-danger mt-3 w-100"
+          role="alert"
+        >
+        Неверный ответ на CAPTCHA
+        </div>
+        {% endif %}
+        <div class="col-12 col-md-6 row g-2">
+          {{ form.name }} {{ form.email }} {{ form.message }}
+        </div>
+        <div class="col-12 col-md-6 mt-3">
+          <span class="my-3">{{ form.captcha}} </span>
+
+          <button
+            class="btn btn-light mt-3 w-100"
+            id="btnsend"
+            type="submit"
+            style="color: #060936; margin: 0px; box-shadow: 1px 1px 2px gray"
+          >
+            Отправить
+          </button>
+        </div>
+      </div>
+    </form>
+    <script>
+      //Скрипт для отображения капчи после заполнения всех полей
+      var captchaImage = document.getElementsByClassName("captcha")[0];
+      var captcha = document.getElementById("id_captcha_1");
+      captchaImage.style.height = "80px";
+      captchaImage.style.marginBottom = "20px";
+      captcha.className += " form-control";
+      captcha.placeholder = "Ответ на капчу";
+    </script>
+  </div>
+</div>
+{% endblock %}

+ 18 - 0
butler/templates/butler/pages/in_work.html

@@ -0,0 +1,18 @@
+{% extends 'butler/index.html' %}
+{% load static %} 
+{% block container %}
+
+<div class="row" style="min-height: 500px;">
+    
+    <div class="col-12 col-sm-6 col-md-5 col-lg-4 col-xxl-3">
+        {% include 'butler/menu.html' %}
+    </div>
+
+    <div class="col-12 col-sm-6 col-md-7 col-lg-8 col-xxl-9" style="overflow-wrap: break-word;">
+        {{ mainpage.content|safe }}
+
+        <h1 class="display-6 my-5">Страница в разработке!</h1>
+        
+    </div>
+</div>
+{% endblock %}

+ 59 - 0
butler/templates/butler/pages/main.html

@@ -0,0 +1,59 @@
+{% extends 'butler/index.html' %}
+{% load static %} 
+{% block container %}
+
+<div class="row" style="min-height: 500px;">
+    <!-- видео -->
+    <div class="ratio ratio-21x9">
+        <iframe 
+        src="#">
+         </iframe>
+    </div>
+    
+    <div class="col-12 col-sm-6 col-md-5 col-lg-4 col-xxl-3 order-1 order-md-0">
+        {% include 'butler/menu.html' %}
+    </div>
+    
+    <div class="col-12 col-sm-6 col-md-7 col-lg-8 col-xxl-9 order-0 order-md-1" style="overflow-wrap: break-word;">
+        <!-- {% comment %} {{ flatpage.content|safe }} {% endcomment %}
+        {{ mainpage.content|safe }} -->
+        {% block about %}{% endblock %}
+        <h3>&nbsp;</h3>
+
+        <h1>О КОМПАНИИ</h1>
+      
+        <h4><span style="font-size:20px">Lorem ipsum dolor sit amet consectetur adipisicing elit. Dolor, culpa cum vel veniam, quaerat assumenda unde deserunt mollitia architecto nemo alias ullam omnis odit labore</span></h4>
+      
+        <h2>&nbsp;</h2>
+      
+        <h1>НАШИ ПРЕИМУЩЕСТВА</h1>
+      
+        <h4><span style="font-size:20px">Lorem ipsum dolor sit amet consectetur, adipisicing elit.</span></h4>
+      
+        <h4><span style="font-size:20px">Lorem ipsum dolor sit amet consectetur adipisicing elit.</span></h4>
+      
+        <h4><span style="font-size:20px">Lorem ipsum, dolor sit amet consectetur adipisicing </span></h4>
+      
+        <h4><span style="font-size:20px">Lorem ipsum, dolor sit amet consectetur adipisicing elit.</span></h4>
+      
+        <h4><span style="font-size:20px">Lorem ipsum dolor sit amet consectetur adipisicing elit.</span></h4>
+      
+        <h4><span style="font-size:20px">Lorem ipsum dolor sit amet consectetur adipisicing elit.</span></h4>
+      
+        <h2>&nbsp;</h2>
+      
+        {% comment %} <h1>ПАКЕТНОЕ ОБСЛУЖИВАНИЕ</h1>
+      
+        <h4><span style="font-size:20px">Lorem ipsum dolor sit amet consectetur adipisicing elit. Placeat impedit quas iure eos pariatur deserunt facilis architecto animi ipsum, atque, distinctio iusto dolores deleniti q</span></h4>
+      
+        <h4><span style="font-size:20px">Lorem ipsum dolor sit amet consectetur adipisicing elit. Alias aliquam amet ulla</span></h4>
+      
+        <h4><span style="font-size:20px">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aliquam quas iusto autem fugiat aut architecto quidem sit totam fugit adipisci? Odio, dolor</span></h4> {% endcomment %}
+        {% include 'butler/ser_btn.html' %}
+        
+    </div>
+    <div class="col-12 order-2">
+        <img src="{% static 'butler/img/bigimg.png' %}" style="width: 100%; height: 100%;" alt="">
+    </div>
+</div>
+{% endblock %}

+ 71 - 0
butler/templates/butler/pages/order.html

@@ -0,0 +1,71 @@
+{% extends 'butler/index.html' %}
+{% load static %}
+{% block container %}
+
+<div class="row">
+    <div class="col-12 col-md-3"></div>
+    <div class="col-12 col-md-6 my-5" style=" min-height: 500px;">
+        <h2 class="w-100 text-center">ЗАКАЖИТЕ ОНЛАЙН</h2>
+        <h5 class="w-100 text-center">Lorem ipsum dolor, sit amet consectetur adipisicing elit. Molestias ab nemo nisi harum. Laboriosam pariatur facilis accusamus, suscipit assumenda odio.</h5>
+        <form method="post" style="font-family: Forum;" class="row g-2">
+            {% csrf_token %}
+           
+            <div class="col-md-6">
+                {{ form.name }}
+            </div>
+            <div class="col-md-6">
+                {{ form.surname }}
+            </div>
+            <div class="col-md-12">
+                <label for="exampleInputEmail1" class="form-label">Выберите услугу/услуги</label>
+                {{ form.service }}
+            </div>
+            <div class="col-md-6">
+                <label for="exampleInputEmail1" class="form-label">Желаемая дата оказания услуг</label>
+                {{ form.datetime }}
+            </div>
+            <div class="col-md-6">
+                <label for="exampleInputEmail1" class="form-label">Номер телефона</label>
+                {{ form.phone }}
+            </div>
+            <div class="col-md-6">
+                {{ form.comment }}
+            </div>
+            <div class="col-md-6">
+                {{ form.captcha}}
+            </div>
+            {% if form.errors %}
+            <div class="alert alert-danger mt-3 w-100"  role="alert">
+                <ul>
+                    {% if form.captcha.errors %}
+                        <li>Неверный ответ на CAPTCHA</li>
+                    {% endif %}
+                    {% if form.service.errors %}
+                        <li>Выберите хотя бы одну услугу</li>
+                    {% endif %}
+                    {% if form.phone.errors %}
+                        <li>Номер должен быть в формате: +79876543210</li>
+                    {% endif %}
+                </ul>
+                
+            </div>
+            {% endif %}
+            <div class="col-md-12">
+                <button class="btn btn-light mt-3 w-100" id="btnsend" type="submit" style="color: #060936;
+                margin: 0px;
+                box-shadow: 1px 1px 2px gray;">Отправить</button>
+            </div>
+        </form>
+    </div>
+    <div class="col-12 col-md-3"></div>
+    <script>
+        //Скрипт для отображения капчи после заполнения всех полей
+        var captchaImage = document.getElementsByClassName('captcha')[0]
+        var captcha = document.getElementById('id_captcha_1')
+        captchaImage.style.height = "80px";
+        captchaImage.style.marginBottom = "20px";
+        captcha.className += " form-control";
+        captcha.placeholder = "Ответ на капчу";
+    </script>
+</div>
+{% endblock %}

+ 105 - 0
butler/templates/butler/pages/price.html

@@ -0,0 +1,105 @@
+{% extends 'butler/index.html' %}
+{% load static %} 
+{% block container %}
+
+<div class="row" style="min-height: 500px;">   
+    <div class="col-12 mt-5" style="overflow-wrap: break-word;">
+        <h2>УВАЖАЕМЫЕ ГОСПОДА!</h2> 
+        <hr>       
+        <h5>Lorem ipsum dolor sit amet consectetur adipisicing elit. Adipisci mollitia vitae ratione. Culpa, corporis sit aperiam voluptas laudantium, modi libero labore ab blanditiis eligendi porro dignissimos ratione ipsam, possimus eos? </h5>
+        <h5>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Molestiae quae, sunt quis distinctio animi, illo atque dolores natus non voluptates quisquam a. Officia facilis provident magni? Praesentium?</h5>
+        <h5>Lorem ipsum dolor sit amet consectetur adipisicing elit. Accusamus, optio!</h5>
+        <hr> 
+        <h2>&nbsp;</h2> 
+        <h2>СТОИМОСТЬ УСЛУГ</h2>
+        <table class="table table-striped">
+            <thead>
+              <tr>
+                <th scope="col">#</th>
+                <th scope="col">Услуга</th>
+                <th scope="col">Цена</th>
+              </tr>
+            </thead>
+            <tbody>
+              <tr>
+                <th scope="row">1</th>
+                <td>Lorem ipsum dolor sit amet.</td>
+                <td>Lorem, ipsum.</td>
+              </tr>
+              <tr>
+                <th scope="row">2</th>
+                <td>Lorem ipsum dolor sit amet.</td>
+                <td>Lorem, ipsum.</td>
+              </tr>
+              <tr>
+                <th scope="row">3</th>
+                <td>Lorem ipsum dolor sit amet.</td>
+                <td>Lorem, ipsum.</td>
+              </tr>
+              <tr>
+                <th scope="row">4</th>
+                <td>Lorem ipsum dolor sit amet.</td>
+                <td>Lorem, ipsum.</td>
+              </tr>
+              <tr>
+                <th scope="row">5</th>
+                <td>Lorem ipsum dolor sit amet.</td>
+                <td>Lorem, ipsum.</td>
+              </tr>
+              <tr>
+                <th scope="row">6</th>
+                <td>Lorem ipsum dolor sit amet.</td>
+                <td>Lorem, ipsum.</td>
+              </tr>
+            </tbody>
+          </table>
+          
+          <h2>&nbsp;</h2> 
+          
+        <h2>ДОПОЛНИТЕЛЬНЫЕ УСЛУГИ</h2>
+        <table class="table table-striped">
+            <thead>
+              <tr>
+                <th scope="col">#</th>
+                <th scope="col">Услуга</th>
+                <th scope="col">Цена</th>
+              </tr>
+            </thead>
+            <tbody>
+              <tr>
+                <th scope="row">1</th>
+                <td>Lorem ipsum dolor sit amet.</td>
+                <td>Lorem, ipsum.</td>
+              </tr>
+              <tr>
+                <th scope="row">2</th>
+                <td>Lorem ipsum dolor sit amet.</td>
+                <td>Lorem, ipsum.</td>
+              </tr>
+              <tr>
+                <th scope="row">3</th>
+                <td>Lorem ipsum dolor sit amet.</td>
+                <td>Lorem, ipsum.</td>
+              </tr>
+              <tr>
+                <th scope="row">4</th>
+                <td>Lorem ipsum dolor sit amet.</td>
+                <td>Lorem, ipsum.</td>
+              </tr>
+              <tr>
+                <th scope="row">5</th>
+                <td>Lorem ipsum dolor sit amet.</td>
+                <td>Lorem, ipsum.</td>
+              </tr>
+              <tr>
+                <th scope="row">6</th>
+                <td>Lorem ipsum dolor sit amet.</td>
+                <td>Lorem, ipsum.</td>
+              </tr>
+            </tbody>
+          </table>
+        {% include 'butler/ser_btn.html' %}
+        
+    </div>
+</div>
+{% endblock %}

+ 15 - 0
butler/templates/butler/pages/simple.html

@@ -0,0 +1,15 @@
+{% extends 'butler/index.html' %}
+{% load static %} 
+{% block container %}
+
+<div class="row" style="min-height: 500px;">
+    
+    <div class="col-12 col-sm-6 col-md-5 col-lg-4 col-xxl-3 order-1 order-md-0">
+        {% include 'butler/menu.html' %}
+    </div>
+
+    <div class="col-12 col-sm-6 col-md-7 col-lg-8 col-xxl-9 order-0 order-md-1" style="overflow-wrap: break-word;">
+        {{ mainpage.content|safe }}
+    </div>
+</div>
+{% endblock %}

+ 7 - 0
butler/templates/butler/ser_btn.html

@@ -0,0 +1,7 @@
+{% load static %} 
+<a href="{% url 'order' %}">
+    <div style="float: right; width: 120px; height: auto; transform: rotate(5deg); cursor: pointer;">
+        <span style="position:relative; right: -30px; top: 75px; color: white; font-size: 18px; font-family: Lobster; ">Заказать</span>
+        <img src="{% static 'butler/img/orderimg.png' %}"  alt="">
+    </div>
+</a>

+ 3 - 0
butler/tests.py

@@ -0,0 +1,3 @@
+from django.test import TestCase
+
+# Create your tests here.

+ 28 - 0
butler/urls.py

@@ -0,0 +1,28 @@
+from django.urls import path, include
+from .views import *
+
+urlpatterns = [
+    
+    #path('', include('django.contrib.flatpages.urls')),
+    path('', index_html, name='main'),
+    path('order/', order_html, name='order'),
+    path('faq/', faq_html, name='faq'),
+    path('price/', price_html, name='price'),
+    path('contact/', contact_html, name='contact'),
+    #pages
+    path('clean-car/', page_html, name='clean-car'),
+    path('clean-fit/', page_html, name='clean-fit'),
+    path('clean-office/', page_html, name='clean-office'),
+    path('clean-tcj/', page_html, name='clean-tcj'),
+    path('clean-area/', page_html, name='clean-area'),
+    path('clean-facades/', page_html, name='clean-facades'),
+    path('clean-apartments/', page_html, name='clean-apartments'),
+    path('clean-cottages/', page_html, name='clean-cottages'),
+    path('clean-out/', page_html, name='clean-out'),
+    path('clean-renovation/', page_html, name='clean-renovation'),
+
+    #path('services/<str:page>/', services_html, name="services"),
+    #path('', views.flatpage, {'url': ''}, name='about'),
+    #path('test/', views.flatpage, {'url': '/test/'}, name='test'),
+]
+

+ 27 - 0
butler/utils.py

@@ -0,0 +1,27 @@
+from butler.models import ButlerPage
+
+
+
+def create_pages_clean():
+    if not ButlerPage.objects.filter(slug='order'):
+        ButlerPage.objects.create(title="Главная", slug="main", content="")
+        ButlerPage.objects.create(title="Заказ онлайн", slug="order", content="")
+        ButlerPage.objects.create(title="FAQ", slug="faq", content="")
+        ButlerPage.objects.create(title="Цены", slug="price", content="")
+        ButlerPage.objects.create(title="Контакты", slug="contact", content="")
+    if not ButlerPage.objects.filter(slug__startswith="clean"):
+        ButlerPage.objects.create(title="Уборка автосалонов", slug="clean-car", content="")
+        ButlerPage.objects.create(title="Уборка фитнес клубов", slug="clean-fit", content="")
+        ButlerPage.objects.create(title="Уборка офисов, ТЦ и БЦ", slug="clean-office", content="")
+        ButlerPage.objects.create(title="Уборка ТСЖ", slug="clean-tcj", content="")
+        ButlerPage.objects.create(title="Уборка прилегающей территории", slug="clean-area", content="")
+        ButlerPage.objects.create(title="Мойка фасадов и остекления", slug="clean-facades", content="")
+        ButlerPage.objects.create(title="Комплексная уборка квартир", slug="clean-apartments", content="")
+        ButlerPage.objects.create(title="Комплексная уборка коттеджей", slug="clean-cottages", content="")
+        ButlerPage.objects.create(title="Генеральная уборка", slug="clean-out", content="")
+        ButlerPage.objects.create(title="Уборка после ремонта", slug="clean-renovation", content="")
+
+def create_pages_clean_admin(modeladmin, request, queryset):
+    create_pages_clean()
+
+create_pages_clean_admin.short_description = "Созадть страницы по умолчанию"

+ 136 - 0
butler/views.py

@@ -0,0 +1,136 @@
+from django.shortcuts import render
+from django.http import HttpResponseRedirect
+from .models import *
+from butler.forms import *
+# Create your views here.
+from django.core.mail import EmailMessage, get_connection
+import core.config_template as settings
+
+
+def send_email_mess(body, sub):
+    with get_connection(  
+        host=settings.EMAIL_HOST, 
+        port=settings.EMAIL_PORT,  
+        username=settings.EMAIL_HOST_USER, 
+        password=settings.EMAIL_HOST_PASSWORD, 
+        use_tls=settings.EMAIL_USE_TLS,
+        use_ssl=settings.EMAIL_USE_SSL
+        ) as connection:
+        #print(form.cleaned_data)
+        subject = sub  
+        email_from = settings.EMAIL_HOST_USER  
+        recipient_list = [settings.EMAIL_TO]  
+        message = body 
+        EmailMessage(subject, message, email_from, recipient_list, connection=connection).send() 
+
+def index_html(request):
+    if request.POST:
+        form = MyForm(request.POST)
+        if form.is_valid():
+            body = f"""
+            Имя: {form.cleaned_data['name']}\n
+            Email: {form.cleaned_data['email']}\n
+            Комментарий: {form.cleaned_data['message']}
+            """
+            send_email_mess(body, "Пользователь оставил отзыв")
+    else:
+        form = MyForm()
+
+    menu = ButlerPage.objects.filter(slug__startswith='clean')
+    context = {
+        # "mainpage":ButlerPage.objects.get(slug="main"),
+        "menu":menu,
+        "form":form
+    }
+    return render(request, 'butler/pages/main.html', context=context)
+
+
+
+def page_html(request):
+    if request.POST:
+        form = MyForm(request.POST)
+        if form.is_valid():
+            print(form.cleaned_data)
+    else:
+        form = MyForm()
+    slug = (request.path[1:-1])
+    if not ButlerPage.objects.filter(slug=slug):
+        menu = ButlerPage.objects.filter(slug__startswith='clean')
+        print(menu)
+        if not ButlerPage.objects.filter(slug__startswith='clean'):
+            menu = ButlerPage.objects.filter(slug__startswith='clean')
+            context = {
+                "form":form
+            }
+        else:
+            context = {
+                "form":form,
+                "menu":menu
+            }
+        return render(request, 'butler/pages/in_work.html', context=context)
+    else:
+        menu = ButlerPage.objects.filter(slug__startswith='clean')
+        print(menu)
+        context = {
+            "mainpage":ButlerPage.objects.get(slug=slug),
+            "form":form,
+            "menu":menu
+        }
+        return render(request, 'butler/pages/simple.html', context=context)
+
+def send_email(request):
+    if request.method == 'POST':
+        print(request.POST['email'])
+    
+    return HttpResponseRedirect('/')
+
+#simple page
+def contact_html(request):
+    return render(request, 'butler/pages/contact.html')
+
+def price_html(request):
+    return render(request, 'butler/pages/price.html')
+
+def order_html(request):
+    if request.POST:
+        form = OrderForm(request.POST)
+        if form.is_valid():
+            services = ""
+            for item in form.cleaned_data['service']:
+                services += f"{SERVICE_CHOICES[int(item)][1]}, " 
+            body = f"""
+            Имя: {form.cleaned_data['name']}\n
+            Фамилия: {form.cleaned_data['surname']}\n
+            Номер телефона: {form.cleaned_data['phone']}\n
+            Выбранные услуги: {services}\n
+            Желаемое время оказания услуги: {form.cleaned_data['datetime']}\n
+            Комментарий: {form.cleaned_data['comment'] or "Комментарий отсутствует"}
+            """
+            send_email_mess(body, "ЗАКАЗ")
+    else:
+        form = OrderForm()
+    context = {
+            "form":form
+        }
+    return render(request, 'butler/pages/order.html', context)
+
+def faq_html(request):
+    if request.POST:
+        form = MyForm(request.POST)
+        if form.is_valid():
+            body = f"""
+            Имя: {form.cleaned_data['name']}\n
+            Email: {form.cleaned_data['email']}\n
+            Вопрос: {form.cleaned_data['message']}
+            """
+            send_email_mess(body, "Пользователь задал вопрос")
+    else:
+        form = MyForm()
+    context = {
+            "form":form,
+            "faq":FAQmodel.objects.all()
+        }
+    return render(request, 'butler/pages/faq.html', context)
+
+
+

+ 0 - 0
core/__init__.py


+ 16 - 0
core/asgi.py

@@ -0,0 +1,16 @@
+"""
+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/4.1/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()

+ 9 - 0
core/conf_gunicorn.py

@@ -0,0 +1,9 @@
+#bind = "0.0.0.0:8001"
+import core.config_template as conf
+bind = conf.BIND
+workers = conf.WORKERS
+worker_class = "sync"
+threads = conf.THREADS
+timeout = 30
+max_requests = 1000
+capture_output = True

+ 39 - 0
core/config_template.py

@@ -0,0 +1,39 @@
+#Create file config.py with this setting or rename this file to config.py
+
+#BASE
+DEBUG=True
+SECRET_KEY='secret-key(absolutely any character)'
+ALLOWED_HOSTS = ['127.0.0.1']
+CSRF_TRUSTED_ORIGINS = []
+
+#DATABSE
+DB_NAME=None
+DB_USER=None
+DB_PASSWORD=None
+DB_HOST=None
+
+#GUNICORN
+BIND = "127.0.0.1:8000"
+WORKERS = 1
+THREADS = 2
+
+#EMAIL SETTINGS
+EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
+EMAIL_HOST = 'mail.sharix-app.org'
+EMAIL_USE_TLS = False
+EMAIL_PORT = 465
+EMAIL_USE_SSL = True
+EMAIL_HOST_USER = 'example@sharix-app.org'
+EMAIL_HOST_PASSWORD = '**************'
+EMAIL_TO = 'example@sharix-app.org'
+
+#STATIC
+from pathlib import Path
+import os
+BASE_DIR = Path(__file__).resolve().parent.parent
+STATIC_URL = '/static/'
+STATICFILES_DIRS = [BASE_DIR / "butler/static/"]
+STATIC_ROOT = os.path.join(BASE_DIR, "staticfiles")
+
+MEDIA_ROOT = os.path.join(BASE_DIR, "media")
+MEDIA_URL = "/media/"

+ 154 - 0
core/settings.py

@@ -0,0 +1,154 @@
+"""
+Django settings for core project.
+
+Generated by 'django-admin startproject' using Django 4.1.5.
+
+For more information on this file, see
+https://docs.djangoproject.com/en/4.1/topics/settings/
+
+For the full list of settings and their values, see
+https://docs.djangoproject.com/en/4.1/ref/settings/
+"""
+
+from pathlib import Path
+import core.config_template as conf
+import os
+# 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/4.1/howto/deployment/checklist/
+
+# SECURITY WARNING: keep the secret key used in production secret!
+SECRET_KEY = conf.SECRET_KEY
+
+# SECURITY WARNING: don't run with debug turned on in production!
+DEBUG = conf.DEBUG
+
+ALLOWED_HOSTS = conf.ALLOWED_HOSTS
+CSRF_TRUSTED_ORIGINS = conf.CSRF_TRUSTED_ORIGINS
+
+# Application definition
+
+INSTALLED_APPS = [
+    'django.contrib.admin',
+    'django.contrib.auth',
+    'django.contrib.contenttypes',
+    'django.contrib.sessions',
+    'django.contrib.messages',
+    'django.contrib.staticfiles',
+    'butler.apps.ButlerConfig',
+    'ckeditor',
+    #antispam
+    'captcha',
+]
+
+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/4.1/ref/settings/#databases
+
+if conf.DB_NAME is None:
+    DATABASES = {
+        'default': {
+            'ENGINE': 'django.db.backends.sqlite3',
+            'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
+        }
+    }
+else:
+    DATABASES = {
+        'default': {
+            'ENGINE': 'django.db.backends.postgresql',
+            'NAME': conf.DB_NAME,
+            'USER': conf.DB_USER,
+            'PASSWORD': conf.DB_PASSWORD,
+            'HOST': conf.DB_HOST,
+            'PORT': '5432',
+        }
+    }
+
+
+# Password validation
+# https://docs.djangoproject.com/en/4.1/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/4.1/topics/i18n/
+
+LANGUAGE_CODE = 'ru'
+
+TIME_ZONE = 'UTC'
+
+USE_I18N = True
+
+USE_TZ = True
+
+
+# Static files (CSS, JavaScript, Images)
+# https://docs.djangoproject.com/en/4.1/howto/static-files/
+
+STATIC_URL = '/static/'
+STATICFILES_DIRS = [os.path.join(BASE_DIR, "core", "static", "/static/")]
+STATIC_ROOT = os.path.join(BASE_DIR, "staticfiles")
+
+MEDIA_ROOT = os.path.join(BASE_DIR, "media")
+MEDIA_URL = "/media/"
+
+#CKEDITOR_BASEPATH = "/staticfiles/ckeditor/ckeditor/"
+CKEDITOR_CONFIGS = {
+    'default': {
+        'toolbar': 'full',
+    },
+}
+# Default primary key field type
+# https://docs.djangoproject.com/en/4.1/ref/settings/#default-auto-field
+
+DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
+
+#SITE_ID = 1
+

+ 30 - 0
core/urls.py

@@ -0,0 +1,30 @@
+"""core URL Configuration
+
+The `urlpatterns` list routes URLs to views. For more information please see:
+    https://docs.djangoproject.com/en/4.1/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
+
+urlpatterns = (
+    [
+    path('admin/', admin.site.urls),
+    path('', include('butler.urls')),
+    path('captcha/', include('captcha.urls')),
+    #path('pages/', include('django.contrib.flatpages.urls')),
+]
++ static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
++ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
+)

+ 16 - 0
core/wsgi.py

@@ -0,0 +1,16 @@
+"""
+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/4.1/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()

Datei-Diff unterdrückt, da er zu groß ist
+ 67 - 0
dumpdb.sql


+ 18 - 0
install.sh

@@ -0,0 +1,18 @@
+#bush install.sh
+python3 -m venv env
+
+source env/bin/activate
+
+python3 -m pip install -U pip
+
+pip install -r requirements.txt
+
+python3 manage.py makemigrations
+
+python3 manage.py migrate
+
+python3 manage.py collectstatic
+
+python3 manage.py createsuperuser
+
+deactivate

+ 22 - 0
manage.py

@@ -0,0 +1,22 @@
+#!/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()

BIN
pages_pdf/main.pdf


+ 16 - 0
requirements.txt

@@ -0,0 +1,16 @@
+asgiref==3.6.0
+certifi==2022.12.7
+charset-normalizer==3.1.0
+Django==4.1.7
+django-ckeditor==6.5.1
+django-js-asset==2.0.0
+django-ranged-response==0.2.0
+django-simple-captcha==0.5.17
+gunicorn==20.1.0
+idna==3.4
+Pillow==9.5.0
+python-akismet==0.4.3
+requests==2.28.2
+sqlparse==0.4.3
+tzdata==2022.7
+urllib3==1.26.15

Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden.