gr421_isghdo 1 سال پیش
کامیت
13e6de1d04

+ 0 - 0
app/__init__.py


+ 9 - 0
app/admin.py

@@ -0,0 +1,9 @@
+from django.contrib import admin
+
+from .models import *
+
+# Register your models here.
+
+admin.site.register(CustomUser)
+admin.site.register(Product)
+admin.site.register(Order)

+ 6 - 0
app/apps.py

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

+ 15 - 0
app/forms.py

@@ -0,0 +1,15 @@
+from django import forms
+from .models import *
+
+
+class RegistrationForm(forms.ModelForm):
+    class Meta:
+        model = CustomUser
+        fields = ['username', 'first_name', 'last_name', 'email', 'password', 'photo_profile']
+
+    def save(self, commit=True):
+        user = super(RegistrationForm, self).save(commit=False)
+        user.set_password(self.cleaned_data['password'])
+        if commit:
+            user.save()
+        return user

+ 140 - 0
app/migrations/0001_initial.py

@@ -0,0 +1,140 @@
+# Generated by Django 4.2.8 on 2023-12-26 04:35
+
+import django.contrib.auth.models
+from django.db import migrations, models
+import django.utils.timezone
+
+
+class Migration(migrations.Migration):
+    initial = True
+
+    dependencies = [
+        ("auth", "0012_alter_user_first_name_max_length"),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name="Product",
+            fields=[
+                (
+                    "id",
+                    models.BigAutoField(
+                        auto_created=True,
+                        primary_key=True,
+                        serialize=False,
+                        verbose_name="ID",
+                    ),
+                ),
+                ("name", models.CharField(max_length=50)),
+                ("desc", models.TextField(max_length=100)),
+                (
+                    "photo_product",
+                    models.ImageField(upload_to="media/", verbose_name="photo_product"),
+                ),
+            ],
+        ),
+        migrations.CreateModel(
+            name="CustomUser",
+            fields=[
+                (
+                    "id",
+                    models.BigAutoField(
+                        auto_created=True,
+                        primary_key=True,
+                        serialize=False,
+                        verbose_name="ID",
+                    ),
+                ),
+                ("password", models.CharField(max_length=128, verbose_name="password")),
+                (
+                    "last_login",
+                    models.DateTimeField(
+                        blank=True, null=True, verbose_name="last login"
+                    ),
+                ),
+                (
+                    "is_superuser",
+                    models.BooleanField(
+                        default=False,
+                        help_text="Designates that this user has all permissions without explicitly assigning them.",
+                        verbose_name="superuser status",
+                    ),
+                ),
+                (
+                    "first_name",
+                    models.CharField(
+                        blank=True, max_length=150, verbose_name="first name"
+                    ),
+                ),
+                (
+                    "last_name",
+                    models.CharField(
+                        blank=True, max_length=150, verbose_name="last name"
+                    ),
+                ),
+                (
+                    "email",
+                    models.EmailField(
+                        blank=True, max_length=254, verbose_name="email address"
+                    ),
+                ),
+                (
+                    "is_staff",
+                    models.BooleanField(
+                        default=False,
+                        help_text="Designates whether the user can log into this admin site.",
+                        verbose_name="staff status",
+                    ),
+                ),
+                (
+                    "is_active",
+                    models.BooleanField(
+                        default=True,
+                        help_text="Designates whether this user should be treated as active. Unselect this instead of deleting accounts.",
+                        verbose_name="active",
+                    ),
+                ),
+                (
+                    "date_joined",
+                    models.DateTimeField(
+                        default=django.utils.timezone.now, verbose_name="date joined"
+                    ),
+                ),
+                ("username", models.CharField(blank=True, max_length=11, unique=True)),
+                (
+                    "photo_profile",
+                    models.ImageField(upload_to="media/", verbose_name="photo_profile"),
+                ),
+                (
+                    "groups",
+                    models.ManyToManyField(
+                        blank=True,
+                        help_text="The groups this user belongs to. A user will get all permissions granted to each of their groups.",
+                        related_name="user_set",
+                        related_query_name="user",
+                        to="auth.group",
+                        verbose_name="groups",
+                    ),
+                ),
+                (
+                    "user_permissions",
+                    models.ManyToManyField(
+                        blank=True,
+                        help_text="Specific permissions for this user.",
+                        related_name="user_set",
+                        related_query_name="user",
+                        to="auth.permission",
+                        verbose_name="user permissions",
+                    ),
+                ),
+            ],
+            options={
+                "verbose_name": "user",
+                "verbose_name_plural": "users",
+                "abstract": False,
+            },
+            managers=[
+                ("objects", django.contrib.auth.models.UserManager()),
+            ],
+        ),
+    ]

