ew code-diff">
@@ -0,0 +1,49 @@
1
+# Generated by Django 3.2.5 on 2021-07-30 08:37
2
+
3
+from django.conf import settings
4
+from django.db import migrations, models
5
+import django.db.models.deletion
6
+import mptt.fields
7
+
8
+
9
+class Migration(migrations.Migration):
10
+
11
+    initial = True
12
+
13
+    dependencies = [
14
+        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
15
+    ]
16
+
17
+    operations = [
18
+        migrations.CreateModel(
19
+            name='PostCat',
20
+            fields=[
21
+                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
22
+                ('name', models.CharField(max_length=50, unique=True)),
23
+                ('lft', models.PositiveIntegerField(editable=False)),
24
+                ('rght', models.PositiveIntegerField(editable=False)),
25
+                ('tree_id', models.PositiveIntegerField(db_index=True, editable=False)),
26
+                ('level', models.PositiveIntegerField(editable=False)),
27
+                ('parent', mptt.fields.TreeForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='children', to='cms.postcat')),
28
+            ],
29
+            options={
30
+                'abstract': False,
31
+            },
32
+        ),
33
+        migrations.CreateModel(
34
+            name='Post',
35
+            fields=[
36
+                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
37
+                ('created_at', models.DateTimeField(auto_now_add=True, null=True)),
38
+                ('updated_at', models.DateTimeField(auto_now=True)),
39
+                ('title', models.CharField(max_length=200)),
40
+                ('body', models.TextField(blank=True, null=True)),
41
+                ('cat', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='cms.postcat')),
42
+                ('created_by', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='post_created', to=settings.AUTH_USER_MODEL)),
43
+                ('modified_by', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='post_modified', to=settings.AUTH_USER_MODEL)),
44
+            ],
45
+            options={
46
+                'abstract': False,
47
+            },
48
+        ),
49
+    ]

+ 36 - 0
app/cms/migrations/0002_auto_20210730_1541.py

@@ -0,0 +1,36 @@
1
+# Generated by Django 3.2.5 on 2021-07-30 08:41
2
+
3
+from django.conf import settings
4
+from django.db import migrations, models
5
+import django.db.models.deletion
6
+
7
+
8
+class Migration(migrations.Migration):
9
+
10
+    dependencies = [
11
+        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
12
+        ('cms', '0001_initial'),
13
+    ]
14
+
15
+    operations = [
16
+        migrations.AddField(
17
+            model_name='postcat',
18
+            name='created_at',
19
+            field=models.DateTimeField(auto_now_add=True, null=True),
20
+        ),
21
+        migrations.AddField(
22
+            model_name='postcat',
23
+            name='created_by',
24
+            field=models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='postcat_created', to=settings.AUTH_USER_MODEL),
25
+        ),
26
+        migrations.AddField(
27
+            model_name='postcat',
28
+            name='modified_by',
29
+            field=models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='postcat_modified', to=settings.AUTH_USER_MODEL),
30
+        ),
31
+        migrations.AddField(
32
+            model_name='postcat',
33
+            name='updated_at',
34
+            field=models.DateTimeField(auto_now=True),
35
+        ),
36
+    ]

+ 20 - 0
app/cms/migrations/0003_alter_post_body.py

@@ -0,0 +1,20 @@
1
+# Generated by Django 3.2.5 on 2021-08-01 06:18
2
+
3
+from django.db import migrations
4
+import django_quill.fields
5
+
6
+
7
+class Migration(migrations.Migration):
8
+
9
+    dependencies = [
10
+        ('cms', '0002_auto_20210730_1541'),
11
+    ]
12
+
13
+    operations = [
14
+        migrations.AlterField(
15
+            model_name='post',
16
+            name='body',
17
+            field=django_quill.fields.QuillField(default=None),
18
+            preserve_default=False,
19
+        ),
20
+    ]

+ 18 - 0
app/cms/migrations/0004_post_status.py

@@ -0,0 +1,18 @@
1
+# Generated by Django 3.2.5 on 2021-08-01 06:48
2
+
3
+from django.db import migrations, models
4
+
5
+
6
+class Migration(migrations.Migration):
7
+
8
+    dependencies = [
9
+        ('cms', '0003_alter_post_body'),
10
+    ]
11
+
12
+    operations = [
13
+        migrations.AddField(
14
+            model_name='post',
15
+            name='status',
16
+            field=models.CharField(choices=[('draft', 'Draft'), ('publish', 'Publish')], default='draft', max_length=30, null=True),
17
+        ),
18
+    ]

+ 18 - 0
app/cms/migrations/0005_post_feature_image.py

@@ -0,0 +1,18 @@
1
+# Generated by Django 3.2.5 on 2021-08-01 06:52
2
+
3
+from django.db import migrations, models
4
+
5
+
6
+class Migration(migrations.Migration):
7
+
8
+    dependencies = [
9
+        ('cms', '0004_post_status'),
10
+    ]
11
+
12
+    operations = [
13
+        migrations.AddField(
14
+            model_name='post',
15
+            name='feature_image',
16
+            field=models.ImageField(blank=True, null=True, upload_to='uploads/%Y/%m/%d/'),
17
+        ),
18
+    ]

+ 20 - 0
app/cms/migrations/0006_post_tags.py

@@ -0,0 +1,20 @@
1
+# Generated by Django 3.2.5 on 2021-08-01 07:34
2
+
3
+from django.db import migrations
4
+import taggit.managers
5
+
6
+
7
+class Migration(migrations.Migration):
8
+
9
+    dependencies = [
10
+        ('taggit', '0003_taggeditem_add_unique_index'),
11
+        ('cms', '0005_post_feature_image'),
12
+    ]
13
+
14
+    operations = [
15
+        migrations.AddField(
16
+            model_name='post',
17
+            name='tags',
18
+            field=taggit.managers.TaggableManager(help_text='A comma-separated list of tags.', through='taggit.TaggedItem', to='taggit.Tag', verbose_name='Tags'),
19
+        ),
20
+    ]

+ 32 - 0
app/cms/migrations/0007_postphoto.py

@@ -0,0 +1,32 @@
1
+# Generated by Django 3.2.5 on 2021-08-01 07:48
2
+
3
+from django.conf import settings
4
+from django.db import migrations, models
5
+import django.db.models.deletion
6
+
7
+
8
+class Migration(migrations.Migration):
9
+
10
+    dependencies = [
11
+        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
12
+        ('cms', '0006_post_tags'),
13
+    ]
14
+
15
+    operations = [
16
+        migrations.CreateModel(
17
+            name='PostPhoto',
18
+            fields=[
19
+                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
20
+                ('created_at', models.DateTimeField(auto_now_add=True, null=True)),
21
+                ('updated_at', models.DateTimeField(auto_now=True)),
22
+                ('name', models.CharField(max_length=200, unique=True)),
23
+                ('photo', models.ImageField(blank=True, upload_to='uploads/%Y/%m/%d/', verbose_name='Photo')),
24
+                ('created_by', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='postphoto_created', to=settings.AUTH_USER_MODEL)),
25
+                ('modified_by', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='postphoto_modified', to=settings.AUTH_USER_MODEL)),
26
+                ('product', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='cms.post')),
27
+            ],
28
+            options={
29
+                'abstract': False,
30
+            },
31
+        ),
32
+    ]

+ 18 - 0
app/cms/migrations/0008_rename_product_postphoto_post.py

