tum 4 年 前
コミット
99eb0cfed3

+ 2 - 1
app/front/templates/front/_menu.html

@@ -12,9 +12,10 @@
12 12
 			</a>
13 13
             {% if user.is_authenticated %}
14 14
             <a class="btn btn-sm btn-outline-secondary" href="{% url "fruit:mystore" %}">My Store</a>
15
+            <a class="ml-2 btn btn-sm btn-outline-secondary" href="{% url "logout" %}">Sign Out</a>
15 16
             {% else  %}
16 17
             <a class="btn btn-sm btn-outline-secondary mx-2" href="{% url "login" %}">Sign In</a>
17
-			<a class="btn btn-sm btn-outline-secondary" href="#">Sign up</a>
18
+            <a class="btn btn-sm btn-outline-secondary" href="{% url "fruit:signup" %}">Sign up</a>
18 19
             {% endif %}
19 20
 		</div>
20 21
 	</div>

+ 11 - 0
app/fruit/forms.py

@@ -6,6 +6,8 @@ from django_google_maps import widgets as map_widgets
6 6
 from django_google_maps import fields as map_fields
7 7
 
8 8
 import django_filters
9
+from django.contrib.auth.forms import UserCreationForm
10
+from django.contrib.auth.models import User
9 11
 
10 12
 GeneralWidgets = {
11 13
     'startDate': forms.DateInput(format="%d/%m/%Y",attrs={'type': 'text', 'class': 'datepicker'}),
@@ -109,3 +111,12 @@ class VendorOrderFilter(django_filters.FilterSet):
109 111
         fields = ['vendor', 'product', 'store', 'price', 'n_unit',  'unit_name', 'total', 'created_at']
110 112
 
111 113
 
114
+
115
+class SignUpForm(UserCreationForm):
116
+    email = forms.EmailField(max_length=254, help_text='Required. Inform a valid email address.')
117
+
118
+    class Meta:
119
+        model = User
120
+        fields = ('username', 'email', 'password1', 'password2', )
121
+
122
+

+ 25 - 0
app/fruit/migrations/0029_auto_20210815_1415.py

@@ -0,0 +1,25 @@
1
+# Generated by Django 3.2.6 on 2021-08-15 07:15
2
+
3
+from django.db import migrations, models
4
+import django.db.models.deletion
5
+import smart_selects.db_fields
6
+
7
+
8
+class Migration(migrations.Migration):
9
+
10
+    dependencies = [
11
+        ('fruit', '0028_auto_20210809_2130'),
12
+    ]
13
+
14
+    operations = [
15
+        migrations.AlterField(
16
+            model_name='product',
17
+            name='store',
18
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='fruit.store'),
19
+        ),
20
+        migrations.AlterField(
21
+            model_name='vendororder',
22
+            name='product',
23
+            field=smart_selects.db_fields.ChainedForeignKey(auto_choose=True, chained_field='vendor', chained_model_field='vendor', null=True, on_delete=django.db.models.deletion.CASCADE, to='fruit.vendorproduct'),
24
+        ),
25
+    ]

+ 9 - 1
app/fruit/models.py

@@ -191,6 +191,9 @@ class VendorProduct(GenericModel, models.Model):
191 191
     n_unit = models.DecimalField(blank=True, decimal_places=2, max_digits=7, null=True)
192 192
     unit_name = models.CharField(max_length=200, null=True)
193 193
 
194
+    def __str__(self):
195
+        return f"{self.product.name} {self.price}/{self.unit_name}"
196
+
194 197
 class Vendor(GenericModel, models.Model ):
195 198
     name = models.CharField(max_length=200)
196 199
     code = models.CharField(max_length=200)
@@ -223,7 +226,7 @@ class Vendor(GenericModel, models.Model ):
223 226
 class VendorOrder(GenericModel, models.Model):
224 227
     vendor = models.ForeignKey('Vendor', on_delete=models.CASCADE,  null=False, blank=False)