+ 42 - 0
app/migrations/0002_order.py

@@ -0,0 +1,42 @@
+# Generated by Django 4.2.8 on 2023-12-26 04:58
+
+from django.conf import settings
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+    dependencies = [
+        ("app", "0001_initial"),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name="Order",
+            fields=[
+                (
+                    "id",
+                    models.BigAutoField(
+                        auto_created=True,
+                        primary_key=True,
+                        serialize=False,
+                        verbose_name="ID",
+                    ),
+                ),
+                ("created_at", models.DateTimeField(auto_now_add=True)),
+                (
+                    "product",
+                    models.ForeignKey(
+                        on_delete=django.db.models.deletion.CASCADE, to="app.product"
+                    ),
+                ),
+                (
+                    "user",
+                    models.ForeignKey(
+                        on_delete=django.db.models.deletion.CASCADE,
+                        to=settings.AUTH_USER_MODEL,
+                    ),
+                ),
+            ],
+        ),
+    ]

+ 0 - 0
app/migrations/__init__.py


+ 21 - 0
app/models.py

@@ -0,0 +1,21 @@
+from django.contrib.auth.models import AbstractUser
+from django.db import models
+
+# Create your models here.
+
+
+class CustomUser(AbstractUser):
+    username = models.CharField(max_length=11, blank=True, unique=True)
+    photo_profile = models.ImageField(upload_to='media/', verbose_name='photo_profile')
+
+
+class Product(models.Model):
+    name = models.CharField(max_length=50)
+    desc = models.TextField(max_length=100)
+    photo_product = models.ImageField(upload_to='media/', verbose_name='photo_product')
+
+
+class Order(models.Model):
+    user = models.ForeignKey(CustomUser, on_delete=models.CASCADE)
+    product = models.ForeignKey(Product, on_delete=models.CASCADE)
+    created_at = models.DateTimeField(auto_now_add=True)

+ 61 - 0
app/templates/base.html

@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <title>Магазин</title>
+    <script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
+    <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-Fy6S3B9q64WdZWQUiU+q4/2Lc9npb8tCaSX9FK7E8HnRr0Jz8D6OP9dO5Vg3Q9ct" crossorigin="anonymous"></script>
+    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css" integrity="sha384-xOolHFLEh07PJGoPkLv1IbcEPTNtaed2xpHsD9ESMhqIYd0nLMwNLD69Npy4HI+N" crossorigin="anonymous">
+</head>
+<body>
+<nav class="navbar navbar-expand-lg navbar-light bg-light">
+  <a class="navbar-brand" href="{% url 'base' %}">Магазинчик</a>
+  <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
+    <span class="navbar-toggler-icon"></span>
+  </button>
+
+  <div class="collapse navbar-collapse" id="navbarSupportedContent">
+    <ul class="navbar-nav mr-auto">
+      <li class="nav-item">
+        <a class="nav-link" href="{% url 'service' %}" >Товары</a>
+      </li>
+        {% if user.is_authenticated%}
+            <li class="nav-item">
+            <a class="nav-link" href="{% url 'profile' %}">Профиль</a>
+            </li>
+            <li class="nav-item">
+        <a class="nav-link" href="{% url 'logout' %}">Выход</a>
+            </li>
+        {% else %}
+
+             <li class="nav-item">
+        <a class="nav-link" href="{% url 'login' %}">Вход</a>
+            </li>
+             <li class="nav-item">
+        <a class="nav-link" href="{% url 'register' %}">Регистрация</a>
+            </li>
+        {% endif %}
+    </ul>
+
+  </div>
+</nav>
+{% block content %}
+<div class="jumbotron jumbotron-fluid">
+  <div class="container">
+    <h1 class="display-4">Новые товары</h1>
+    <div class="card" style="width: 18rem;">
+    {% for product in product %}
+        {% if product.photo_product %}
+      <img src="{{  product.photo_product.url }}" class="card-img-top" alt="...">
+        {% endif %}
+      <div class="card-body">
+        <h5 class="card-title"><a href="{% url 'detail' product.id %}">{{ product.name }}</a></h5>
+      </div>
+    {% endfor %}
+</div>
+  </div>
+</div>
+
+{% endblock %}
+</body>
+</html>