@@ -0,0 +1,18 @@
1
+# Generated by Django 3.2.5 on 2021-08-01 07:54
2
+
3
+from django.db import migrations
4
+
5
+
6
+class Migration(migrations.Migration):
7
+
8
+    dependencies = [
9
+        ('cms', '0007_postphoto'),
10
+    ]
11
+
12
+    operations = [
13
+        migrations.RenameField(
14
+            model_name='postphoto',
15
+            old_name='product',
16
+            new_name='post',
17
+        ),
18
+    ]

+ 18 - 0
app/cms/migrations/0009_alter_postphoto_name.py

@@ -0,0 +1,18 @@
1
+# Generated by Django 3.2.5 on 2021-08-01 07:55
2
+
3
+from django.db import migrations, models
4
+
5
+
6
+class Migration(migrations.Migration):
7
+
8
+    dependencies = [
9
+        ('cms', '0008_rename_product_postphoto_post'),
10
+    ]
11
+
12
+    operations = [
13
+        migrations.AlterField(
14
+            model_name='postphoto',
15
+            name='name',
16
+            field=models.CharField(blank=True, max_length=200, null=True, unique=True),
17
+        ),
18
+    ]

+ 0 - 0
app/cms/migrations/__init__.py


+ 82 - 0
app/cms/models.py

@@ -0,0 +1,82 @@
1
+from django.db import models
2
+
3
+from django_google_maps import fields as map_fields
4
+from colorfield.fields import ColorField
5
+from smart_selects.db_fields import (
6
+    ChainedForeignKey,
7
+    ChainedManyToManyField,
8
+    GroupedForeignKey,
9
+)
10
+from django.db.models import Q
11
+import googlemaps
12
+from django.contrib.gis.geos import fromstr
13
+
14
+from django.conf import settings
15
+from mptt.models import MPTTModel, TreeForeignKey
16
+
17
+from django.contrib.auth.models import User
18
+from django.db.models.signals import post_save
19
+from django.dispatch import receiver
20
+from shaqfindbed.utils import get_current_user
21
+from django_quill.fields import QuillField
22
+
23
+from django.utils.html import escape, format_html
24
+from taggit.managers import TaggableManager
25
+# Create your models here.
26
+
27
+
28
+class GenericModel(models.Model):
29
+    created_at = models.DateTimeField(auto_now_add=True, null=True)
30
+    updated_at = models.DateTimeField(auto_now=True)
31
+
32
+    created_by = models.ForeignKey(User, null=True, editable=False, related_name='%(class)s_created', on_delete=models.SET_NULL)
33
+    modified_by = models.ForeignKey(User, null=True, editable=False, related_name='%(class)s_modified', on_delete=models.SET_NULL)
34
+
35
+    class Meta:
36
+        abstract = True
37
+
38
+class PostCat(GenericModel, MPTTModel):
39
+    name = models.CharField(max_length=50, unique=True)
40
+    parent = TreeForeignKey('self', on_delete=models.CASCADE, null=True, blank=True, related_name='children')
41
+
42
+    class MPTTMeta:
43
+        order_insertion_by = ['name']
44
+
45
+
46
+    def __str__(self):
47
+        return f"{self.name}"
48
+
49
+
50
+class Post(GenericModel, models.Model):
51
+    feature_image  = models.ImageField(upload_to="uploads/%Y/%m/%d/", blank=True,  null=True)
52
+    title = models.CharField(max_length=200)
53
+    body = QuillField()
54
+    #body = models.TextField(blank=True, null=True)
55
+    cat = models.ForeignKey('PostCat', on_delete=models.SET_NULL, null=True)
56
+    tags = TaggableManager()
57
+    status = models.CharField(
58
+        max_length=30,
59
+        choices=(("draft", "Draft"), ("publish", "Publish")),
60
+        default="draft",
61
+        null=True,
62
+    )
63
+
64
+    def image_tag(self):
65
+        return format_html('<img src="%s" width="300px"/>' % escape(self.feature_image.url))
66
+
67
+    image_tag.short_description = 'Image'
68
+    image_tag.allow_tags = True
69
+
70
+    def __str__(self):
71
+        return f"{self.title}"
72
+
73
+
74
+class PostPhoto(GenericModel, models.Model):
75
+    name = models.CharField(max_length=200, unique=True, blank=True, null=True)
76
+    photo  = models.ImageField(upload_to="uploads/%Y/%m/%d/", blank=True, verbose_name="Photo")
77
+    post = models.ForeignKey('Post', on_delete=models.CASCADE, null=True)
78
+
79
+    def image_tag(self):
80
+        return format_html('<img src="%s" width="300px"/>' % escape(self.photo.url))
81
+
82
+

+ 10 - 0
app/cms/templates/cms/index.html

@@ -0,0 +1,10 @@
1
+{% extends "front/base.html" %}
2
+
3
+{% block content %}
4
+<h1>Posts</h1>
5
+<ul>
6
+{% for p in posts %}
7
+<li><a href="{% url "view_post" post_id=p.id %}">{{ p.title }}</a></li>
8
+{% endfor %}
9
+</ul>
10
+{% endblock %}

+ 10 - 0
app/cms/templates/cms/post_tags.html

@@ -0,0 +1,10 @@
1
+{% extends "front/base.html" %}
2
+
3
+{% block content %}
4
+<h1>Posts</h1>
5
+<ul>
6
+{% for p in posts %}
7
+<li><a href="{% url "view_post" post_id=p.id %}">{{ p.title }}</a></li>
8
+{% endfor %}
9
+</ul>
10
+{% endblock %}

+ 8 - 0
app/cms/templates/cms/view.html

@@ -0,0 +1,8 @@
1
+{% extends "front/base.html" %}
2
+
3
+{% block content %}
4
+View HTML
5
+<h1>{{ post.title }}</h1>
6
+{{ post.body.html | safe }}
7
+{{ post_id }}
8
+{% endblock %}

+ 3 - 0
app/cms/tests.py

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

+ 9 - 0
app/cms/urls.py

@@ -0,0 +1,9 @@
1
+from django.urls import path
2
+from django.conf.urls import url
3
+from . import views
4
+
5
+urlpatterns = [
6
+    path('', views.index, name='index'),
7
+    path('post/<post_id>', views.post, name='view_post'),
8
+    path('tags/<tag>', views.post_tags, name='tags'),
9
+]

+ 14 - 0
app/cms/views.py

@@ -0,0 +1,14 @@
1
+from django.shortcuts import render, redirect
2
+from .models import Post
3
+
4
+def index(request):
5
+    posts = Post.objects.filter(status="publish")
6
+    return render(request, 'cms/index.html', {'posts': posts})
7
+
8
+def post(request, post_id):
9
+    post = Post.objects.get(pk = post_id, status="publish")
10
+    return render(request, 'cms/view.html', {'post_id': post_id, 'post': post})
11
+
12
+def post_tags(request, tag):
13
+    posts = Post.objects.filter(tags__name__in=[tag], status="publish")
14
+    return render(request, 'cms/post_tags.html',{'posts': posts})

BIN
app/front/__pycache__/__init__.cpython-39.pyc


BIN
app/front/__pycache__/admin.cpython-39.pyc


BIN
app/front/__pycache__/apps.cpython-39.pyc


BIN
app/front/__pycache__/models.cpython-39.pyc


BIN
app/front/__pycache__/urls.cpython-39.pyc


BIN
app/front/__pycache__/views.cpython-39.pyc


BIN
app/front/migrations/__pycache__/__init__.cpython-39.pyc


+ 132 - 0
app/front/static/front/css/blog.css