225 228
     product = ChainedForeignKey(
226
-        "Product",
229
+        "VendorProduct",
227 230
         chained_field="vendor",
228 231
         chained_model_field="vendor",
229 232
         show_all=False,
@@ -240,6 +243,7 @@ class VendorOrder(GenericModel, models.Model):
240 243
     vat = models.DecimalField(null=True, blank=True, decimal_places=2, max_digits=10)
241 244
     total = models.DecimalField(null=True, blank=True, decimal_places=2, max_digits=10)
242 245
 
246
+
243 247
     def save(self, *args, **kwargs):
244 248
         self.sub_total = self.price * self.n_unit
245 249
         self.vat  = self.sub_total * decimal.Decimal(VAT)
@@ -280,6 +284,10 @@ class Profile(models.Model):
280 284
 @receiver(post_save, sender=User)
281 285
 def create_user_profile(sender, instance, created, **kwargs):
282 286
     if created:
287
+        store = Store()
288
+        store.name = "Unname"
289
+        store.created_by = instance
290
+        store.save()
283 291
         Profile.objects.create(user=instance)
284 292
 
285 293
 @receiver(post_save, sender=User)

+ 7 - 0
app/fruit/templates/fruit/account_activation_email.html

@@ -0,0 +1,7 @@
1
+{% autoescape off %}
2
+Hi {{ user.username }},
3
+
4
+Please click on the link below to confirm your registration:
5
+
6
+{{ domain }}{% url 'fruit:activate' uidb64=uid token=token %}
7
+{% endautoescape %}

+ 6 - 0
app/fruit/templates/fruit/account_activation_sent.html

@@ -0,0 +1,6 @@
1
+{% extends "front/base.html" %}
2
+
3
+
4
+{% block content  %}
5
+Please confirm ur email to activate account
6
+{% endblock %}

+ 2 - 0
app/fruit/templates/fruit/vendor_form.html

@@ -19,6 +19,7 @@
19 19
     {% csrf_token %}
20 20
     {{ form | crispy  }}
21 21
     <hr>
22
+    {% if obj %}
22 23
     <a href="{% url "fruit:vendorproduct_create" pk=obj.id %}" class='btn btn-primary'>Create Product</a>
23 24
     <h2>Products</h2>
24 25
     <table class='table table-borded table-striped'>
@@ -40,6 +41,7 @@
40 41
     </tbody>
41 42
     </table>
42 43
     <br>
44
+    {% endif %}
43 45
     <input type='submit' class='btn btn-primary' value="Update" />
44 46
 
45 47
 </form>

+ 11 - 0
app/fruit/tokens.py

@@ -0,0 +1,11 @@
1
+from django.contrib.auth.tokens import PasswordResetTokenGenerator
2
+import six
3
+
4
+class AccountActivationTokenGenerator(PasswordResetTokenGenerator):
5
+    def _make_hash_value(self, user, timestamp):
6
+        return (
7
+            six.text_type(user.pk) + six.text_type(timestamp) +
8
+            six.text_type(user.email)
9
+        )
10
+
11
+account_activation_token = AccountActivationTokenGenerator()

+ 4 - 0
app/fruit/urls.py

@@ -24,6 +24,10 @@ urlpatterns = [
24 24
     path('vendororder/create', views.vendororder_create, name='vendororder_create'),
25 25
     path('vendororder/<pk>', views.vendororder_edit, name='vendororder_edit'),
26 26
     path('signup', views.signup, name='signup'),
27
+    path('account_activation_sent', views.account_activation_sent, name='account_activation_sent'),
28
+    path(r'activate/<uidb64>/<token>/',
29
+        views.activate, name='activate'),
30
+
27 31
 ]
28 32
 
29 33
 app_name = 'fruit'

+ 48 - 12
app/fruit/views.py

@@ -8,10 +8,18 @@ from django.contrib.auth.decorators import login_required
8 8
 
9 9
 from fruit.models import Store, Product, Photo, ProductSKU, Sale, Inbox, Vendor, VendorProduct
10 10
 
11
-from .forms import StoreForm, ProductForm, InboxForm, SaleForm,  PhotoFormSet,VendorFilter,  InlinePhotoFormset, ProductSKUForm, ProductFilter, SaleFilter, InboxFilter, VendorForm, VendorOrderForm, VendorOrderFilter, VendorOrder, InlineVendorProductFormset, VendorProductForm
11
+from .forms import StoreForm, ProductForm, InboxForm, SaleForm,  PhotoFormSet,VendorFilter,  InlinePhotoFormset, ProductSKUForm, ProductFilter, SaleFilter, InboxFilter, VendorForm, VendorOrderForm, VendorOrderFilter, VendorOrder, InlineVendorProductFormset, VendorProductForm, SignUpForm
12 12
 from django.contrib import messages
13 13
 from django.core.paginator import Paginator
14 14
 
15
+from django.utils.encoding import force_bytes, force_text
16
+from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode
17
+from django.template.loader import render_to_string
18
+from .tokens import account_activation_token
19
+
20
+
21
+from django.contrib.auth.models import User
22
+
15 23
 
16 24
 def index(request):
17 25
     return render(request, 'fruit/index.html')
@@ -304,7 +312,7 @@ def vendor_create(request):
304 312
 
305 313
     form = VendorForm()
306 314
 
307
-    form.fields['products'].queryset = stores[0].product_set.all().order_by("-created_at")
315
+    #form.fields['products'].queryset = stores[0].product_set.all().order_by("-created_at")
308 316
 
309 317
     if request.method == "POST":
310 318
         form = VendorForm(request.POST)
@@ -417,7 +425,7 @@ def vendororder_edit(request, pk):
417 425
 
418 426
     obj = VendorOrder.objects.get(pk=pk)
419 427
     form = VendorOrderForm(instance = obj)
420
-
428
+    form.fields['vendor'].queryset = stores[0].vendor_set.all().order_by("-created_at")
421 429
     #form.fields['product'].queryset = stores[0].product_set.all().order_by("-created_at")
422 430
 
423 431
     if request.method == "POST":
@@ -445,7 +453,8 @@ def vendororder_create(request):
445 453
     stores = request.user.store_created.all().order_by("-created_at")
446 454
 
447 455
     form = VendorOrderForm()
448
-
456
+    form.fields['vendor'].queryset = stores[0].vendor_set.all().order_by("-created_at")
457
+    #form = stores[0].vendor_set.all()
449 458
 
450 459
     if request.method == "POST":
451 460
         form = VendorOrderForm(request.POST)
@@ -472,14 +481,41 @@ def vendororder_create(request):
472 481
 
473 482
 def signup(request):
474 483
     if request.method == 'POST':
475
-        form = UserCreationForm(request.POST)
484
+        form = SignUpForm(request.POST)
476 485
         if form.is_valid():
477
-            form.save()
478
-            username = form.cleaned_data.get('username')
479
-            raw_password = form.cleaned_data.get('password1')
480
-            user = authenticate(username=username, password=raw_password)
481
-            login(request, user)
482
-            return redirect('front:index')
486
+            user = form.save(commit=False)
487
+            user.is_active = False
488
+            user.save()
489
+            current_site = "https://localhost:8000"
490
+            subject = 'Activate Your MySite Account'
491
+            message = render_to_string('fruit/account_activation_email.html', {
492
+                'user': user,
493
+                'domain': current_site,
494
+                'uid': urlsafe_base64_encode(force_bytes(user.pk)),
495
+                'token': account_activation_token.make_token(user),
496
+            })
497
+            user.email_user(subject, message)
498
+            return redirect('fruit:account_activation_sent')
499
+
483 500
     else:
484
-        form = UserCreationForm()
501
+        form = SignUpForm()
485 502
     return render(request, 'fruit/signup.html', {'form': form})
503
+
504
+def activate(request, uidb64, token):
505
+    try:
506
+        uid = force_text(urlsafe_base64_decode(uidb64))
507
+        user = User.objects.get(pk=uid)
508
+    except (TypeError, ValueError, OverflowError, User.DoesNotExist):
509
+        user = None
510
+
511
+    if user is not None and account_activation_token.check_token(user, token):
512
+        user.is_active = True
513
+        user.profile.email_confirmed = True
514
+        user.save()
515
+        login(request, user)
516
+        return redirect('front:index')
517
+    else:
518
+        return render(request, 'account_activation_invalid.html')
519
+
520
+def account_activation_sent(request):
521
+    return render(request, "fruit/account_activation_sent.html")

BIN
app/shaqfindbed/__pycache__/settings.cpython-39.pyc


+ 7 - 0
app/shaqfindbed/settings.py

@@ -74,6 +74,13 @@ MIDDLEWARE = [
74 74
     'django.middleware.clickjacking.XFrameOptionsMiddleware',
75 75
 ]
76 76
 
77
+EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
78
+EMAIL_HOST = 'smtp.gmail.com'
79
+EMAIL_HOST_USER = 'tech@simplico.net'
80
+EMAIL_HOST_PASSWORD = 'SteveJobs1984'
81
+EMAIL_PORT = 587
82
+EMAIL_USE_TLS = True
83
+DEFAULT_FROM_EMAIL = EMAIL_HOST_USER
77 84
 ROOT_URLCONF = 'shaqfindbed.urls'
78 85
 
79 86
 TEMPLATES = [