+ 21 - 0
app/templates/detail_product.html

@@ -0,0 +1,21 @@
+{% extends 'base.html' %}
+{% block content %}
+<div class="jumbotron jumbotron-fluid">
+  <div class="container">
+    <h1 class="display-4">О товаре</h1>
+    <div class="card" style="width: 18rem;">
+
+        {% if product.photo_product %}
+      <img src="{{  product.photo_product.url }}" class="card-img-top" alt="...">
+        {% endif %}
+      <div class="card-body">
+        <h5 class="card-title">{{ product.name }}</h5>
+          <p class="card-text">{{ product.desc }}</p>
+            <input type="submit" value="Заказать">
+      </div>
+
+</div>
+  </div>
+</div>
+
+{% endblock %}

+ 41 - 0
app/templates/profile.html

@@ -0,0 +1,41 @@
+{% extends 'base.html' %}
+{% block content %}
+<div class="jumbotron jumbotron-fluid">
+  <div class="container">
+
+    <h1 class="display-4">Профиль пользователя {{ user.username }}</h1>
+    <div class="card mb-3" style="max-width: 540px;">
+  <div class="row no-gutters">
+    <div class="col-md-4">
+     {% if user.photo_profile %}
+      <img src="{{  user.photo_profile.url }}" class="card-img-top" alt="...">
+        {% endif %}
+    </div>
+    <div class="col-md-8">
+      <div class="card-body">
+
+        <p class="card-text">{{ user.first_name }}</p>
+          <p class="card-text">{{ user.last_name }}</p>
+          <p class="card-text">{{ user.email }}</p>
+
+      </div>
+    </div>
+  </div>
+</div>
+  <h1 class="display-4">Мои заказы</h1>
+    <div class="card" style="width: 18rem;">
+    {% for i in products %}
+        {% if i.product.photo_product %}
+      <img src="{{  i.product.photo_product.url }}" class="card-img-top" alt="...">
+        {% endif %}
+      <div class="card-body">
+        <h5 class="card-title"><a href="{% url 'detail' i.product.id %}">{{ i.product.name }}</a></h5>
+      </div>
+    {% endfor %}
+  </div>
+
+
+  </div>
+</div>
+
+{% endblock %}

+ 15 - 0
app/templates/registration/login.html

@@ -0,0 +1,15 @@
+
+{% extends 'base.html' %}
+{% block content %}
+<div class="jumbotron jumbotron-fluid">
+  <div class="container">
+    <h1 class="display-4">Вход</h1>
+    <form  method="post">
+        {% csrf_token %}
+        {{ form.as_p }}
+        <input type="submit" value="Войти">
+    </form>
+  </div>
+</div>
+
+{% endblock %}

+ 10 - 0
app/templates/registration/logout.html

@@ -0,0 +1,10 @@
+{% extends 'base.html' %}
+{% block content %}
+<div class="jumbotron jumbotron-fluid">
+  <div class="container">
+    <h1 class="display-4">Вы вышли!</h1>
+
+  </div>
+</div>
+
+{% endblock %}

+ 14 - 0
app/templates/registration/register.html

@@ -0,0 +1,14 @@
+{% extends 'base.html' %}
+{% block content %}
+<div class="jumbotron jumbotron-fluid">
+  <div class="container">
+    <h1 class="display-4">Регистрация</h1>
+    <form  method="post" enctype="multipart/form-data">
+        {% csrf_token %}
+        {{ form.as_p }}
+        <input type="submit" value="Войти">
+    </form>
+  </div>
+</div>
+
+{% endblock %}