@@ -0,0 +1,132 @@
1
+/* stylelint-disable selector-list-comma-newline-after */
2
+
3
+.blog-header {
4
+  line-height: 1;
5
+  border-bottom: 1px solid #e5e5e5;
6
+}
7
+
8
+.blog-header-logo {
9
+  font-family: "Playfair Display", Georgia, "Times New Roman", serif;
10
+  font-size: 2.25rem;
11
+}
12
+
13
+.blog-header-logo:hover {
14
+  text-decoration: none;
15
+}
16
+
17
+h1, h2, h3, h4, h5, h6 {
18
+  font-family: "Playfair Display", Georgia, "Times New Roman", serif;
19
+}
20
+
21
+.display-4 {
22
+  font-size: 2.5rem;
23
+}
24
+@media (min-width: 768px) {
25
+  .display-4 {
26
+    font-size: 3rem;
27
+  }
28
+}
29
+
30
+.nav-scroller {
31
+  position: relative;
32
+  z-index: 2;
33
+  height: 2.75rem;
34
+  overflow-y: hidden;
35
+}
36
+
37
+.nav-scroller .nav {
38
+  display: -webkit-box;
39
+  display: -ms-flexbox;
40
+  display: flex;
41
+  -ms-flex-wrap: nowrap;
42
+  flex-wrap: nowrap;
43
+  padding-bottom: 1rem;
44
+  margin-top: -1px;
45
+  overflow-x: auto;
46
+  text-align: center;
47
+  white-space: nowrap;
48
+  -webkit-overflow-scrolling: touch;
49
+}
50
+
51
+.nav-scroller .nav-link {
52
+  padding-top: .75rem;
53
+  padding-bottom: .75rem;
54
+  font-size: .875rem;
55
+}
56
+
57
+.card-img-right {
58
+  height: 100%;
59
+  border-radius: 0 3px 3px 0;
60
+}
61
+
62
+.flex-auto {
63
+  -ms-flex: 0 0 auto;
64
+  -webkit-box-flex: 0;
65
+  flex: 0 0 auto;
66
+}
67
+
68
+.h-250 { height: 250px; }
69
+@media (min-width: 768px) {
70
+  .h-md-250 { height: 250px; }
71
+}
72
+
73
+.border-top { border-top: 1px solid #e5e5e5; }
74
+.border-bottom { border-bottom: 1px solid #e5e5e5; }
75
+
76
+.box-shadow { box-shadow: 0 .25rem .75rem rgba(0, 0, 0, .05); }
77
+
78
+/*
79
+ * Blog name and description
80
+ */
81
+.blog-title {
82
+  margin-bottom: 0;
83
+  font-size: 2rem;
84
+  font-weight: 400;
85
+}
86
+.blog-description {
87
+  font-size: 1.1rem;
88
+  color: #999;
89
+}
90
+
91
+@media (min-width: 40em) {
92
+  .blog-title {
93
+    font-size: 3.5rem;
94
+  }
95
+}
96
+
97
+/* Pagination */
98
+.blog-pagination {
99
+  margin-bottom: 4rem;
100
+}
101
+.blog-pagination > .btn {
102
+  border-radius: 2rem;
103
+}
104
+
105
+/*
106
+ * Blog posts
107
+ */
108
+.blog-post {
109
+  margin-bottom: 4rem;
110
+}
111
+.blog-post-title {
112
+  margin-bottom: .25rem;
113
+  font-size: 2.5rem;
114
+}
115
+.blog-post-meta {
116
+  margin-bottom: 1.25rem;
117
+  color: #999;
118
+}
119
+
120
+/*
121
+ * Footer
122
+ */
123
+.blog-footer {
124
+  padding: 2.5rem 0;
125
+  color: #999;
126
+  text-align: center;
127
+  background-color: #f9f9f9;
128
+  border-top: .05rem solid #e5e5e5;
129
+}
130
+.blog-footer p:last-child {
131
+  margin-bottom: 0;
132
+}

+ 34 - 0
app/front/templates/front/_menu.html

@@ -0,0 +1,34 @@
1
+<header class="blog-header py-3">
2
+	<div class="row flex-nowrap justify-content-between align-items-center">
3
+		<div class="col-4 pt-1">
4
+			<a class="text-muted" href="#">Subscribe</a>
5
+		</div>
6
+		<div class="col-4 text-center">
7
+			<a class="blog-header-logo text-dark" href="{% url "front:index" %}">SimpleMarket</a>
8
+		</div>
9
+		<div class="col-4 d-flex justify-content-end align-items-center">
10
+			<a class="text-muted" href="#">
11
+				<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="mx-3"><circle cx="10.5" cy="10.5" r="7.5"></circle><line x1="21" y1="21" x2="15.8" y2="15.8"></line></svg>
12
+			</a>
13
+			<a class="btn btn-sm btn-outline-secondary" href="#">Sign up</a>
14
+		</div>
15
+	</div>
16
+</header>
17
+
18
+<div class="nav-scroller py-1 mb-2">
19
+	<nav class="nav d-flex justify-content-between">
20
+		<a class="p-2 text-muted" href="#">World</a>
21
+		<a class="p-2 text-muted" href="#">U.S.</a>
22
+		<a class="p-2 text-muted" href="#">Technology</a>
23
+		<a class="p-2 text-muted" href="#">Design</a>
24
+		<a class="p-2 text-muted" href="#">Culture</a>
25
+		<a class="p-2 text-muted" href="#">Business</a>
26
+		<a class="p-2 text-muted" href="#">Politics</a>
27
+		<a class="p-2 text-muted" href="#">Opinion</a>
28
+		<a class="p-2 text-muted" href="#">Science</a>
29
+		<a class="p-2 text-muted" href="#">Health</a>
30
+		<a class="p-2 text-muted" href="#">Style</a>
31
+		<a class="p-2 text-muted" href="#">Travel</a>
32
+	</nav>
33
+</div>
34
+

+ 56 - 0
app/front/templates/front/base.html

@@ -0,0 +1,56 @@
1
+{% load static %}
2
+<!DOCTYPE html>
3
+<html lang="en">
4
+<head>
5
+    <title>
6
+        FindBed.xyz ทำเพื่อช่วยเหลือในการหาเตียงสำหรับผู้ป่วย COVID19
7
+    </title>
8
+    <meta name="description" content="FindBed.xyz ทำเพื่อช่วยเหลือในการหาเตียงสำหรับผู้ป่วย COVID19">
9
+     <!-- Include meta tag to ensure proper rendering and touch zooming -->
10
+  <meta name="viewport" content="width=device-width, initial-scale=1">
11
+  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
12
+
13
+  <!-- Include the jQuery library -->
14
+  <script src="https://code.jquery.com/jquery-1.11.3.min.js"></script>
15
+<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>
16
+<script>
17
+var _hmt = _hmt || [];
18
+(function() {
19
+var hm = document.createElement("script");
20
+hm.src = "//hm.baidu.com/hm.js?73c27e26f610eb3c9f3feb0c75b03925";
21
+var s = document.getElementsByTagName("script")[0];
22
+s.parentNode.insertBefore(hm, s);
23
+})();
24
+</script>
25
+<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.5.0/font/bootstrap-icons.css">
26
+
27
+  <link href="https://fonts.googleapis.com/css?family=Playfair+Display:700,900" rel="stylesheet">
28
+    <link href="{% static "front/css/blog.css" %}" rel="stylesheet">
29
+<script type='text/javascript' src="{% static "js/main.js" %}"></script>
30
+</head>
31
+
32
+<body>
33
+	<div class="container">
34
+		{% include "front/_menu.html" %}
35
+		{% block top_slide %}	
36
+		{% endblock %}  
37
+	</div>
38
+	<main role="main" class="container">
39
+		{% block content %}
40
+		{% endblock %}
41
+	</main><!-- /.container -->
42
+	<footer class="blog-footer">
43
+		<p>Blog template built for <a href="https://getbootstrap.com/">Bootstrap</a> by <a href="https://twitter.com/mdo">@mdo</a>.</p>
44
+		<p>
45
+		<a href="#">Back to top</a>
46
+		</p>
47
+	</footer>
48
+
49
+
50
+    {% block foot_script %}
51
+    {% endblock %}
52
+<script src="{% static "bower_components/holderjs/holder.min.js" %}"></script>
53
+<!-- 
54
+<script src="{% static "bower_components/popper.js/src/popper.js" %}"></script> -->
55
+</body>
56
+</html>

+ 150 - 35
app/front/templates/front/index.html

@@ -1,39 +1,154 @@
1
-{% extends "base.html" %}
1
+{% extends "front/base.html" %}
2 2
 
3 3
 {% load static %}
4
+{% block top_slide %}
5
+
6
+		<div class="jumbotron p-3 p-md-5 text-white rounded bg-dark">
7
+			<div class="col-md-6 px-0">
8
+				<h1 class="display-4 font-italic">Title of a longer featured blog post</h1>
9
+				<p class="lead my-3">Multiple lines of text that form the lede, informing new readers quickly and efficiently about what's most interesting in this post's contents.</p>
10
+				<p class="lead mb-0"><a href="#" class="text-white font-weight-bold">Continue reading...</a></p>
11
+			</div>
12
+		</div>
13
+
14
+		<div class="row mb-2">
15
+			<div class="col-md-6">
16
+				<div class="card flex-md-row mb-4 box-shadow h-md-250">
17
+					<div class="card-body d-flex flex-column align-items-start">
18
+						<strong class="d-inline-block mb-2 text-primary">World</strong>
19
+						<h3 class="mb-0">
20
+							<a class="text-dark" href="#">Featured post</a>
21
+						</h3>
22
+						<div class="mb-1 text-muted">Nov 12</div>
23
+						<p class="card-text mb-auto">This is a wider card with supporting text below as a natural lead-in to additional content.</p>
24
+						<a href="#">Continue reading</a>
25
+					</div>
26
+					<img class="card-img-right flex-auto d-none d-md-block" data-src="holder.js/200x250?theme=thumb" alt="Card image cap">
27
+				</div>
28
+			</div>
29
+			<div class="col-md-6">
30
+				<div class="card flex-md-row mb-4 box-shadow h-md-250">
31
+					<div class="card-body d-flex flex-column align-items-start">
32
+						<strong class="d-inline-block mb-2 text-success">Design</strong>
33
+						<h3 class="mb-0">
34
+							<a class="text-dark" href="#">Post title</a>
35
+						</h3>
36
+						<div class="mb-1 text-muted">Nov 11</div>
37
+						<p class="card-text mb-auto">This is a wider card with supporting text below as a natural lead-in to additional content.</p>
38
+						<a href="#">Continue reading</a>
39
+					</div>
40
+					<img class="card-img-right flex-auto d-none d-md-block" data-src="holder.js/200x250?theme=thumb" alt="Card image cap">
41
+				</div>
42
+			</div>
43
+		</div>
44
+{% endblock %}
4 45
 {% block content %}
5
-<br>
6
-<div class='row'>
7
-    <form method='post' enctype="multipart/form-data">
8
-         {% csrf_token %}
9
-    <div class='col-md-12'>
10
-        <input type='text' name='firstName' class='form-control' placeholder='ชื่อ' required/>
11
-        <br>
12
-        <input type='text' name='lastName' class='form-control' placeholder='นามสกุล' required/>
13
-        <br>
14
-        <!-- 
15
-        <input type='text' name='idCard' class='form-control' placeholder='หมายเลขบัตรประชาชน' required /> 
16
-        <br> -->
17
-        <label>วันเกิด</label>
18
-        <input type='date' name='bd' class='form-control' placeholder='วันเกิด' required />
19
-        <br>
20
-        <textarea name='address' class='form-control' placeholder='ที่อยู่' required></textarea>  
21
-        <br>
22
-        <textarea name='comment' class='form-control' placeholder='ข้อความฝากถึงเจ้าหน้าที่'></textarea>  
23
-        <br>
24
-        <input type='tel' name='tel' class='form-control' placeholder='Tel.' required/>
25
-        <br>
26
-        <input type='text' name='line_id' class='form-control' placeholder='Line ID'/>
27
-        <br>
28
-        <label>อัพโหลดภาพ</label>
29
-        <input type="file" name='photo' accept="image/*;capture=camera" class='form-control'> </br>
30
-        <span class="glyphicon glyphicon-map-marker"></span>
31
-        <a class='btn btn-primary form-control' id="currentLocationBtn">
32
-        <i class="bi bi-geo-alt-fill"></i>
33
-            คลิกเพื่อแสดงตำแหน่ง</a><br><br>
34
-        <input type='text' class='form-control' name='geo' id='geoText' readonly/><br>
35
-        <input type='submit' value='ส่งข้อมูล' class='btn-success form-control'/><br><br>
36
-    </div>
37
-    </form>
38
-</div>
46
+
47
+      <div class="row">
48
+        <div class="col-md-8 blog-main">
49
+          <h3 class="pb-3 mb-4 font-italic border-bottom">
50
+            From the Firehose
51
+          </h3>
52
+
53
+          <div class="blog-post">
54
+            <h2 class="blog-post-title">Sample blog post</h2>
55
+            <p class="blog-post-meta">January 1, 2014 by <a href="#">Mark</a></p>
56
+
57
+            <p>This blog post shows a few different types of content that's supported and styled with Bootstrap. Basic typography, images, and code are all supported.</p>
58
+            <hr>
59
+            <p>Cum sociis natoque penatibus et magnis <a href="#">dis parturient montes</a>, nascetur ridiculus mus. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Sed posuere consectetur est at lobortis. Cras mattis consectetur purus sit amet fermentum.</p>
60
+            <blockquote>
61
+              <p>Curabitur blandit tempus porttitor. <strong>Nullam quis risus eget urna mollis</strong> ornare vel eu leo. Nullam id dolor id nibh ultricies vehicula ut id elit.</p>
62
+            </blockquote>
63
+            <p>Etiam porta <em>sem malesuada magna</em> mollis euismod. Cras mattis consectetur purus sit amet fermentum. Aenean lacinia bibendum nulla sed consectetur.</p>
64
+            <h2>Heading</h2>
65
+            <p>Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.</p>
66
+            <h3>Sub-heading</h3>
67
+            <p>Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.</p>
68
+            <pre><code>Example code block</code></pre>
69
+            <p>Aenean lacinia bibendum nulla sed consectetur. Etiam porta sem malesuada magna mollis euismod. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa.</p>
70
+            <h3>Sub-heading</h3>
71
+            <p>Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Aenean lacinia bibendum nulla sed consectetur. Etiam porta sem malesuada magna mollis euismod. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus.</p>
72
+            <ul>
73
+              <li>Praesent commodo cursus magna, vel scelerisque nisl consectetur et.</li>
74
+              <li>Donec id elit non mi porta gravida at eget metus.</li>
75
+              <li>Nulla vitae elit libero, a pharetra augue.</li>
76
+            </ul>
77
+            <p>Donec ullamcorper nulla non metus auctor fringilla. Nulla vitae elit libero, a pharetra augue.</p>
78
+            <ol>
79
+              <li>Vestibulum id ligula porta felis euismod semper.</li>
80
+              <li>Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.</li>
81
+              <li>Maecenas sed diam eget risus varius blandit sit amet non magna.</li>
82
+            </ol>
83
+            <p>Cras mattis consectetur purus sit amet fermentum. Sed posuere consectetur est at lobortis.</p>
84
+          </div><!-- /.blog-post -->
85
+
86
+          <div class="blog-post">
87
+            <h2 class="blog-post-title">Another blog post</h2>
88
+            <p class="blog-post-meta">December 23, 2013 by <a href="#">Jacob</a></p>
89
+
90
+            <p>Cum sociis natoque penatibus et magnis <a href="#">dis parturient montes</a>, nascetur ridiculus mus. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Sed posuere consectetur est at lobortis. Cras mattis consectetur purus sit amet fermentum.</p>
91
+            <blockquote>
92
+              <p>Curabitur blandit tempus porttitor. <strong>Nullam quis risus eget urna mollis</strong> ornare vel eu leo. Nullam id dolor id nibh ultricies vehicula ut id elit.</p>
93
+            </blockquote>
94
+            <p>Etiam porta <em>sem malesuada magna</em> mollis euismod. Cras mattis consectetur purus sit amet fermentum. Aenean lacinia bibendum nulla sed consectetur.</p>
95
+            <p>Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.</p>
96
+          </div><!-- /.blog-post -->
97
+
98
+          <div class="blog-post">
99
+            <h2 class="blog-post-title">New feature</h2>
100
+            <p class="blog-post-meta">December 14, 2013 by <a href="#">Chris</a></p>
101
+
102
+            <p>Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Aenean lacinia bibendum nulla sed consectetur. Etiam porta sem malesuada magna mollis euismod. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus.</p>
103
+            <ul>
104
+              <li>Praesent commodo cursus magna, vel scelerisque nisl consectetur et.</li>
105
+              <li>Donec id elit non mi porta gravida at eget metus.</li>
106
+              <li>Nulla vitae elit libero, a pharetra augue.</li>
107
+            </ul>
108
+            <p>Etiam porta <em>sem malesuada magna</em> mollis euismod. Cras mattis consectetur purus sit amet fermentum. Aenean lacinia bibendum nulla sed consectetur.</p>
109
+            <p>Donec ullamcorper nulla non metus auctor fringilla. Nulla vitae elit libero, a pharetra augue.</p>
110
+          </div><!-- /.blog-post -->
111
+
112
+          <nav class="blog-pagination">
113
+            <a class="btn btn-outline-primary" href="#">Older</a>
114
+            <a class="btn btn-outline-secondary disabled" href="#">Newer</a>
115
+          </nav>
116
+
117
+        </div><!-- /.blog-main -->
118
+
119
+        <aside class="col-md-4 blog-sidebar">
120
+          <div class="p-3 mb-3 bg-light rounded">
121
+            <h4 class="font-italic">About</h4>
122
+            <p class="mb-0">Etiam porta <em>sem malesuada magna</em> mollis euismod. Cras mattis consectetur purus sit amet fermentum. Aenean lacinia bibendum nulla sed consectetur.</p>
123
+          </div>
124
+
125
+          <div class="p-3">
126
+            <h4 class="font-italic">Archives</h4>
127
+            <ol class="list-unstyled mb-0">
128
+              <li><a href="#">March 2014</a></li>
129
+              <li><a href="#">February 2014</a></li>
130
+              <li><a href="#">January 2014</a></li>
131
+              <li><a href="#">December 2013</a></li>
132
+              <li><a href="#">November 2013</a></li>
133
+              <li><a href="#">October 2013</a></li>
134
+              <li><a href="#">September 2013</a></li>
135
+              <li><a href="#">August 2013</a></li>
136
+              <li><a href="#">July 2013</a></li>
137
+              <li><a href="#">June 2013</a></li>
138
+              <li><a href="#">May 2013</a></li>
139
+              <li><a href="#">April 2013</a></li>
140
+            </ol>
141
+          </div>
142
+
143
+          <div class="p-3">
144
+            <h4 class="font-italic">Elsewhere</h4>
145
+            <ol class="list-unstyled">
146
+              <li><a href="#">GitHub</a></li>
147
+              <li><a href="#">Twitter</a></li>
148
+              <li><a href="#">Facebook</a></li>
149
+            </ol>
150
+          </div>
151
+        </aside><!-- /.blog-sidebar -->
152
+
153
+      </div><!-- /.row -->
39 154
 {% endblock %}

+ 39 - 0
app/front/templates/front/index.old.html

@@ -0,0 +1,39 @@
1
+{% extends "front/base.html" %}
2
+
3
+{% load static %}
4
+{% block content %}
5
+<br>
6
+<div class='row'>
7
+    <form method='post' enctype="multipart/form-data">
8
+         {% csrf_token %}
9
+    <div class='col-md-12'>
10
+        <input type='text' name='firstName' class='form-control' placeholder='ชื่อ' required/>
11
+        <br>
12
+        <input type='text' name='lastName' class='form-control' placeholder='นามสกุล' required/>
13
+        <br>
14
+        <!-- 
15
+        <input type='text' name='idCard' class='form-control' placeholder='หมายเลขบัตรประชาชน' required /> 
16
+        <br> -->
17
+        <label>วันเกิด</label>
18
+        <input type='date' name='bd' class='form-control' placeholder='วันเกิด' required />
19
+        <br>
20
+        <textarea name='address' class='form-control' placeholder='ที่อยู่' required></textarea>  
21
+        <br>
22
+        <textarea name='comment' class='form-control' placeholder='ข้อความฝากถึงเจ้าหน้าที่'></textarea>  
23
+        <br>
24
+        <input type='tel' name='tel' class='form-control' placeholder='Tel.' required/>
25
+        <br>
26
+        <input type='text' name='line_id' class='form-control' placeholder='Line ID'/>
27
+        <br>
28
+        <label>อัพโหลดภาพ</label>
29
+        <input type="file" name='photo' accept="image/*;capture=camera" class='form-control'> </br>
30
+        <span class="glyphicon glyphicon-map-marker"></span>
31
+        <a class='btn btn-primary form-control' id="currentLocationBtn">
32
+        <i class="bi bi-geo-alt-fill"></i>
33
+            คลิกเพื่อแสดงตำแหน่ง</a><br><br>
34
+        <input type='text' class='form-control' name='geo' id='geoText' readonly/><br>
35
+        <input type='submit' value='ส่งข้อมูล' class='btn-success form-control'/><br><br>
36
+    </div>
37
+    </form>
38
+</div>
39
+{% endblock %}

+ 3 - 0
app/front/urls.py

@@ -6,5 +6,8 @@ from . import views
6 6
 urlpatterns = [
7 7
     path('', views.index, name='index'),
8 8
     path('tracking', views.tracking, name='tracking'),
9
+    path('tracking', views.tracking, name='tracking'),
9 10
     path('success', views.success, name='success'),
10 11
 ]
12
+
13
+app_name = 'front'

+ 16 - 0
app/front/views.py

@@ -23,6 +23,22 @@ def index(request):
23 23
         return redirect('success')
24 24
     return render(request, 'front/index.html')
25 25
 
26
+def news(request):
27
+    pass
28
+
29
+def forum(request):
30
+    pass
31
+
32
+def articles(request):
33
+    pass
34
+
35
+def market(request):
36
+    pass
37
+
38
+def mystore(requeset):
39
+    pass
40
+
41
+
26 42
 def success(request):
27 43
     return render(request, 'front/success.html')
28 44
 

+ 0 - 0
app/fruit/__init__.py


+ 67 - 0
app/fruit/admin.py

@@ -0,0 +1,67 @@
1
+from django.contrib import admin
2
+
3
+from django.contrib import admin
4
+from django.contrib.gis.admin import OSMGeoAdmin
5
+from .models import Store, ProductType, Product, Photo, ProductSKU
6
+# Register your models here.
7
+
8
+from django_google_maps import widgets as map_widgets
9
+from django_google_maps import fields as map_fields
10
+from django_json_widget.widgets import JSONEditorWidget
11
+from django.db import models
12
+from django.utils.html import format_html
13
+from django.conf import settings
14
+
15
+from dal import autocomplete
16
+from django import forms
17
+from mptt.admin import MPTTModelAdmin
18
+
19
+
20
+
21
+@admin.register(Store)
22
+class StoreAdmin(admin.ModelAdmin):
23
+    search_fields = ('name',)
24
+    list_display = ('name', 'address', 'geolocation')
25
+    fields = ('name', 'address_text',  'tel', 'line_id',  'email', 'address', 'geolocation',)
26
+    formfield_overrides = {
27
+        map_fields.AddressField: {'widget': map_widgets.GoogleMapsAddressWidget},
28
+    }
29
+
30
+
31
+
32
+@admin.register(ProductType)
33
+class ProductTypeAdmin(MPTTModelAdmin):
34
+    pass
35
+
36
+
37
+
38
+class PhotoInlineAdmin(admin.StackedInline):
39
+    model = Photo
40
+
41
+@admin.register(Product)
42
+class ProductAdmin(admin.ModelAdmin):
43
+    inlines = [PhotoInlineAdmin,]
44
+
45
+    formfield_overrides = {
46
+        map_fields.AddressField: {'widget': map_widgets.GoogleMapsAddressWidget},
47
+        models.JSONField: {'widget': JSONEditorWidget},
48
+    }
49
+    list_display = ["name", "created_at", "created_by"]
50
+
51
+    def save_model(self, request, obj, form, change):
52
+        if obj.created_by == None:
53
+            obj.created_by = request.user
54
+        #super().save_model(request, obj, form, change)
55
+        obj.modified_by = request.user
56
+        super().save_model(request, obj, form, change)
57
+
58
+@admin.register(ProductSKU)
59
+class ProductSKUAdmin(admin.ModelAdmin):
60
+    formfield_overrides = {
61
+        map_fields.AddressField: {'widget': map_widgets.GoogleMapsAddressWidget},
62
+        models.JSONField: {'widget': JSONEditorWidget},
63
+    }
64
+
65
+@admin.register(Photo)
66
+class PhotoAdmin(admin.ModelAdmin):
67
+    pass

+ 6 - 0
app/fruit/apps.py

@@ -0,0 +1,6 @@
1
+from django.apps import AppConfig
2
+
3
+
4
+class FruitConfig(AppConfig):
5
+    default_auto_field = 'django.db.models.BigAutoField'
6
+    name = 'fruit'

+ 6 - 0
app/fruit/middleware.py

@@ -0,0 +1,6 @@
1
+from .utils import set_current_user
2
+
3
+
4
+class CurrentUserMiddleware:
5
+    def process_request(self, request):
6
+        set_current_user(getattr(request, 'user', None))

+ 30 - 0
app/fruit/migrations/0001_initial.py

@@ -0,0 +1,30 @@
1
+# Generated by Django 3.2.5 on 2021-07-27 13:20
2
+
3
+from django.db import migrations, models
4
+import django_google_maps.fields
5
+
6
+
7
+class Migration(migrations.Migration):
8
+
9
+    initial = True
10
+
11
+    dependencies = [
12
+    ]
13
+
14
+    operations = [
15
+        migrations.CreateModel(
16
+            name='Store',
17
+            fields=[
18
+                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
19
+                ('name', models.CharField(max_length=200)),
20
+                ('address_text', models.TextField(blank=True, null=True)),
21
+                ('address', django_google_maps.fields.AddressField(max_length=200)),
22
+                ('geolocation', django_google_maps.fields.GeoLocationField(max_length=100)),
23
+                ('tel', models.CharField(blank=True, max_length=100, null=True)),
24
+                ('line_id', models.CharField(blank=True, max_length=100, null=True)),
25
+                ('email', models.EmailField(blank=True, max_length=254, null=True)),
26
+                ('created_at', models.DateTimeField(auto_now_add=True, null=True)),
27
+                ('updated_at', models.DateTimeField(auto_now=True)),
28
+            ],
29
+        ),
30
+    ]

+ 30 - 0
app/fruit/migrations/0002_producttype.py

@@ -0,0 +1,30 @@
1
+# Generated by Django 3.2.5 on 2021-07-27 13:41
2
+
3
+from django.db import migrations, models
4
+import django.db.models.deletion
5
+import mptt.fields
6
+
7
+
8
+class Migration(migrations.Migration):
9
+
10
+    dependencies = [
11
+        ('fruit', '0001_initial'),
12
+    ]
13
+
14
+    operations = [
15
+        migrations.CreateModel(
16
+            name='ProductType',
17
+            fields=[
18
+                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
19
+                ('name', models.CharField(max_length=50, unique=True)),
20
+                ('lft', models.PositiveIntegerField(editable=False)),
21
+                ('rght', models.PositiveIntegerField(editable=False)),
22
+                ('tree_id', models.PositiveIntegerField(db_index=True, editable=False)),
23
+                ('level', models.PositiveIntegerField(editable=False)),
24
+                ('parent', mptt.fields.TreeForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='children', to='fruit.producttype')),
25
+            ],
26
+            options={
27
+                'abstract': False,
28
+            },
29
+        ),
30
+    ]

+ 19 - 0
app/fruit/migrations/0003_store_product_type.py

@@ -0,0 +1,19 @@
1
+# Generated by Django 3.2.5 on 2021-07-27 15:05
2
+
3
+from django.db import migrations, models
4
+import django.db.models.deletion
5
+
6
+
7
+class Migration(migrations.Migration):
8
+
9
+    dependencies = [
10
+        ('fruit', '0002_producttype'),
11
+    ]
12
+
13
+    operations = [
14
+        migrations.AddField(
15
+            model_name='store',
16
+            name='product_type',
17
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='fruit.producttype'),
18
+        ),
19
+    ]

