pre> 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


Some files were not shown because too many files changed in this diff

tum/whitesports - Gogs: Simplico Git Service

Нет описания

File.php 4.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. <?php
  2. /**
  3. * SimplePie
  4. *
  5. * A PHP-Based RSS and Atom Feed Framework.
  6. * Takes the hard work out of managing a complete RSS/Atom solution.
  7. *
  8. * Copyright (c) 2004-2016, Ryan Parman, Sam Sneddon, Ryan McCue, and contributors
  9. * All rights reserved.
  10. *
  11. * Redistribution and use in source and binary forms, with or without modification, are
  12. * permitted provided that the following conditions are met:
  13. *
  14. * * Redistributions of source code must retain the above copyright notice, this list of
  15. * conditions and the following disclaimer.
  16. *
  17. * * Redistributions in binary form must reproduce the above copyright notice, this list
  18. * of conditions and the following disclaimer in the documentation and/or other materials
  19. * provided with the distribution.
  20. *
  21. * * Neither the name of the SimplePie Team nor the names of its contributors may be used
  22. * to endorse or promote products derived from this software without specific prior
  23. * written permission.
  24. *
  25. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
  26. * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  27. * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
  28. * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  29. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  30. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  31. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  32. * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  33. * POSSIBILITY OF SUCH DAMAGE.
  34. *
  35. * @package SimplePie
  36. * @copyright 2004-2016 Ryan Parman, Sam Sneddon, Ryan McCue
  37. * @author Ryan Parman
  38. * @author Sam Sneddon
  39. * @author Ryan McCue
  40. * @link http://simplepie.org/ SimplePie
  41. * @license http://www.opensource.org/licenses/bsd-license.php BSD License
  42. */
  43. /**
  44. * Caches data to the filesystem
  45. *
  46. * @package SimplePie
  47. * @subpackage Caching
  48. */
  49. class SimplePie_Cache_File implements SimplePie_Cache_Base
  50. {
  51. /**
  52. * Location string
  53. *
  54. * @see SimplePie::$cache_location
  55. * @var string
  56. */
  57. protected $location;
  58. /**
  59. * Filename
  60. *
  61. * @var string
  62. */
  63. protected $filename;
  64. /**
  65. * File extension
  66. *
  67. * @var string
  68. */
  69. protected $extension;
  70. /**
  71. * File path
  72. *
  73. * @var string
  74. */
  75. protected $name;
  76. /**
  77. * Create a new cache object
  78. *
  79. * @param string $location Location string (from SimplePie::$cache_location)
  80. * @param string $name Unique ID for the cache
  81. * @param string $type Either TYPE_FEED for SimplePie data, or TYPE_IMAGE for image data
  82. */
  83. public function __construct($location, $name, $type)
  84. {
  85. $this->location = $location;
  86. $this->filename = $name;
  87. $this->extension = $type;
  88. $this->name = "$this->location/$this->filename.$this->extension";
  89. }
  90. /**
  91. * Save data to the cache
  92. *
  93. * @param array|SimplePie $data Data to store in the cache. If passed a SimplePie object, only cache the $data property
  94. * @return bool Successfulness
  95. */
  96. public function save($data)
  97. {
  98. if (file_exists($this->name) && is_writable($this->name) || file_exists($this->location) && is_writable($this->location))
  99. {
  100. if ($data instanceof SimplePie)
  101. {
  102. $data = $data->data;
  103. }
  104. $data = serialize($data);
  105. return (bool) file_put_contents($this->name, $data);
  106. }
  107. return false;
  108. }
  109. /**
  110. * Retrieve the data saved to the cache
  111. *
  112. * @return array Data for SimplePie::$data
  113. */
  114. public function load()
  115. {
  116. if (file_exists($this->name) && is_readable($this->name))
  117. {
  118. return unserialize(file_get_contents($this->name));
  119. }
  120. return false;
  121. }
  122. /**
  123. * Retrieve the last modified time for the cache
  124. *
  125. * @return int Timestamp
  126. */
  127. public function mtime()
  128. {
  129. return @filemtime($this->name);
  130. }
  131. /**
  132. * Set the last modified time to the current time
  133. *
  134. * @return bool Success status
  135. */
  136. public function touch()
  137. {
  138. return @touch($this->name);
  139. }
  140. /**
  141. * Remove the cache
  142. *
  143. * @return bool Success status
  144. */
  145. public function unlink()
  146. {
  147. if (file_exists($this->name))
  148. {
  149. return unlink($this->name);
  150. }
  151. return false;
  152. }
  153. }