+ 19 - 0
app/templates/service.html

@@ -0,0 +1,19 @@
+{% extends 'base.html' %}
+{% block content %}
+<div class="jumbotron jumbotron-fluid">
+  <div class="container">
+    <h1 class="display-4">Наши товары</h1>
+    <div class="card" style="width: 18rem;">
+    {% for i in products %}
+        {% if i.photo_product %}
+      <img src="{{  i.photo_product.url }}" class="card-img-top" alt="...">
+        {% endif %}
+      <div class="card-body">
+        <h5 class="card-title"><a href="{% url 'detail' i.id %}">{{ i.name }}</a></h5>
+      </div>
+    {% endfor %}
+</div>
+  </div>
+</div>
+
+{% endblock %}

+ 3 - 0
app/tests.py

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

+ 18 - 0
app/urls.py

@@ -0,0 +1,18 @@
+from django.urls import path
+
+from django.conf import settings
+from django.conf.urls.static import static
+
+from .views import *
+
+urlpatterns = [
+    path('', HomePageView.as_view(), name='base'),
+    path('login/', LoginUserView.as_view(), name='login'),
+    path('logout/', LogoutUserView.as_view(), name='logout'),
+    path('service/', ProductListView.as_view(), name='service'),
+    path('<int:pk>/service/', ProductDetailView.as_view(), name='detail'),
+    path('accounts/profile/', ProfileListView.as_view(), name='profile'),
+    path('accounts/register/', RegistrationListView.as_view(), name='register'),
+
+
+] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

+ 61 - 0
app/views.py

@@ -0,0 +1,61 @@
+from django.contrib.auth.decorators import login_required
+from django.contrib.auth.mixins import LoginRequiredMixin
+from django.contrib.auth.models import User
+from django.contrib.auth.views import LogoutView, LoginView
+from django.http import HttpResponseRedirect
+from django.shortcuts import render
+from django.urls import reverse_lazy
+from django.views.generic import TemplateView, ListView, DetailView, CreateView
+
+from .forms import RegistrationForm
+from .models import *
+
+# Create your views here.
+
+
+class HomePageView(ListView):
+    template_name = 'base.html'
+    context_object_name = 'product'
+    model = Product
+
+    def get_queryset(self):
+        return Product.objects.all()[:5]
+
+
+class LogoutUserView(LoginRequiredMixin, LogoutView):
+    template_name = 'registration/logout.html'
+    success_url = reverse_lazy('base')
+
+
+class LoginUserView(LoginView):
+    template_name = 'registration/login.html'
+    success_url = reverse_lazy('profile')
+
+
+class ProductListView(ListView):
+    model = Product
+    template_name = 'service.html'
+    context_object_name = 'products'
+
+
+class ProductDetailView(DetailView):
+    model = Product
+    template_name = 'detail_product.html'
+
+
+class RegistrationListView(CreateView):
+    model = CustomUser
+    form_class = RegistrationForm
+    success_url = reverse_lazy('login')
+    template_name = 'registration/register.html'
+
+
+class ProfileListView(ListView):
+    model = Order
+    context_object_name = 'profile'
+    template_name = 'profile.html'
+
+    def get_queryset(self):
+        return Order.objects.filter(user=self.request.user)
+
+

BIN
db.sqlite3


+ 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", "project.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
media/the-cat-on-the-grass-shows-his-tongue.jpg


BIN
media/the-cat-on-the-grass-shows-his-tongue_BdzIY6o.jpg


BIN
media/the-cat-on-the-grass-shows-his-tongue_C5lgPx7.jpg


BIN
media/the-cat-on-the-grass-shows-his-tongue_Cxxncyj.jpg


BIN
media/the-cat-on-the-grass-shows-his-tongue_HIisSmC.jpg


BIN
media/the-cat-on-the-grass-shows-his-tongue_aDKl3C7.jpg


BIN
media/the-cat-on-the-grass-shows-his-tongue_jWBlKcz.jpg


+ 0 - 0
project/__init__.py


+ 16 - 0
project/asgi.py