+ 48 - 0
app/fruit/migrations/0004_auto_20210727_2220.py

@@ -0,0 +1,48 @@
1
+# Generated by Django 3.2.5 on 2021-07-27 15:20
2
+
3
+from django.conf import settings
4
+from django.db import migrations, models
5
+import django.db.models.deletion
6
+
7
+
8
+class Migration(migrations.Migration):
9
+
10
+    dependencies = [
11
+        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
12
+        ('fruit', '0003_store_product_type'),
13
+    ]
14
+
15
+    operations = [
16
+        migrations.CreateModel(
17
+            name='Product',
18
+            fields=[
19
+                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
20
+                ('name', models.CharField(max_length=200)),
21
+            ],
22
+        ),
23
+        migrations.RemoveField(
24
+            model_name='store',
25
+            name='product_type',
26
+        ),
27
+        migrations.CreateModel(
28
+            name='Profile',
29
+            fields=[
30
+                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
31
+                ('bio', models.TextField(blank=True, max_length=500)),
32
+                ('location', models.CharField(blank=True, max_length=30)),
33
+                ('birth_date', models.DateField(blank=True, null=True)),
34
+                ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
35
+            ],
36
+        ),
37
+        migrations.CreateModel(
38
+            name='Photo',
39
+            fields=[
40
+                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
41
+                ('name', models.CharField(max_length=200, unique=True)),
42
+                ('photo', models.ImageField(blank=True, upload_to='uploads/%Y/%m/%d/', verbose_name='Photo')),
43
+                ('created_at', models.DateTimeField(auto_now_add=True, null=True)),
44
+                ('updated_at', models.DateTimeField(auto_now=True)),
45
+                ('product', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='fruit.product')),
46
+            ],
47
+        ),
48
+    ]

+ 66 - 0
app/fruit/migrations/0005_auto_20210727_2243.py

@@ -0,0 +1,66 @@
1
+# Generated by Django 3.2.5 on 2021-07-27 15:43
2
+
3
+from django.conf import settings
4
+from django.db import migrations, models
5
+import django.db.models.deletion
6
+
7
+
8
+class Migration(migrations.Migration):
9
+
10
+    dependencies = [
11
+        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
12
+        ('fruit', '0004_auto_20210727_2220'),
13
+    ]
14
+
15
+    operations = [
16
+        migrations.AddField(
17
+            model_name='photo',
18
+            name='created_by',
19
+            field=models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='photo_created', to=settings.AUTH_USER_MODEL),
20
+        ),
21
+        migrations.AddField(
22
+            model_name='photo',
23
+            name='modified_by',
24
+            field=models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='photo_modified', to=settings.AUTH_USER_MODEL),
25
+        ),
26
+        migrations.AddField(
27
+            model_name='product',
28
+            name='created_at',
29
+            field=models.DateTimeField(auto_now_add=True, null=True),
30
+        ),
31
+        migrations.AddField(
32
+            model_name='product',
33
+            name='created_by',
34
+            field=models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='product_created', to=settings.AUTH_USER_MODEL),
35
+        ),
36
+        migrations.AddField(
37
+            model_name='product',
38
+            name='description',
39
+            field=models.TextField(blank=True, null=True),
40
+        ),
41
+        migrations.AddField(
42
+            model_name='product',
43
+            name='modified_by',
44
+            field=models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='product_modified', to=settings.AUTH_USER_MODEL),
45
+        ),
46
+        migrations.AddField(
47
+            model_name='product',
48
+            name='price',
49
+            field=models.DecimalField(blank=True, decimal_places=2, max_digits=7, null=True),
50
+        ),
51
+        migrations.AddField(
52
+            model_name='product',
53
+            name='product_type',
54
+            field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='fruit.producttype'),
55
+        ),
56
+        migrations.AddField(
57
+            model_name='product',
58
+            name='store',
59
+            field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='fruit.store'),
60
+        ),
61
+        migrations.AddField(
62
+            model_name='product',
63
+            name='updated_at',
64
+            field=models.DateTimeField(auto_now=True),
65
+        ),
66
+    ]