@@ -0,0 +1,16 @@
+"""
+ASGI config for project 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.2/howto/deployment/asgi/
+"""
+
+import os
+
+from django.core.asgi import get_asgi_application
+
+os.environ.setdefault("DJANGO_SETTINGS_MODULE", "project.settings")
+
+application = get_asgi_application()

+ 126 - 0
project/settings.py

@@ -0,0 +1,126 @@
+"""
+Django settings for project project.
+
+Generated by 'django-admin startproject' using Django 4.2.8.
+
+For more information on this file, see
+https://docs.djangoproject.com/en/4.2/topics/settings/
+
+For the full list of settings and their values, see
+https://docs.djangoproject.com/en/4.2/ref/settings/
+"""
+
+from pathlib import Path
+
+# Build paths inside the project like this: BASE_DIR / 'subdir'.
+BASE_DIR = Path(__file__).resolve().parent.parent
+
+
+# Quick-start development settings - unsuitable for production
+# See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/
+
+# SECURITY WARNING: keep the secret key used in production secret!
+SECRET_KEY = "django-insecure-!m^82byju7=_5jy&_lk8kf_h%de)!4()z4@17qd&g_uqf_vyv8"
+
+# SECURITY WARNING: don't run with debug turned on in production!
+DEBUG = True
+
+ALLOWED_HOSTS = []
+
+
+# Application definition
+
+INSTALLED_APPS = [
+    'app',
+    'bootstrap4',
+    "django.contrib.admin",
+    "django.contrib.auth",
+    "django.contrib.contenttypes",
+    "django.contrib.sessions",
+    "django.contrib.messages",
+    "django.contrib.staticfiles",
+]
+
+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 = "project.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 = "project.wsgi.application"
+
+
+# Database
+# https://docs.djangoproject.com/en/4.2/ref/settings/#databases
+
+DATABASES = {
+    "default": {
+        "ENGINE": "django.db.backends.sqlite3",
+        "NAME": BASE_DIR / "db.sqlite3",
+    }
+}
+
+
+# Password validation
+# https://docs.djangoproject.com/en/4.2/ref/settings/#auth-password-validators
+
+AUTH_PASSWORD_VALIDATORS = [
+    {
+        "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
+    },
+    {
+        "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",
+    },
+    {
+        "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",
+    },
+    {
+        "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",
+    },
+]
+
+
+# Internationalization
+# https://docs.djangoproject.com/en/4.2/topics/i18n/
+
+LANGUAGE_CODE = "en-us"
+
+TIME_ZONE = "UTC"
+
+USE_I18N = True
+
+USE_TZ = True
+
+
+# Static files (CSS, JavaScript, Images)
+# https://docs.djangoproject.com/en/4.2/howto/static-files/
+
+STATIC_URL = "static/"
+
+# Default primary key field type
+# https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field
+
+DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
+AUTH_USER_MODEL = "app.CustomUser"

+ 26 - 0
project/urls.py

@@ -0,0 +1,26 @@
+"""
+URL configuration for project project.
+
+The `urlpatterns` list routes URLs to views. For more information please see:
+    https://docs.djangoproject.com/en/4.2/topics/http/urls/
+Examples:
+Function views
+    1. Add an import:  from my_app import views
+    2. Add a URL to urlpatterns:  path('', views.home, name='home')
+Class-based views
+    1. Add an import:  from other_app.views import Home
+    2. Add a URL to urlpatterns:  path('', Home.as_view(), name='home')
+Including another URLconf
+    1. Import the include() function: from django.urls import include, path
+    2. Add a URL to urlpatterns:  path('blog/', include('blog.urls'))
+"""
+from django.contrib import admin
+from django.urls import path, include
+from django.conf import settings
+from django.conf.urls.static import static
+
+urlpatterns = [
+    path("admin/", admin.site.urls),
+    path('', include('app.urls')),
+]+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
+

+ 16 - 0
project/wsgi.py

@@ -0,0 +1,16 @@
+"""
+WSGI config for project 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.2/howto/deployment/wsgi/
+"""
+
+import os
+
+from django.core.wsgi import get_wsgi_application
+
+os.environ.setdefault("DJANGO_SETTINGS_MODULE", "project.settings")
+
+application = get_wsgi_application()