+ 18 - 0
app/fruit/migrations/0006_product_details.py

@@ -0,0 +1,18 @@
1
+# Generated by Django 3.2.5 on 2021-07-27 15:58
2
+
3
+from django.db import migrations, models
4
+
5
+
6
+class Migration(migrations.Migration):
7
+
8
+    dependencies = [
9
+        ('fruit', '0005_auto_20210727_2243'),
10
+    ]
11
+
12
+    operations = [
13
+        migrations.AddField(
14
+            model_name='product',
15
+            name='details',
16
+            field=models.JSONField(blank=True, null=True),
17
+        ),
18
+    ]

+ 46 - 0
app/fruit/migrations/0007_auto_20210727_2312.py

@@ -0,0 +1,46 @@
1
+# Generated by Django 3.2.5 on 2021-07-27 16:12
2
+
3
+from django.conf import settings
4
+from django.db import migrations, models
5
+import django.db.models.deletion
6
+
7
+
8
+class Migration(migrations.Migration):
9
+
10
+    dependencies = [
11
+        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
12
+        ('fruit', '0006_product_details'),
13
+    ]
14
+
15
+    operations = [
16
+        migrations.AddField(
17
+            model_name='product',
18
+            name='n_unit',
19
+            field=models.DecimalField(blank=True, decimal_places=2, max_digits=7, null=True),
20
+        ),
21
+        migrations.AddField(
22
+            model_name='product',
23
+            name='unit_name',
24
+            field=models.CharField(max_length=200, null=True),
25
+        ),
26
+        migrations.CreateModel(
27
+            name='ProductSKU',
28
+            fields=[
29
+                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
30
+                ('created_at', models.DateTimeField(auto_now_add=True, null=True)),
31
+                ('updated_at', models.DateTimeField(auto_now=True)),
32
+                ('sku', models.CharField(max_length=200)),
33
+                ('description', models.TextField(blank=True, null=True)),
34
+                ('price', models.DecimalField(blank=True, decimal_places=2, max_digits=7, null=True)),
35
+                ('details', models.JSONField(blank=True, null=True)),
36
+                ('n_unit', models.DecimalField(blank=True, decimal_places=2, max_digits=7, null=True)),
37
+                ('unit_name', models.CharField(max_length=200, null=True)),
38
+                ('created_by', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='productsku_created', to=settings.AUTH_USER_MODEL)),
39
+                ('modified_by', models.ForeignKey(editable=False, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='productsku_modified', to=settings.AUTH_USER_MODEL)),
40
+                ('product', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='fruit.product')),
41
+            ],
42
+            options={
43
+                'abstract': False,
44
+            },
45
+        ),
46
+    ]

+ 19 - 0
app/fruit/migrations/0008_product_code.py

@@ -0,0 +1,19 @@
1
+# Generated by Django 3.2.5 on 2021-07-27 16:18
2
+
3
+from django.db import migrations, models
4
+
5
+
6
+class Migration(migrations.Migration):
7
+
8
+    dependencies = [
9
+        ('fruit', '0007_auto_20210727_2312'),
10
+    ]
11
+
12
+    operations = [
13
+        migrations.AddField(
14
+            model_name='product',
15
+            name='code',
16
+            field=models.CharField(default='', max_length=200),
17
+            preserve_default=False,
18
+        ),
19
+    ]

+ 0 - 0
app/fruit/migrations/__init__.py


+ 133 - 0
app/fruit/models.py

@@ -0,0 +1,133 @@
1
+from django.db import models
2
+
3
+from django_google_maps import fields as map_fields
4
+from colorfield.fields import ColorField
5
+from smart_selects.db_fields import (
6
+    ChainedForeignKey,
7
+    ChainedManyToManyField,
8
+    GroupedForeignKey,
9
+)
10
+from django.db.models import Q
11
+import googlemaps
12
+from django.contrib.gis.geos import fromstr
13
+
14
+from django.conf import settings
15
+import csv
16
+import haversine as hs
17
+from mptt.models import MPTTModel, TreeForeignKey
18
+
19
+from django.contrib.auth.models import User
20
+from django.db.models.signals import post_save
21
+from django.dispatch import receiver
22
+from shaqfindbed.utils import get_current_user
23
+
24
+
25
+# Create your models here.
26
+
27
+class GenericModel(models.Model):
28
+    created_at = models.DateTimeField(auto_now_add=True, null=True)
29
+    updated_at = models.DateTimeField(auto_now=True)
30
+
31
+    created_by = models.ForeignKey(User, null=True, editable=False, related_name='%(class)s_created', on_delete=models.SET_NULL)
32
+    modified_by = models.ForeignKey(User, null=True, editable=False, related_name='%(class)s_modified', on_delete=models.SET_NULL)
33
+
34
+    '''
35
+    def save(self, *args, **kwargs):
36
+        user = get_current_user()
37
+        print("user "+user.is_authenticated())
38
+        if user and user.is_authenticated():
39
+            self.modified_by = user
40
+            if not self.id:
41
+                self.created_by = user
42
+        super(GenericModel, self).save(*args, **kwargs)
43
+    '''
44
+
45
+    class Meta:
46
+        abstract = True
47
+
48
+class Store(models.Model):
49
+    name = models.CharField(max_length=200)
50
+    address_text = models.TextField(blank=True, null=True)
51
+    #address = models.CharField(max_length=100)
52
+    address = map_fields.AddressField(max_length=200)
53
+    geolocation = map_fields.GeoLocationField(max_length=100)
54
+
55
+
56
+    tel = models.CharField(max_length=100, null=True, blank=True)
57
+    line_id = models.CharField(max_length=100, null=True, blank=True)
58
+    email = models.EmailField(null=True, blank=True)
59
+
60
+
61
+    created_at = models.DateTimeField(auto_now_add=True, null=True)
62
+    updated_at = models.DateTimeField(auto_now=True)
63
+
64
+    def __str__(self):
65
+        return f"{self.name}"
66
+
67
+
68
+
69
+class ProductType(MPTTModel):
70
+    name = models.CharField(max_length=50, unique=True)
71
+    parent = TreeForeignKey('self', on_delete=models.CASCADE, null=True, blank=True, related_name='children')
72
+
73
+    class MPTTMeta:
74
+        order_insertion_by = ['name']
75
+
76
+
77
+    def __str__(self):
78
+        return f"{self.name}"
79
+
80
+
81
+class Product(GenericModel, models.Model ):
82
+    name = models.CharField(max_length=200)
83
+    code = models.CharField(max_length=200)
84
+    product_type = models.ForeignKey('ProductType', on_delete=models.SET_NULL, null=True)
85
+    description = models.TextField(blank=True, null=True)
86
+    store = models.ForeignKey('Store', on_delete=models.CASCADE, null=True, blank=False)
87
+    price = models.DecimalField(null=True, blank=True, decimal_places=2, max_digits=7)
88
+
89
+    details  = models.JSONField(null=True, blank=True)
90
+
91
+    n_unit = models.DecimalField(blank=True, decimal_places=2, max_digits=7, null=True)
92
+    unit_name = models.CharField(max_length=200, null=True)
93
+
94
+    def __str__(self):
95
+        return f"{self.name} {self.code}"
96
+
97
+class ProductSKU(GenericModel, models.Model ):
98
+    sku = models.CharField(max_length=200)
99
+    product  = models.ForeignKey('Product', on_delete=models.CASCADE, null=True)
100
+    description = models.TextField(blank=True, null=True)
101
+    price = models.DecimalField(null=True, blank=True, decimal_places=2, max_digits=7)
102
+
103
+    details  = models.JSONField(null=True, blank=True)
104
+
105
+    n_unit = models.DecimalField(blank=True, decimal_places=2, max_digits=7, null=True)
106
+    unit_name = models.CharField(max_length=200, null=True)
107
+
108
+class Photo(GenericModel, models.Model):
109
+    name = models.CharField(max_length=200, unique=True)
110
+    photo  = models.ImageField(upload_to="uploads/%Y/%m/%d/", blank=True, verbose_name="Photo")
111
+    product = models.ForeignKey('Product', on_delete=models.CASCADE, null=True)
112
+
113
+
114
+
115
+
116
+
117
+class Profile(models.Model):
118
+    user = models.OneToOneField(User, on_delete=models.CASCADE)
119
+    bio = models.TextField(max_length=500, blank=True)
120
+    location = models.CharField(max_length=30, blank=True)
121
+    birth_date = models.DateField(null=True, blank=True)
122
+
123
+@receiver(post_save, sender=User)
124
+def create_user_profile(sender, instance, created, **kwargs):
125
+    if created:
126
+        Profile.objects.create(user=instance)
127
+
128
+@receiver(post_save, sender=User)
129
+def save_user_profile(sender, instance, **kwargs):
130
+    try:
131
+        instance.profile.save()
132
+    except:
133
+        Profile.objects.create(user=instance)

+ 0 - 0
app/fruit/templates/fruit/index.html


+ 5 - 0
app/fruit/templates/fruit/mystore.html

@@ -0,0 +1,5 @@
1
+{% extends "front/base.html" %}
2
+{% load static %}
3
+{% block content %}
4
+<h1>My Store</h1>
5
+{% endblock %}

+ 21 - 0
app/fruit/templates/fruit/signup.html

@@ -0,0 +1,21 @@
1
+{% extends "front/base.html" %}
2
+{% load static %}
3
+{% block content %}
4
+  <h2>Sign up</h2>
5
+  <form method="post">
6
+    {% csrf_token %}
7
+    {% for field in form %}
8
+      <p>
9
+        {{ field.label_tag }}<br>
10
+        {{ field }}
11
+        {% if field.help_text %}
12
+          <small style="color: grey">{{ field.help_text }}</small>
13
+        {% endif %}
14
+        {% for error in field.errors %}
15
+          <p style="color: red">{{ error }}</p>
16
+        {% endfor %}
17
+      </p>
18
+    {% endfor %}
19
+    <button type="submit">Sign up</button>
20
+  </form>
21
+{% endblock %}

+ 3 - 0
app/fruit/tests.py

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

+ 12 - 0
app/fruit/urls.py

@@ -0,0 +1,12 @@
1
+
2
+from django.urls import path
3
+from django.conf.urls import url
4
+from . import views
5
+
6
+urlpatterns = [
7
+    path('', views.index, name='index'),
8
+    path('mystore', views.mystore, name='mystore'),
9
+    path('signup', views.signup, name='signup'),
10
+]
11
+
12
+app_name = 'fruit'

+ 28 - 0
app/fruit/views.py

@@ -0,0 +1,28 @@
1
+#from django.shortcuts import render
2
+from django.shortcuts import render, redirect
3
+# Create your views here.
4
+from django.contrib.auth import login, authenticate
5
+from django.contrib.auth.forms import UserCreationForm
6
+from django.urls import reverse
7
+from django.contrib.auth.decorators import login_required
8
+
9
+def index(request):
10
+    return render(request, 'fruit/index.html')
11
+
12
+@login_required
13
+def mystore(request):
14
+    return render(request, 'fruit/mystore.html')
15
+
16
+def signup(request):
17
+    if request.method == 'POST':
18
+        form = UserCreationForm(request.POST)
19
+        if form.is_valid():
20
+            form.save()
21
+            username = form.cleaned_data.get('username')
22
+            raw_password = form.cleaned_data.get('password1')
23
+            user = authenticate(username=username, password=raw_password)
24
+            login(request, user)
25
+            return redirect('front:index')
26
+    else:
27
+        form = UserCreationForm()
28
+    return render(request, 'fruit/signup.html', {'form': form})

+ 0 - 0
app/requirements.txt


Bu fark içinde çok fazla dosya değişikliği olduğu için bazı dosyalar gösterilmiyor

golf/wellness - Gogs: Simplico Git Service

1 次代码提交 (5a73f0844f5fedc212c0abc55ac0aa3ddb7cdf73)

作者 SHA1 备注 提交日期
  inboxz 0494d5436c update-260821 4 年之前