├── .gitignore ├── InstaClone ├── authentication │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── forms.py │ ├── migrations │ │ └── __init__.py │ ├── models.py │ ├── tests.py │ ├── urls.py │ └── views.py ├── core │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── forms.py │ ├── migrations │ │ ├── 0001_initial.py │ │ ├── 0002_auto_20201223_1612.py │ │ ├── 0003_auto_20201223_1631.py │ │ ├── 0004_remove_follow_is_follow.py │ │ ├── 0005_auto_20210224_1548.py │ │ ├── 0006_auto_20210224_1548.py │ │ ├── 0007_auto_20210224_1549.py │ │ ├── 0008_auto_20210227_1657.py │ │ ├── 0009_savedpost.py │ │ └── __init__.py │ ├── models.py │ ├── tests.py │ ├── urls.py │ ├── utils.py │ └── views.py ├── insta_clone │ ├── __init__.py │ ├── asgi.py │ ├── settings.py │ ├── urls.py │ └── wsgi.py ├── manage.py ├── media │ ├── post_images │ │ ├── Walrus_operator.png │ │ ├── and_operator.png │ │ ├── host_static_websites.png │ │ ├── host_static_websites_I97YUc9.png │ │ ├── todoapp_playlist_marketing.png │ │ ├── todoapp_playlist_marketing_laAwEhM.png │ │ └── weather_dashboard_playlist_marketing.png │ └── profile_pictures │ │ ├── D.png │ │ └── fresh_logo_circle.png ├── static_files │ ├── img │ │ ├── appstore.png │ │ ├── instalogo.png │ │ ├── no-posts1.jpg │ │ ├── no-posts2.jpg │ │ ├── phone_img.png │ │ └── playstore.png │ └── styles │ │ ├── authentication │ │ ├── main.css │ │ ├── password_change.css │ │ ├── password_reset.css │ │ ├── signin.css │ │ └── signup.css │ │ ├── core │ │ ├── main.css │ │ ├── navbar.css │ │ └── post_card.css │ │ └── user │ │ ├── all_profiles.css │ │ ├── profile.css │ │ └── profile_edit.css ├── templates │ ├── authentication │ │ ├── base.html │ │ ├── components │ │ │ └── no_login_navbar.html │ │ ├── password_change.html │ │ ├── password_change_done.html │ │ ├── password_reset.html │ │ ├── password_reset_complete.html │ │ ├── password_reset_confirm.html │ │ ├── password_reset_done.html │ │ ├── password_reset_email.html │ │ ├── signin.html │ │ └── signup.html │ ├── components │ │ ├── navbar.html │ │ ├── post_card.html │ │ └── post_detail_card.html │ ├── core │ │ ├── base.html │ │ ├── feed.html │ │ ├── liked_posts.html │ │ ├── post_detail.html │ │ ├── posts_explore.html │ │ └── saved_posts.html │ └── user │ │ ├── all_profiles.html │ │ ├── anonymous_profile.html │ │ ├── authenticated_profile.html │ │ └── profile_edit.html └── user │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── forms.py │ ├── managers.py │ ├── migrations │ ├── 0001_initial.py │ ├── 0002_auto_20201201_1649.py │ ├── 0003_auto_20201203_1638.py │ ├── 0004_auto_20201203_1638.py │ ├── 0005_auto_20201211_1656.py │ ├── 0006_auto_20210219_1614.py │ ├── 0007_auto_20210222_1610.py │ ├── 0008_auto_20210224_1546.py │ └── __init__.py │ ├── models.py │ ├── tests.py │ ├── urls.py │ └── views.py ├── ToDoApp ├── manage.py ├── mytodo │ ├── __init__.py │ ├── __pycache__ │ │ ├── __init__.cpython-38.pyc │ │ ├── admin.cpython-38.pyc │ │ ├── forms.cpython-38.pyc │ │ ├── models.cpython-38.pyc │ │ ├── urls.cpython-38.pyc │ │ └── views.cpython-38.pyc │ ├── admin.py │ ├── apps.py │ ├── forms.py │ ├── migrations │ │ ├── 0001_initial.py │ │ ├── 0002_auto_20201120_1628.py │ │ ├── 0003_auto_20201128_1440.py │ │ ├── __init__.py │ │ └── __pycache__ │ │ │ ├── 0001_initial.cpython-38.pyc │ │ │ ├── 0002_auto_20201120_1628.cpython-38.pyc │ │ │ ├── 0003_auto_20201128_1440.cpython-38.pyc │ │ │ └── __init__.cpython-38.pyc │ ├── models.py │ ├── static │ │ └── styles.css │ ├── templates │ │ ├── base.html │ │ ├── components │ │ │ └── footer.html │ │ ├── edit.html │ │ └── home.html │ ├── tests.py │ ├── urls.py │ └── views.py ├── requirements.txt └── todo │ ├── __init__.py │ ├── __pycache__ │ ├── __init__.cpython-38.pyc │ ├── settings.cpython-38.pyc │ ├── urls.cpython-38.pyc │ └── wsgi.cpython-38.pyc │ ├── asgi.py │ ├── settings.py │ ├── urls.py │ └── wsgi.py └── WeatherDashboard ├── WeatherDashboard ├── __init__.py ├── __pycache__ │ ├── __init__.cpython-38.pyc │ ├── settings.cpython-38.pyc │ ├── urls.cpython-38.pyc │ └── wsgi.cpython-38.pyc ├── asgi.py ├── settings.py ├── urls.py └── wsgi.py ├── dashboard ├── __init__.py ├── __pycache__ │ ├── __init__.cpython-38.pyc │ ├── admin.cpython-38.pyc │ ├── forms.cpython-38.pyc │ ├── helper.cpython-38.pyc │ ├── models.cpython-38.pyc │ └── views.cpython-38.pyc ├── admin.py ├── apps.py ├── forms.py ├── helper.py ├── migrations │ ├── 0001_initial.py │ ├── __init__.py │ └── __pycache__ │ │ ├── 0001_initial.cpython-38.pyc │ │ └── __init__.cpython-38.pyc ├── models.py ├── static │ ├── styles.css │ └── weather-cloud.jpg ├── templates │ ├── base.html │ ├── components │ │ ├── card.html │ │ ├── footer.html │ │ └── sideform.html │ ├── history.html │ └── home.html ├── tests.py └── views.py ├── manage.py └── requirements.txt /.gitignore: -------------------------------------------------------------------------------- 1 | emails/ 2 | TestDemo/ 3 | 4 | # Byte-compiled / optimized / DLL files 5 | __pycache__/ 6 | *.py[cod] 7 | *$py.class 8 | 9 | # C extensions 10 | *.so 11 | 12 | # Distribution / packaging 13 | .Python 14 | build/ 15 | develop-eggs/ 16 | dist/ 17 | downloads/ 18 | eggs/ 19 | .eggs/ 20 | lib/ 21 | lib64/ 22 | parts/ 23 | sdist/ 24 | var/ 25 | wheels/ 26 | pip-wheel-metadata/ 27 | share/python-wheels/ 28 | *.egg-info/ 29 | .installed.cfg 30 | *.egg 31 | MANIFEST 32 | 33 | # PyInstaller 34 | # Usually these files are written by a python script from a template 35 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 36 | *.manifest 37 | *.spec 38 | 39 | # Installer logs 40 | pip-log.txt 41 | pip-delete-this-directory.txt 42 | 43 | # Unit test / coverage reports 44 | htmlcov/ 45 | .tox/ 46 | .nox/ 47 | .coverage 48 | .coverage.* 49 | .cache 50 | nosetests.xml 51 | coverage.xml 52 | *.cover 53 | *.py,cover 54 | .hypothesis/ 55 | .pytest_cache/ 56 | 57 | # Translations 58 | *.mo 59 | *.pot 60 | 61 | # Django stuff: 62 | *.log 63 | local_settings.py 64 | db.sqlite3 65 | db.sqlite3-journal 66 | 67 | # Flask stuff: 68 | instance/ 69 | .webassets-cache 70 | 71 | # Scrapy stuff: 72 | .scrapy 73 | 74 | # Sphinx documentation 75 | docs/_build/ 76 | 77 | # PyBuilder 78 | target/ 79 | 80 | # Jupyter Notebook 81 | .ipynb_checkpoints 82 | 83 | # IPython 84 | profile_default/ 85 | ipython_config.py 86 | 87 | # pyenv 88 | .python-version 89 | 90 | # pipenv 91 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 92 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 93 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 94 | # install all needed dependencies. 95 | #Pipfile.lock 96 | 97 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 98 | __pypackages__/ 99 | 100 | # Celery stuff 101 | celerybeat-schedule 102 | celerybeat.pid 103 | 104 | # SageMath parsed files 105 | *.sage.py 106 | 107 | # Environments 108 | .env 109 | .venv 110 | env/ 111 | venv/ 112 | ENV/ 113 | env.bak/ 114 | venv.bak/ 115 | 116 | # Spyder project settings 117 | .spyderproject 118 | .spyproject 119 | 120 | # Rope project settings 121 | .ropeproject 122 | 123 | # mkdocs documentation 124 | /site 125 | 126 | # mypy 127 | .mypy_cache/ 128 | .dmypy.json 129 | dmypy.json 130 | 131 | # Pyre type checker 132 | .pyre/ 133 | -------------------------------------------------------------------------------- /InstaClone/authentication/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mnamegaurav/easy_django/a9b959f1e436a74a513ff5f9d948eb6cd8813a10/InstaClone/authentication/__init__.py -------------------------------------------------------------------------------- /InstaClone/authentication/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | # Register your models here. 4 | -------------------------------------------------------------------------------- /InstaClone/authentication/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class AuthenticationConfig(AppConfig): 5 | name = 'authentication' 6 | -------------------------------------------------------------------------------- /InstaClone/authentication/forms.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | from django.contrib.auth.forms import UserCreationForm, UserChangeForm 3 | from django.contrib.auth import get_user_model 4 | 5 | 6 | class UserForm(UserCreationForm): 7 | class Meta: 8 | model = get_user_model() 9 | fields = ('full_name', 'email', 'username', 'password1', 'password2') 10 | 11 | 12 | class CustomUserChangeForm(UserChangeForm): 13 | class Meta: 14 | model = get_user_model() 15 | fields = ('full_name', 'email', 'username',) -------------------------------------------------------------------------------- /InstaClone/authentication/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mnamegaurav/easy_django/a9b959f1e436a74a513ff5f9d948eb6cd8813a10/InstaClone/authentication/migrations/__init__.py -------------------------------------------------------------------------------- /InstaClone/authentication/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | # Create your models here. 4 | -------------------------------------------------------------------------------- /InstaClone/authentication/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /InstaClone/authentication/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | from authentication.views import ( 3 | SignInView, 4 | SignUpView, 5 | SignOutView, 6 | PRView, PRDone, PRConfirm, PRComplete, 7 | PWDChangeView, PWDChangeDoneView, 8 | ) 9 | from django.urls import reverse_lazy 10 | 11 | 12 | from django.contrib.auth.views import ( 13 | PasswordResetView, 14 | PasswordResetDoneView, 15 | PasswordResetConfirmView, 16 | PasswordResetCompleteView, 17 | PasswordChangeView, 18 | PasswordChangeDoneView, 19 | ) 20 | 21 | 22 | urlpatterns = [ 23 | path('', SignInView.as_view(), name='signin_view'), 24 | path('signup/', SignUpView.as_view(), name='signup_view'), 25 | path('signout/', SignOutView.as_view(), name='signout_view'), 26 | 27 | # path('password/reset/', PRView.as_view(), name='password_reset'), 28 | # path('password/reset/done/', PRDone.as_view() ,name='password_reset_done'), 29 | # path('password/reset/confirm//', PRConfirm.as_view() , name='password_reset_confirm'), 30 | # path('password/reset/complete/', PRComplete.as_view() , name='password_reset_complete'), 31 | 32 | path('password/reset/', 33 | PasswordResetView.as_view( 34 | email_template_name = 'authentication/password_reset_email.html', 35 | template_name = 'authentication/password_reset.html', 36 | ), 37 | name='password_reset'), 38 | 39 | path('password/reset/done/', 40 | PasswordResetDoneView.as_view( 41 | template_name = 'authentication/password_reset_done.html' 42 | ) , 43 | name='password_reset_done'), 44 | 45 | path('password/reset/confirm//', 46 | PasswordResetConfirmView.as_view( 47 | template_name = 'authentication/password_reset_confirm.html' 48 | ) , 49 | name='password_reset_confirm'), 50 | 51 | path('password/reset/complete/', 52 | PasswordResetCompleteView.as_view( 53 | template_name = 'authentication/password_reset_complete.html' 54 | ) , 55 | name='password_reset_complete'), 56 | 57 | # path( 58 | # 'password/change/', 59 | # PWDChangeView.as_view(), 60 | # name='password_change_view' 61 | # ), 62 | # path( 63 | # 'password/change/done/', 64 | # PWDChangeDoneView.as_view(), 65 | # name='password_change_done_view' 66 | # ), 67 | 68 | path( 69 | 'password/change/', 70 | PasswordChangeView.as_view( 71 | template_name = 'authentication/password_change.html', 72 | success_url = reverse_lazy('password_change_done_view') 73 | ), 74 | name='password_change_view' 75 | ), 76 | path( 77 | 'password/change/done/', 78 | PasswordResetDoneView.as_view( 79 | template_name = 'authentication/password_change_done.html' 80 | ), 81 | name='password_change_done_view' 82 | ) 83 | ] 84 | 85 | # PasswordResetView ->> Ask for Email 86 | # PasswordResetDoneView ->> Show him success email message 87 | # PasswordResetConfirmView ->> Ask to set a new password 88 | # PasswordResetCompleteView ->> Successfully set your password login -------------------------------------------------------------------------------- /InstaClone/authentication/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render, redirect 2 | from django.views.generic import View 3 | from django.contrib import messages 4 | from django.http import HttpResponse 5 | from django.urls import reverse_lazy 6 | from authentication.forms import UserForm 7 | from django.contrib.auth import ( 8 | authenticate, 9 | login, logout, 10 | get_user_model, 11 | ) 12 | from django.contrib.auth.views import ( 13 | PasswordResetView, 14 | PasswordResetDoneView, 15 | PasswordResetConfirmView, 16 | PasswordResetCompleteView, 17 | PasswordChangeView, 18 | PasswordChangeDoneView, 19 | ) 20 | # Create your views here. 21 | 22 | User = get_user_model() 23 | 24 | class SignInView(View): 25 | template_name = 'authentication/signin.html' 26 | 27 | def get(self, request, *args, **kwargs): 28 | if request.user.is_authenticated: 29 | return redirect('home_feed_view') 30 | return render(request, self.template_name) 31 | 32 | def post(self, request, *args, **kwargs): 33 | email_username = request.POST.get('email_username') 34 | password = request.POST.get('password') 35 | 36 | try: 37 | user_obj = User.objects.get(username=email_username) 38 | email = user_obj.email 39 | except Exception as e: 40 | email = email_username 41 | 42 | user = authenticate(request, email=email, password=password) 43 | 44 | if user is None: 45 | messages.error(request, 'Invalid Login.', extra_tags="error") 46 | return render(request, self.template_name) 47 | 48 | login(request, user) 49 | messages.success(request, 'Thanks for Login, Welcome to Insta Clone.', extra_tags='success') 50 | return redirect('home_feed_view') 51 | 52 | 53 | 54 | class SignUpView(View): 55 | template_name = 'authentication/signup.html' 56 | form_class = UserForm 57 | 58 | def get(self, request, *args, **kwargs): 59 | if request.user.is_authenticated: 60 | return redirect('home_feed_view') 61 | # ye wala code run kardo 62 | return render(request, self.template_name) 63 | 64 | def post(self, request, *args, **kwargs): 65 | # ye wala code run kardo 66 | form = self.form_class(request.POST) 67 | if form.is_valid(): 68 | form.save() 69 | return redirect('signin_view') 70 | 71 | context = {'form': form} 72 | 73 | return render(request, self.template_name, context) 74 | 75 | 76 | class SignOutView(View): 77 | def post(self, request, *args, **kwargs): 78 | # is user is not authenticated 79 | logout(request) 80 | return redirect('signin_view') 81 | 82 | 83 | class PRView(PasswordResetView): 84 | email_template_name = 'authentication/password_reset_email.html' 85 | template_name = 'authentication/password_reset.html' 86 | 87 | class PRDone(PasswordResetDoneView): 88 | template_name = 'authentication/password_reset_done.html' 89 | 90 | class PRConfirm(PasswordResetConfirmView): 91 | template_name = 'authentication/password_reset_confirm.html' 92 | 93 | class PRComplete(PasswordResetCompleteView): 94 | template_name = 'authentication/password_reset_complete.html' 95 | 96 | 97 | class PWDChangeView(PasswordChangeView): 98 | template_name = 'authentication/password_change.html' 99 | success_url = reverse_lazy('password_change_done_view') 100 | 101 | class PWDChangeDoneView(PasswordChangeDoneView): 102 | template_name = 'authentication/password_change_done.html' -------------------------------------------------------------------------------- /InstaClone/core/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mnamegaurav/easy_django/a9b959f1e436a74a513ff5f9d948eb6cd8813a10/InstaClone/core/__init__.py -------------------------------------------------------------------------------- /InstaClone/core/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from core.models import ( 3 | Post, 4 | Comment, 5 | Like, 6 | Follow, 7 | SavedPost, 8 | ) 9 | # Register your models here. 10 | 11 | class PostModelAdmin(admin.ModelAdmin): 12 | model = Post 13 | list_display = ('text', 'image', 'user', 'created_on', 'updated_on') 14 | 15 | 16 | class CommentModelAdmin(admin.ModelAdmin): 17 | model = Comment 18 | list_display = ('text', 'post', 'user', 'commented_on', 'updated_on') 19 | 20 | 21 | class LikeModelAdmin(admin.ModelAdmin): 22 | model = Like 23 | list_display = ('post', 'user', 'liked_on', 'updated_on') 24 | 25 | 26 | class FollowModelAdmin(admin.ModelAdmin): 27 | model = Follow 28 | list_display = ('user', 'followed', 'followed_on', 'updated_on') 29 | 30 | class SavedPostModelAdmin(admin.ModelAdmin): 31 | model = SavedPost 32 | list_display = ('post', 'user', 'saved_on') 33 | 34 | 35 | admin.site.register(Post, PostModelAdmin) 36 | admin.site.register(Comment, CommentModelAdmin) 37 | admin.site.register(Like, LikeModelAdmin) 38 | admin.site.register(Follow, FollowModelAdmin) 39 | admin.site.register(SavedPost, SavedPostModelAdmin) -------------------------------------------------------------------------------- /InstaClone/core/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class CoreConfig(AppConfig): 5 | name = 'core' 6 | -------------------------------------------------------------------------------- /InstaClone/core/forms.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | from core.models import Post 3 | 4 | class PostCreateForm(forms.ModelForm): 5 | class Meta: 6 | model = Post 7 | fields = ('text', 'image') 8 | widgets = { 9 | 'text': forms.TextInput(attrs={ 10 | 'class': 'form-control form-control-sm', 11 | 'placeholder': 'Caption this...' 12 | } 13 | ) 14 | } -------------------------------------------------------------------------------- /InstaClone/core/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.1.4 on 2020-12-21 16:56 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 | initial = True 11 | 12 | dependencies = [ 13 | migrations.swappable_dependency(settings.AUTH_USER_MODEL), 14 | ] 15 | 16 | operations = [ 17 | migrations.CreateModel( 18 | name='Post', 19 | fields=[ 20 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 21 | ('text', models.CharField(blank=True, max_length=140, null=True)), 22 | ('image', models.ImageField(upload_to='post_images')), 23 | ('created_on', models.DateTimeField(auto_now_add=True)), 24 | ('updated_on', models.DateTimeField(auto_now=True)), 25 | ('user', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL)), 26 | ], 27 | ), 28 | migrations.CreateModel( 29 | name='Like', 30 | fields=[ 31 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 32 | ('is_like', models.BooleanField(default=True)), 33 | ('liked_on', models.DateTimeField(auto_now_add=True)), 34 | ('updated_on', models.DateTimeField(auto_now=True)), 35 | ('post', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.post')), 36 | ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), 37 | ], 38 | ), 39 | migrations.CreateModel( 40 | name='Follow', 41 | fields=[ 42 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 43 | ('is_follow', models.BooleanField(default=True)), 44 | ('followed_on', models.DateTimeField(auto_now_add=True)), 45 | ('updated_on', models.DateTimeField(auto_now=True)), 46 | ('follower', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='follow_follower', to=settings.AUTH_USER_MODEL)), 47 | ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='follow_user', to=settings.AUTH_USER_MODEL)), 48 | ], 49 | ), 50 | migrations.CreateModel( 51 | name='Comment', 52 | fields=[ 53 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 54 | ('text', models.CharField(max_length=240)), 55 | ('commented_on', models.DateTimeField(auto_now_add=True)), 56 | ('updated_on', models.DateTimeField(auto_now=True)), 57 | ('post', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.post')), 58 | ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), 59 | ], 60 | ), 61 | ] 62 | -------------------------------------------------------------------------------- /InstaClone/core/migrations/0002_auto_20201223_1612.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.1.4 on 2020-12-23 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 | ('core', '0001_initial'), 13 | ] 14 | 15 | operations = [ 16 | migrations.AlterField( 17 | model_name='post', 18 | name='user', 19 | field=models.ForeignKey(editable=False, on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL), 20 | ), 21 | ] 22 | -------------------------------------------------------------------------------- /InstaClone/core/migrations/0003_auto_20201223_1631.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.1.4 on 2020-12-23 16:31 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 | ('core', '0002_auto_20201223_1612'), 13 | ] 14 | 15 | operations = [ 16 | migrations.AlterField( 17 | model_name='comment', 18 | name='user', 19 | field=models.ForeignKey(editable=False, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL), 20 | ), 21 | migrations.AlterField( 22 | model_name='follow', 23 | name='user', 24 | field=models.ForeignKey(editable=False, on_delete=django.db.models.deletion.CASCADE, related_name='follow_user', to=settings.AUTH_USER_MODEL), 25 | ), 26 | migrations.AlterField( 27 | model_name='like', 28 | name='user', 29 | field=models.ForeignKey(editable=False, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL), 30 | ), 31 | ] 32 | -------------------------------------------------------------------------------- /InstaClone/core/migrations/0004_remove_follow_is_follow.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.1.3 on 2021-02-24 15:46 2 | 3 | from django.db import migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('core', '0003_auto_20201223_1631'), 10 | ] 11 | 12 | operations = [ 13 | migrations.RemoveField( 14 | model_name='follow', 15 | name='is_follow', 16 | ), 17 | ] 18 | -------------------------------------------------------------------------------- /InstaClone/core/migrations/0005_auto_20210224_1548.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.1.3 on 2021-02-24 15:48 2 | 3 | from django.db import migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('core', '0004_remove_follow_is_follow'), 10 | ] 11 | 12 | operations = [ 13 | migrations.RenameField( 14 | model_name='follow', 15 | old_name='follower', 16 | new_name='followed', 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /InstaClone/core/migrations/0006_auto_20210224_1548.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.1.3 on 2021-02-24 15: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 | ('core', '0005_auto_20210224_1548'), 13 | ] 14 | 15 | operations = [ 16 | migrations.AlterField( 17 | model_name='follow', 18 | name='followed', 19 | field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='follow_followed', to=settings.AUTH_USER_MODEL), 20 | ), 21 | ] 22 | -------------------------------------------------------------------------------- /InstaClone/core/migrations/0007_auto_20210224_1549.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.1.3 on 2021-02-24 15:49 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 | ('core', '0006_auto_20210224_1548'), 13 | ] 14 | 15 | operations = [ 16 | migrations.AlterField( 17 | model_name='follow', 18 | name='user', 19 | field=models.ForeignKey(editable=False, on_delete=django.db.models.deletion.CASCADE, related_name='follow_follower', to=settings.AUTH_USER_MODEL), 20 | ), 21 | ] 22 | -------------------------------------------------------------------------------- /InstaClone/core/migrations/0008_auto_20210227_1657.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.1.3 on 2021-02-27 16:57 2 | 3 | from django.db import migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('core', '0007_auto_20210224_1549'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterModelOptions( 14 | name='post', 15 | options={'ordering': ['-created_on']}, 16 | ), 17 | migrations.RemoveField( 18 | model_name='like', 19 | name='is_like', 20 | ), 21 | ] 22 | -------------------------------------------------------------------------------- /InstaClone/core/migrations/0009_savedpost.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.1.1 on 2021-02-28 16:03 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 | ('core', '0008_auto_20210227_1657'), 13 | ] 14 | 15 | operations = [ 16 | migrations.CreateModel( 17 | name='SavedPost', 18 | fields=[ 19 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 20 | ('saved_on', models.DateTimeField(auto_now_add=True)), 21 | ('post', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.post')), 22 | ('user', models.ForeignKey(editable=False, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), 23 | ], 24 | ), 25 | ] 26 | -------------------------------------------------------------------------------- /InstaClone/core/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mnamegaurav/easy_django/a9b959f1e436a74a513ff5f9d948eb6cd8813a10/InstaClone/core/migrations/__init__.py -------------------------------------------------------------------------------- /InstaClone/core/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | from django.contrib.auth import get_user_model 3 | 4 | from core.utils import auto_save_current_user 5 | # Create your models here. 6 | 7 | User = get_user_model() 8 | 9 | 10 | # Posts Model 11 | class Post(models.Model): 12 | # id = models.AutoField(primary_key=True) # generated by default 13 | text = models.CharField(max_length=140, blank=True, null=True) # null == None, blank = '' 14 | image = models.ImageField(upload_to='post_images') # BASE_DIR -> media -> post_images 15 | user = models.ForeignKey(User, on_delete=models.PROTECT, editable=False) # user_id 16 | created_on = models.DateTimeField(auto_now_add=True) 17 | updated_on = models.DateTimeField(auto_now=True) 18 | 19 | class Meta: 20 | ordering = ['-created_on'] 21 | 22 | def __str__(self): 23 | return str(self.pk) 24 | 25 | def save(self, *args, **kwargs): 26 | auto_save_current_user(self) 27 | super(Post, self).save(*args, **kwargs) 28 | 29 | @property 30 | def likes_count(self): 31 | count = self.like_set.count() 32 | return count 33 | 34 | @property 35 | def comments_count(self): 36 | count = self.comment_set.count() 37 | return count 38 | 39 | 40 | # Comments Model 41 | class Comment(models.Model): 42 | text = models.CharField(max_length=240) 43 | post = models.ForeignKey(Post, on_delete=models.CASCADE) 44 | user = models.ForeignKey(User, on_delete=models.CASCADE, editable=False) 45 | commented_on = models.DateTimeField(auto_now_add=True) 46 | updated_on = models.DateTimeField(auto_now=True) 47 | 48 | def __str__(self): 49 | return self.text 50 | 51 | def save(self, *args, **kwargs): 52 | auto_save_current_user(self) 53 | super(Comment, self).save(*args, **kwargs) 54 | 55 | # Likes Model 56 | class Like(models.Model): 57 | post = models.ForeignKey(Post, on_delete=models.CASCADE) 58 | user = models.ForeignKey(User, on_delete=models.CASCADE, editable=False) 59 | liked_on = models.DateTimeField(auto_now_add=True) 60 | updated_on = models.DateTimeField(auto_now=True) 61 | 62 | def __str__(self): 63 | return str(self.post.id) 64 | 65 | def save(self, *args, **kwargs): 66 | auto_save_current_user(self) 67 | super(Like, self).save(*args, **kwargs) 68 | 69 | # Followers Model 70 | class Follow(models.Model): 71 | user = models.ForeignKey(User, related_name='follow_follower', on_delete=models.CASCADE, editable=False) 72 | followed = models.ForeignKey(User, related_name='follow_followed', on_delete=models.CASCADE) 73 | followed_on = models.DateTimeField(auto_now_add=True) 74 | updated_on = models.DateTimeField(auto_now=True) 75 | 76 | 77 | def __str__(self): 78 | return f"{self.user} --> {self.followed}" 79 | 80 | def save(self, *args, **kwargs): 81 | auto_save_current_user(self) 82 | super(Follow, self).save(*args, **kwargs) 83 | 84 | 85 | class SavedPost(models.Model): 86 | post = models.ForeignKey(Post, on_delete=models.CASCADE) 87 | user = models.ForeignKey(User, on_delete=models.CASCADE, editable=False) 88 | saved_on = models.DateTimeField(auto_now_add=True) 89 | 90 | def __str__(self): 91 | return str(self.post.pk) 92 | 93 | def save(self, *args, **kwargs): 94 | auto_save_current_user(self) 95 | super(SavedPost, self).save(*args, **kwargs) -------------------------------------------------------------------------------- /InstaClone/core/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /InstaClone/core/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | from core.views import ( 3 | HomeView, 4 | FollowDoneView, 5 | UnfollowDoneView, 6 | PostCreatView, 7 | PostDeleteView, 8 | PostDetailView, 9 | PostLikeView, 10 | PostUnlikeView, 11 | PostCommentView, 12 | PostSaveView, 13 | PostUnsaveView, 14 | LikedPostsView, 15 | ExplorePostsView, 16 | SavedPostsView, 17 | ) 18 | from django.contrib.auth.decorators import login_required 19 | 20 | urlpatterns = [ 21 | path('feed/', login_required(HomeView.as_view()), name='home_feed_view'), 22 | 23 | # follow and unfollow view 24 | path('follow/done/', login_required(FollowDoneView.as_view()), name='follow_done_view'), 25 | path('unfollow/done/', login_required(UnfollowDoneView.as_view()), name='unfollow_done_view'), 26 | 27 | # post related urls 28 | path('post//', login_required(PostDetailView.as_view()), name='post_detail_view'), 29 | path('post/create/', login_required(PostCreatView.as_view()), name='post_create_view'), 30 | path('post/delete//', login_required(PostDeleteView.as_view()), name='post_delete_view'), 31 | path('post/save//', login_required(PostSaveView.as_view()), name='post_save_view'), 32 | path('post/unsave//', login_required(PostUnsaveView.as_view()), name='post_unsave_view'), 33 | 34 | path('post/liked/', login_required(LikedPostsView.as_view()), name='liked_posts_view'), 35 | path('post/saved/', login_required(SavedPostsView.as_view()), name='saved_posts_view'), 36 | path('post/explore/', login_required(ExplorePostsView.as_view()), name='explore_posts_view'), 37 | 38 | path('post/like//', PostLikeView.as_view(), name='post_like_view'), 39 | path('post/unlike//', PostUnlikeView.as_view(), name='post_unlike_view'), 40 | path('post/comment//', PostCommentView.as_view(), name='post_comment_view'), 41 | ] -------------------------------------------------------------------------------- /InstaClone/core/utils.py: -------------------------------------------------------------------------------- 1 | from crum import get_current_user 2 | 3 | 4 | # to save currently logged in user by model itself 5 | def auto_save_current_user(obj): 6 | user = get_current_user() 7 | if user and not user.pk: 8 | user = None 9 | if not obj.pk: 10 | obj.user = user -------------------------------------------------------------------------------- /InstaClone/core/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render, redirect 2 | from django.views.generic import TemplateView, View 3 | from django.contrib.auth import get_user_model 4 | from django.db.models import Count 5 | 6 | from core.models import ( 7 | Follow, 8 | Post, 9 | Like, 10 | Comment, 11 | SavedPost 12 | ) 13 | from core.forms import PostCreateForm 14 | 15 | User = get_user_model() 16 | # Create your views here. 17 | class HomeView(View): 18 | template_name = 'core/feed.html' 19 | form_class = PostCreateForm 20 | 21 | def get(self, request, *arga, **kwargs): 22 | form = self.form_class() 23 | all_posts = Post.objects.all() 24 | context = { 'form': form, 'all_posts': all_posts } 25 | return render(request, self.template_name, context=context) 26 | 27 | 28 | class PostDetailView(View): 29 | template_name = 'core/post_detail.html' 30 | 31 | def get(self, request, *args, **kwargs): 32 | post_id = kwargs.get('id') 33 | 34 | try: 35 | post_obj = Post.objects.get(pk=post_id) 36 | except Exception as e: 37 | return redirect(request.META.get('HTTP_REFERER')) 38 | 39 | try: 40 | Like.objects.get(user=request.user, post_id=post_id) 41 | liked_this_post = True 42 | except Exception as e: 43 | liked_this_post = False 44 | 45 | try: 46 | SavedPost.objects.get(user=request.user, post_id=post_id) 47 | post_saved = True 48 | except Exception as e: 49 | post_saved = False 50 | 51 | context = { 52 | 'post': post_obj, 53 | 'liked_this_post': liked_this_post, 54 | 'post_saved': post_saved, 55 | } 56 | 57 | return render(request, self.template_name, context=context) 58 | 59 | 60 | class PostCreatView(View): 61 | template_name = 'core/feed.html' 62 | form_class = PostCreateForm 63 | 64 | def post(self, request, *args, **kwargs): 65 | form = self.form_class(request.POST, request.FILES) 66 | 67 | if form.is_valid(): 68 | form.save() 69 | return redirect('home_feed_view') 70 | else: 71 | context = { 'form': form } 72 | return render(request, self.template_name, context=context) 73 | 74 | 75 | class PostDeleteView(View): 76 | 77 | def post(self, request, *args, **kwargs): 78 | post_id = kwargs.get('id') 79 | try: 80 | post_obj = Post.objects.get(pk=post_id) 81 | except Exception as e: 82 | pass 83 | 84 | if request.user == post_obj.user: 85 | post_obj.delete() 86 | 87 | return redirect(request.META.get('HTTP_REFERER')) 88 | 89 | 90 | class PostSaveView(View): 91 | def post(self, request, *args, **kwargs): 92 | post_id = kwargs.get('id') 93 | 94 | try: 95 | post_obj = Post.objects.get(pk=post_id) 96 | except Exception as e: 97 | pass 98 | 99 | try: 100 | SavedPost.objects.create(post_id=post_id) 101 | except Exception as e: 102 | pass 103 | 104 | return redirect(request.META.get('HTTP_REFERER')) 105 | 106 | 107 | class PostUnsaveView(View): 108 | def post(self, request, *args, **kwargs): 109 | post_id = kwargs.get('id') 110 | 111 | try: 112 | savedpost_obj = SavedPost.objects.get(post_id=post_id) 113 | savedpost_obj.delete() 114 | except Exception as e: 115 | pass 116 | 117 | return redirect(request.META.get('HTTP_REFERER')) 118 | 119 | 120 | class PostLikeView(View): 121 | def post(self, request, *args, **kwargs): 122 | post_id = kwargs.get('id') 123 | 124 | try: 125 | Like.objects.get(user=request.user, post_id=post_id) 126 | except Exception as e: 127 | Like.objects.create(post_id=post_id) 128 | 129 | return redirect(request.META.get('HTTP_REFERER')) 130 | 131 | 132 | class PostUnlikeView(View): 133 | def post(self, request, *args, **kwargs): 134 | post_id = kwargs.get('id') 135 | 136 | try: 137 | like_obj = Like.objects.get(user=request.user, post_id=post_id) 138 | like_obj.delete() 139 | except Exception as e: 140 | pass 141 | 142 | return redirect(request.META.get('HTTP_REFERER')) 143 | 144 | 145 | class PostCommentView(View): 146 | def post(self, request, *args, **kwargs): 147 | post_id = kwargs.get('id') 148 | comment_text = request.POST.get('comment_text') 149 | 150 | Comment.objects.create(post_id=post_id, text=comment_text) 151 | 152 | return redirect(request.META.get('HTTP_REFERER')) 153 | 154 | 155 | class FollowDoneView(View): 156 | def post(self, request, *args, **kwargs): 157 | followed_user_id = request.POST.get('followed_user_id') 158 | followed_user_obj = User.objects.get(pk=followed_user_id) 159 | 160 | try: 161 | Follow.objects.get(user=request.user, followed=followed_user_obj) 162 | except Exception as e: 163 | follow_obj = Follow.objects.create(followed=followed_user_obj) 164 | 165 | return redirect(request.META.get('HTTP_REFERER')) 166 | 167 | 168 | class UnfollowDoneView(View): 169 | def post(self, request, *args, **kwargs): 170 | unfollowed_user_id = request.POST.get('unfollowed_user_id') 171 | unfollowed_user_obj = User.objects.get(pk=unfollowed_user_id) 172 | 173 | try: 174 | follow_obj = Follow.objects.get(user=request.user, followed=unfollowed_user_obj) 175 | follow_obj.delete() 176 | except Exception as e: 177 | pass 178 | 179 | return redirect(request.META.get('HTTP_REFERER')) 180 | 181 | 182 | class LikedPostsView(View): 183 | template_name = 'core/liked_posts.html' 184 | def get(self, request, *args, **kwargs): 185 | return render(request, self.template_name) 186 | 187 | 188 | class SavedPostsView(View): 189 | template_name = 'core/saved_posts.html' 190 | def get(self, request, *args, **kwargs): 191 | return render(request, self.template_name) 192 | 193 | 194 | class ExplorePostsView(View): 195 | template_name = 'core/posts_explore.html' 196 | def get(self, request, *args, **kwargs): 197 | 198 | all_posts = Post.objects.annotate(count=Count('like')).order_by('-count') 199 | context = {'all_posts': all_posts} 200 | return render(request, self.template_name, context=context) -------------------------------------------------------------------------------- /InstaClone/insta_clone/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mnamegaurav/easy_django/a9b959f1e436a74a513ff5f9d948eb6cd8813a10/InstaClone/insta_clone/__init__.py -------------------------------------------------------------------------------- /InstaClone/insta_clone/asgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | ASGI config for insta_clone project. 3 | 4 | It exposes the ASGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.1/howto/deployment/asgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.asgi import get_asgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'insta_clone.settings') 15 | 16 | application = get_asgi_application() 17 | -------------------------------------------------------------------------------- /InstaClone/insta_clone/settings.py: -------------------------------------------------------------------------------- 1 | """ 2 | Django settings for insta_clone project. 3 | 4 | Generated by 'django-admin startproject' usign Django 3.1.3. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.1/topics/settings/ 8 | 9 | For the full list of settings and their values, see 10 | https://docs.djangoproject.com/en/3.1/ref/settings/ 11 | """ 12 | 13 | from pathlib import Path 14 | 15 | # Build paths inside the project like this: BASE_DIR / 'subdir'. 16 | BASE_DIR = Path(__file__).resolve().parent.parent 17 | 18 | 19 | # Quick-start development settings - unsuitable for production 20 | # See https://docs.djangoproject.com/en/3.1/howto/deployment/checklist/ 21 | 22 | # SECURITY WARNING: keep the secret key used in production secret! 23 | SECRET_KEY = '23gdwfji#=24-=*0j9n%%j-zjd&h*(5^ireu44^i9vgiuw^+du' 24 | 25 | # SECURITY WARNING: don't run with debug turned on in production! 26 | DEBUG = True 27 | 28 | ALLOWED_HOSTS = [] 29 | 30 | 31 | # Application definition 32 | 33 | INSTALLED_APPS = [ 34 | 'django.contrib.admin', 35 | 'django.contrib.auth', 36 | 'django.contrib.contenttypes', 37 | 'django.contrib.sessions', 38 | 'django.contrib.messages', 39 | 'django.contrib.staticfiles', 40 | 'authentication.apps.AuthenticationConfig', 41 | 'core.apps.CoreConfig', 42 | 'user.apps.UserConfig', 43 | ] 44 | 45 | MIDDLEWARE = [ 46 | 'django.middleware.security.SecurityMiddleware', 47 | 'django.contrib.sessions.middleware.SessionMiddleware', 48 | 'django.middleware.common.CommonMiddleware', 49 | 'django.middleware.csrf.CsrfViewMiddleware', 50 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 51 | 'django.contrib.messages.middleware.MessageMiddleware', 52 | 'django.middleware.clickjacking.XFrameOptionsMiddleware', 53 | 'crum.CurrentRequestUserMiddleware', 54 | ] 55 | 56 | ROOT_URLCONF = 'insta_clone.urls' 57 | 58 | TEMPLATES = [ 59 | { 60 | 'BACKEND': 'django.template.backends.django.DjangoTemplates', 61 | 'DIRS': [BASE_DIR/'templates',], 62 | 'APP_DIRS': True, 63 | 'OPTIONS': { 64 | 'context_processors': [ 65 | 'django.template.context_processors.debug', 66 | 'django.template.context_processors.request', 67 | 'django.contrib.auth.context_processors.auth', 68 | 'django.contrib.messages.context_processors.messages', 69 | ], 70 | }, 71 | }, 72 | ] 73 | 74 | WSGI_APPLICATION = 'insta_clone.wsgi.application' 75 | 76 | 77 | # Database 78 | # https://docs.djangoproject.com/en/3.1/ref/settings/#databases 79 | 80 | DATABASES = { 81 | 'default': { 82 | 'ENGINE': 'django.db.backends.sqlite3', 83 | 'NAME': BASE_DIR / 'db.sqlite3', 84 | } 85 | } 86 | 87 | 88 | # Password validation 89 | # https://docs.djangoproject.com/en/3.1/ref/settings/#auth-password-validators 90 | 91 | AUTH_PASSWORD_VALIDATORS = [ 92 | { 93 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', 94 | }, 95 | { 96 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 97 | }, 98 | { 99 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', 100 | }, 101 | { 102 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', 103 | }, 104 | ] 105 | 106 | 107 | # Internationalization 108 | # https://docs.djangoproject.com/en/3.1/topics/i18n/ 109 | 110 | LANGUAGE_CODE = 'en-us' 111 | 112 | TIME_ZONE = 'UTC' 113 | 114 | USE_I18N = True 115 | 116 | USE_L10N = True 117 | 118 | USE_TZ = True 119 | 120 | 121 | # Static files (CSS, JavaScript, Images) 122 | # https://docs.djangoproject.com/en/3.1/howto/static-files/ 123 | 124 | STATIC_URL = '/static/' 125 | STATICFILES_DIRS = [BASE_DIR/'static_files',] 126 | MEDIA_URL = '/media/' 127 | MEDIA_ROOT = BASE_DIR / 'media' 128 | 129 | 130 | AUTH_USER_MODEL = 'user.User' 131 | LOGIN_URL = 'signin_view' 132 | 133 | # EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' 134 | EMAIL_PORT = 587 135 | EMAIL_USE_TLS = True 136 | EMAIL_HOST = 'smtp.gmail.com' 137 | EMAIL_HOST_USER = '' 138 | # EMAIL_HOST_PASSWORD = '' 139 | 140 | EMAIL_BACKEND = 'django.core.mail.backends.filebased.EmailBackend' 141 | EMAIL_FILE_PATH = BASE_DIR / 'emails' -------------------------------------------------------------------------------- /InstaClone/insta_clone/urls.py: -------------------------------------------------------------------------------- 1 | """insta_clone URL Configuration 2 | 3 | The `urlpatterns` list routes URLs to views. For more information please see: 4 | https://docs.djangoproject.com/en/3.1/topics/http/urls/ 5 | Examples: 6 | Function views 7 | 1. Add an import: from my_app import views 8 | 2. Add a URL to urlpatterns: path('', views.home, name='home') 9 | Class-based views 10 | 1. Add an import: from other_app.views import Home 11 | 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') 12 | Including another URLconf 13 | 1. Import the include() function: from django.urls import include, path 14 | 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) 15 | """ 16 | from django.contrib import admin 17 | from django.urls import path, include 18 | from django.conf.urls.static import static 19 | from django.conf import settings 20 | 21 | urlpatterns = [ 22 | path('admin/', admin.site.urls), 23 | path('', include('authentication.urls')), 24 | path('', include('core.urls')), 25 | path('', include('user.urls')), 26 | ] 27 | 28 | urlpatterns.extend( 29 | static( 30 | settings.MEDIA_URL, 31 | document_root=settings.MEDIA_ROOT 32 | ) 33 | ) -------------------------------------------------------------------------------- /InstaClone/insta_clone/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for insta_clone project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.1/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'insta_clone.settings') 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /InstaClone/manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Django's command-line utility for administrative tasks.""" 3 | import os 4 | import sys 5 | 6 | 7 | def main(): 8 | """Run administrative tasks.""" 9 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'insta_clone.settings') 10 | try: 11 | from django.core.management import execute_from_command_line 12 | except ImportError as exc: 13 | raise ImportError( 14 | "Couldn't import Django. Are you sure it's installed and " 15 | "available on your PYTHONPATH environment variable? Did you " 16 | "forget to activate a virtual environment?" 17 | ) from exc 18 | execute_from_command_line(sys.argv) 19 | 20 | 21 | if __name__ == '__main__': 22 | main() 23 | -------------------------------------------------------------------------------- /InstaClone/media/post_images/Walrus_operator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mnamegaurav/easy_django/a9b959f1e436a74a513ff5f9d948eb6cd8813a10/InstaClone/media/post_images/Walrus_operator.png -------------------------------------------------------------------------------- /InstaClone/media/post_images/and_operator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mnamegaurav/easy_django/a9b959f1e436a74a513ff5f9d948eb6cd8813a10/InstaClone/media/post_images/and_operator.png -------------------------------------------------------------------------------- /InstaClone/media/post_images/host_static_websites.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mnamegaurav/easy_django/a9b959f1e436a74a513ff5f9d948eb6cd8813a10/InstaClone/media/post_images/host_static_websites.png -------------------------------------------------------------------------------- /InstaClone/media/post_images/host_static_websites_I97YUc9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mnamegaurav/easy_django/a9b959f1e436a74a513ff5f9d948eb6cd8813a10/InstaClone/media/post_images/host_static_websites_I97YUc9.png -------------------------------------------------------------------------------- /InstaClone/media/post_images/todoapp_playlist_marketing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mnamegaurav/easy_django/a9b959f1e436a74a513ff5f9d948eb6cd8813a10/InstaClone/media/post_images/todoapp_playlist_marketing.png -------------------------------------------------------------------------------- /InstaClone/media/post_images/todoapp_playlist_marketing_laAwEhM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mnamegaurav/easy_django/a9b959f1e436a74a513ff5f9d948eb6cd8813a10/InstaClone/media/post_images/todoapp_playlist_marketing_laAwEhM.png -------------------------------------------------------------------------------- /InstaClone/media/post_images/weather_dashboard_playlist_marketing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mnamegaurav/easy_django/a9b959f1e436a74a513ff5f9d948eb6cd8813a10/InstaClone/media/post_images/weather_dashboard_playlist_marketing.png -------------------------------------------------------------------------------- /InstaClone/media/profile_pictures/D.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mnamegaurav/easy_django/a9b959f1e436a74a513ff5f9d948eb6cd8813a10/InstaClone/media/profile_pictures/D.png -------------------------------------------------------------------------------- /InstaClone/media/profile_pictures/fresh_logo_circle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mnamegaurav/easy_django/a9b959f1e436a74a513ff5f9d948eb6cd8813a10/InstaClone/media/profile_pictures/fresh_logo_circle.png -------------------------------------------------------------------------------- /InstaClone/static_files/img/appstore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mnamegaurav/easy_django/a9b959f1e436a74a513ff5f9d948eb6cd8813a10/InstaClone/static_files/img/appstore.png -------------------------------------------------------------------------------- /InstaClone/static_files/img/instalogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mnamegaurav/easy_django/a9b959f1e436a74a513ff5f9d948eb6cd8813a10/InstaClone/static_files/img/instalogo.png -------------------------------------------------------------------------------- /InstaClone/static_files/img/no-posts1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mnamegaurav/easy_django/a9b959f1e436a74a513ff5f9d948eb6cd8813a10/InstaClone/static_files/img/no-posts1.jpg -------------------------------------------------------------------------------- /InstaClone/static_files/img/no-posts2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mnamegaurav/easy_django/a9b959f1e436a74a513ff5f9d948eb6cd8813a10/InstaClone/static_files/img/no-posts2.jpg -------------------------------------------------------------------------------- /InstaClone/static_files/img/phone_img.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mnamegaurav/easy_django/a9b959f1e436a74a513ff5f9d948eb6cd8813a10/InstaClone/static_files/img/phone_img.png -------------------------------------------------------------------------------- /InstaClone/static_files/img/playstore.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mnamegaurav/easy_django/a9b959f1e436a74a513ff5f9d948eb6cd8813a10/InstaClone/static_files/img/playstore.png -------------------------------------------------------------------------------- /InstaClone/static_files/styles/authentication/main.css: -------------------------------------------------------------------------------- 1 | *{ 2 | margin: 0; 3 | padding: 0; 4 | } 5 | 6 | .auth__card{ 7 | width: 380px; 8 | } 9 | 10 | body{ 11 | background-color: #fafafa!important; 12 | } 13 | 14 | .nav__insta__logo{ 15 | height: 30px; 16 | } 17 | 18 | .card{ 19 | border-radius: 1px; 20 | } 21 | 22 | .auth__btn{ 23 | border: 1px solid transparent; 24 | background-color: #0095f6; 25 | background-color: rgba(var(--d69,0,149,246),1); 26 | border-radius: 4px; 27 | color: #fff; 28 | color: rgba(var(--eca,255,255,255),1); 29 | position: relative; 30 | font-weight: 600; 31 | padding: 5px 9px; 32 | font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif; 33 | font-size: 14px; 34 | line-height: 18px; 35 | width: 100%; 36 | } 37 | 38 | .auth__btn:hover{ 39 | color: #fff; 40 | } 41 | 42 | .insta__logo{ 43 | background-repeat: no-repeat; 44 | width: 175px; 45 | } 46 | 47 | .form__input input{ 48 | font-size: 16px; 49 | background: rgba(var(--b3f,250,250,250),1); 50 | border: 1px solid lightgrey; 51 | border-radius: 2px; 52 | width: 100%; 53 | margin: 0; 54 | outline: 0; 55 | overflow: hidden; 56 | padding: 9px 0 7px 8px; 57 | text-overflow: ellipsis; 58 | color: rgba(var(--i1d,38,38,38),1); 59 | font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif; 60 | font-size: 14px; 61 | line-height: 18px; 62 | } 63 | 64 | .have__an__account{ 65 | margin: auto; 66 | color: rgba(var(--i1d,38,38,38),1); 67 | font-size: 14px; 68 | text-align: center; 69 | } 70 | 71 | .or__text{ 72 | font-size: 13px; 73 | font-weight: 600; 74 | line-height: 15px; 75 | display: block; 76 | display: flex; 77 | align-items: center; 78 | justify-content: space-around; 79 | text-transform: uppercase; 80 | color: rgba(var(--f52,142,142,142),1); 81 | } 82 | 83 | .or__text::before{ 84 | content: ''; 85 | display: block; 86 | background-color: rgba(var(--b38,219,219,219),1); 87 | height: 1px; 88 | width: 42%; 89 | } 90 | 91 | .or__text::after{ 92 | content: ''; 93 | display: block; 94 | background-color: rgba(var(--b38,219,219,219),1); 95 | height: 1px; 96 | width: 42%; 97 | } 98 | 99 | .app__download__img{ 100 | height: 40px; 101 | } 102 | 103 | .errorlist{ 104 | list-style: none; 105 | } -------------------------------------------------------------------------------- /InstaClone/static_files/styles/authentication/password_change.css: -------------------------------------------------------------------------------- 1 | .password__change__card{ 2 | background-color: rgba(var(--d87,255,255,255),1); 3 | max-width: 935px; 4 | overflow: hidden; 5 | width: 100%; 6 | } 7 | 8 | .validation__error{ 9 | width: 100%; 10 | margin-top: .25rem; 11 | font-size: 80%; 12 | color: #dc3545; 13 | } 14 | 15 | input{ 16 | font-size: 16px; 17 | background: rgba(var(--b3f,250,250,250),1); 18 | border: 1px solid rgba(var(--b38,219,219,219),1); 19 | border-radius: 6px; 20 | width: 100%; 21 | margin: 0; 22 | outline: 0; 23 | overflow: hidden; 24 | padding: 9px 0 7px 8px; 25 | text-overflow: ellipsis; 26 | color: rgba(var(--i1d,38,38,38),1); 27 | font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif; 28 | font-size: 14px; 29 | line-height: 18px; 30 | } -------------------------------------------------------------------------------- /InstaClone/static_files/styles/authentication/password_reset.css: -------------------------------------------------------------------------------- 1 | .links__to__page{ 2 | color: rgba(var(--f75,38,38,38),1); 3 | font-weight: 600; 4 | font-size: 14px; 5 | } 6 | 7 | .forgot__password__text{ 8 | font-weight: 400; 9 | font-size: 14px; 10 | line-height: 18px; 11 | color: rgba(var(--f52,142,142,142),1); 12 | } 13 | 14 | .trouble__signin__in{ 15 | color: rgba(var(--i1d,38,38,38),1); 16 | font-weight: 600; 17 | font-size: 16px; 18 | line-height: 24px; 19 | } -------------------------------------------------------------------------------- /InstaClone/static_files/styles/authentication/signin.css: -------------------------------------------------------------------------------- 1 | .signin__phone{ 2 | max-height: 80vh; 3 | } 4 | 5 | .login__fb__text{ 6 | color: #385185; 7 | font-weight: 600; 8 | } 9 | 10 | .signin__card{ 11 | width: 350px; 12 | } 13 | 14 | .login__fb__text:hover{ 15 | color: #385185; 16 | } 17 | 18 | .forogt__password{ 19 | color: rgba(var(--fe0,0,55,107),1); 20 | font-size: 12px; 21 | line-height: 14px; 22 | margin-top: 12px; 23 | text-align: center; 24 | } 25 | 26 | .get__app{ 27 | width: 350px; 28 | } -------------------------------------------------------------------------------- /InstaClone/static_files/styles/authentication/signup.css: -------------------------------------------------------------------------------- 1 | .signup__card{ 2 | width: 380px; 3 | } 4 | 5 | .signup__card__text{ 6 | color: rgba(var(--f52,142,142,142),1); 7 | font-size: 17px; 8 | font-weight: 600; 9 | line-height: 20px; 10 | text-align: center; 11 | } 12 | 13 | .terms__conditions{ 14 | color: rgba(var(--f52,142,142,142),1); 15 | font-size: 12px; 16 | line-height: 16px; 17 | text-align: center; 18 | } -------------------------------------------------------------------------------- /InstaClone/static_files/styles/core/main.css: -------------------------------------------------------------------------------- 1 | .nav__insta__logo{ 2 | height: 30px; 3 | } 4 | 5 | .search__input input{ 6 | font-size: 16px; 7 | height: 28px; 8 | background: rgba(var(--b3f,250,250,250),1); 9 | border: 1px solid lightgrey; 10 | border-radius: 2px; 11 | width: 100%; 12 | text-align: center; 13 | margin: 0; 14 | outline: 0; 15 | overflow: hidden; 16 | padding: 9px 0 7px 8px; 17 | text-overflow: ellipsis; 18 | color: rgba(var(--i1d,38,38,38),1); 19 | font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif; 20 | font-size: 14px; 21 | line-height: 18px; 22 | } -------------------------------------------------------------------------------- /InstaClone/static_files/styles/core/navbar.css: -------------------------------------------------------------------------------- 1 | #user__avatar img{ 2 | height: 26px; 3 | width: 26px; 4 | } 5 | 6 | .navbar-nav .dropdown-menu { 7 | position: absolute !important; 8 | } 9 | 10 | .nav__icons{ 11 | font-size: 24px; 12 | } 13 | 14 | .signout__btn{ 15 | border: none; 16 | background: none; 17 | cursor: pointer; 18 | padding: 0; 19 | text-decoration: none; 20 | } -------------------------------------------------------------------------------- /InstaClone/static_files/styles/core/post_card.css: -------------------------------------------------------------------------------- 1 | .post__card__head img{ 2 | width: 32px; 3 | height: 32px; 4 | border: 3px solid #d357a4; 5 | } 6 | 7 | .post__card__head span{ 8 | font-weight: 600; 9 | font-size: 14px; 10 | } 11 | 12 | .post__card__reactions .fa, .fas, .far, .post__card__reactions .far{ 13 | font-size: 25px; 14 | } 15 | 16 | .post__card__text{ 17 | font-size: 14px; 18 | color: #262626; 19 | color: rgba(var(--i1d,38,38,38),1); 20 | font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif; 21 | line-height: 18px; 22 | } 23 | 24 | .profile__pic{ 25 | height: 40px; 26 | width: 40px; 27 | border-radius: 50%; 28 | object-fit: cover; 29 | } -------------------------------------------------------------------------------- /InstaClone/static_files/styles/user/all_profiles.css: -------------------------------------------------------------------------------- 1 | .profile__pic{ 2 | height: 40px; 3 | width: 40px; 4 | object-fit: cover; 5 | overflow: hidden; 6 | } -------------------------------------------------------------------------------- /InstaClone/static_files/styles/user/profile.css: -------------------------------------------------------------------------------- 1 | .username__text{ 2 | display: block; 3 | overflow: hidden; 4 | text-overflow: ellipsis; 5 | white-space: nowrap; 6 | color: rgba(var(--i1d,38,38,38),1); 7 | font-weight: 300; 8 | font-size: 28px; 9 | line-height: 32px; 10 | margin: -5px 0 -6px; 11 | } 12 | 13 | .profile__pic__btn{ 14 | cursor: pointer; 15 | } 16 | 17 | .profile__pic{ 18 | height: 175px; 19 | width: 175px; 20 | border-radius: 50%; 21 | object-fit: cover; 22 | } 23 | 24 | .profile__pic__input{ 25 | display: none!important; 26 | } 27 | 28 | .edit__profile__btn{ 29 | background-color: transparent; 30 | border: 1px solid rgba(var(--ca6,219,219,219),1); 31 | color: rgba(var(--f75,38,38,38),1); 32 | border-radius: 4px; 33 | position: relative; 34 | appearance: none; 35 | background: 0 0; 36 | box-sizing: border-box; 37 | cursor: pointer; 38 | display: block; 39 | font-weight: 600; 40 | font-size: 14px; 41 | text-align: center; 42 | text-transform: inherit; 43 | text-overflow: ellipsis; 44 | -webkit-user-select: none; 45 | -moz-user-select: none; 46 | -ms-user-select: none; 47 | user-select: none; 48 | width: auto; 49 | } 50 | 51 | .settings__icon{ 52 | align-items: center; 53 | background: 0 0; 54 | cursor: pointer; 55 | } 56 | 57 | .settings__icon span{ 58 | font-size: 26px; 59 | } 60 | 61 | .nav-tabs{ 62 | border-top: 1px solid rgba(var(--b38,219,219,219),1) !important; 63 | color: #8e8e8e !important; 64 | border-bottom: none !important; 65 | } 66 | 67 | .nav-link{ 68 | border: none !important; 69 | padding-top: 16px; 70 | } 71 | 72 | .nav-link.active{ 73 | background-color: inherit !important; 74 | color: rgba(var(--i1d,38,38,38),1) !important; 75 | border-top: 1px solid #262626 !important; 76 | border-radius: 0 !important; 77 | } 78 | 79 | .no__posts__img{ 80 | display: flex; 81 | flex-wrap: wrap-reverse; 82 | justify-content: center; 83 | } 84 | 85 | .no__posts__img img{ 86 | height: 400px; 87 | } -------------------------------------------------------------------------------- /InstaClone/static_files/styles/user/profile_edit.css: -------------------------------------------------------------------------------- 1 | .profile__edit__card{ 2 | background-color: rgba(var(--d87,255,255,255),1); 3 | max-width: 935px; 4 | overflow: hidden; 5 | width: 100%; 6 | } -------------------------------------------------------------------------------- /InstaClone/templates/authentication/base.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | {% block extra_head %}{% endblock %} 11 | 12 | Insta Clone 13 | 14 | 15 | 16 | {% block content %}{% endblock %} 17 | 18 | 19 | 20 | {% block extra_body %}{% endblock %} 21 | 22 | 23 | -------------------------------------------------------------------------------- /InstaClone/templates/authentication/components/no_login_navbar.html: -------------------------------------------------------------------------------- 1 | {% load static %} 2 | 3 |
4 | 11 |
-------------------------------------------------------------------------------- /InstaClone/templates/authentication/password_change.html: -------------------------------------------------------------------------------- 1 | {% extends 'core/base.html' %} 2 | {% load static %} 3 | 4 | {% block extra_head %} 5 | 6 | {% endblock %} 7 | 8 | {% block content %} 9 |
10 |
11 |
12 |
13 |
14 |

Change Password

15 |
16 |
17 |
18 | {% csrf_token %} 19 | 20 | 21 | {% for field in form %} 22 |
23 | 26 |
27 | {{ field }} 28 | 29 | {{ field.help_text }} 30 | 31 |
32 | {{ field.errors }} 33 |
34 |
35 |
36 | {% endfor %} 37 | 38 | 39 |
40 | 41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 | {% endblock %} -------------------------------------------------------------------------------- /InstaClone/templates/authentication/password_change_done.html: -------------------------------------------------------------------------------- 1 | {% extends 'core/base.html' %} 2 | {% load static %} 3 | 4 | {% block extra_head %} 5 | 6 | {% endblock %} 7 | 8 | {% block content %} 9 |
10 |
11 |
12 |
13 |
14 | 15 | 16 |

Congratulations, your password has been successfully changed. 17 | Go Back to Profile 18 |

19 | 20 | 21 |
22 |
23 |
24 |
25 |
26 | {% endblock %} -------------------------------------------------------------------------------- /InstaClone/templates/authentication/password_reset.html: -------------------------------------------------------------------------------- 1 | {% extends 'authentication/base.html' %} 2 | {% load static %} 3 | 4 | {% block extra_head %} 5 | 6 | 7 | {% endblock %} 8 | 9 | {% block content %} 10 | 11 |
12 | 19 |
20 | 21 |
22 |
23 |
24 |
25 | 26 |
27 |
28 |
29 | Enter your email, phone, or username and we'll send you a link to get back into your account. 30 |
31 |
32 |
33 | {% csrf_token %} 34 |
35 | 36 |
37 |
38 | 39 |
40 |
41 |
42 |
43 |

OR

44 |
45 | 50 |
51 |
52 |
53 | Back To Signin 54 |
55 |
56 |
57 |
58 | 59 | {% endblock %} -------------------------------------------------------------------------------- /InstaClone/templates/authentication/password_reset_complete.html: -------------------------------------------------------------------------------- 1 | {% extends 'authentication/base.html' %} 2 | {% load static %} 3 | 4 | {% block extra_head %} 5 | 6 | 7 | {% endblock %} 8 | 9 | {% block content %} 10 | 11 | {% include 'authentication/components/no_login_navbar.html' %} 12 | 13 |
14 |
15 |
16 |
17 | 18 |
19 |
20 |
21 | You can go ahead and signin now. 22 |
23 | 24 | Click here to Sign In. 25 | 26 |
27 |
28 |

OR

29 |
30 | 35 |
36 |
37 |
38 | Back To Signin 39 |
40 |
41 |
42 |
43 | 44 | {% endblock %} -------------------------------------------------------------------------------- /InstaClone/templates/authentication/password_reset_confirm.html: -------------------------------------------------------------------------------- 1 | {% extends 'authentication/base.html' %} 2 | {% load static %} 3 | 4 | {% block extra_head %} 5 | 6 | 7 | {% endblock %} 8 | 9 | {% block content %} 10 | 11 | {% include 'authentication/components/no_login_navbar.html' %} 12 | 13 |
14 |
15 |
16 |
17 | 18 |
19 |
20 |
21 | Enter your email, phone, or username and we'll send you a link to get back into your account. 22 |
23 |
24 | {% if form %} 25 |
26 | {% if form.non_field_errors %} 27 | 30 | {% endif%} 31 |
32 |
33 | {% csrf_token %} 34 |
35 | 36 |

{{ form.new_password1.errors }}

37 |
38 |
39 | 40 |

{{ form.new_password2.errors }}

41 |
42 |
43 | 44 |
45 |
46 | {% else %} 47 |
48 | Your password reset link is invalid or expired. 49 |
50 | {% endif %} 51 |
52 |
53 |

OR

54 |
55 | 60 |
61 |
62 |
63 | Back To Signin 64 |
65 |
66 |
67 |
68 | 69 | {% endblock %} -------------------------------------------------------------------------------- /InstaClone/templates/authentication/password_reset_done.html: -------------------------------------------------------------------------------- 1 | {% extends 'authentication/base.html' %} 2 | {% load static %} 3 | 4 | {% block extra_head %} 5 | 6 | 7 | {% endblock %} 8 | 9 | {% block content %} 10 | 11 | {% include 'authentication/components/no_login_navbar.html' %} 12 | 13 |
14 |
15 |
16 |
17 | 18 |
19 |
20 |
21 | Check your registered email for the Password Reset link. 22 |
23 |
24 |

OR

25 |
26 | 31 |
32 |
33 |
34 | Back To Signin 35 |
36 |
37 |
38 |
39 | 40 | {% endblock %} -------------------------------------------------------------------------------- /InstaClone/templates/authentication/password_reset_email.html: -------------------------------------------------------------------------------- 1 | Devjunction is trying to steal your pasword- {{ email }}. Follow the link below: 2 | {{ protocol}}://{{ domain }}{% url 'password_reset_confirm' uidb64=uid token=token %} -------------------------------------------------------------------------------- /InstaClone/templates/authentication/signin.html: -------------------------------------------------------------------------------- 1 | {% extends 'authentication/base.html' %} 2 | {% load static %} 3 | 4 | {% block extra_head %} 5 | 6 | 7 | {% endblock %} 8 | 9 | {% block content %} 10 | 11 |
12 |
13 |
14 | 15 |
16 |
17 |
18 | 53 | 56 |
57 |

Get the app.

58 |
59 |
60 | 61 |
62 |
63 | 64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 | 72 | {% endblock %} -------------------------------------------------------------------------------- /InstaClone/templates/authentication/signup.html: -------------------------------------------------------------------------------- 1 | {% extends 'authentication/base.html' %} 2 | {% load static %} 3 | 4 | {% block extra_head %} 5 | 6 | 7 | {% endblock %} 8 | 9 | {% block content %} 10 | 11 |
12 |
13 |
14 | 72 | 75 |
76 |
77 |
78 | 79 | {% endblock %} -------------------------------------------------------------------------------- /InstaClone/templates/components/navbar.html: -------------------------------------------------------------------------------- 1 | {% load static %} 2 | 3 |
4 | 84 |
-------------------------------------------------------------------------------- /InstaClone/templates/components/post_card.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 | 6 | 7 | {% if post.user.picture %} 8 | 9 | {% else %} 10 | 11 | {% endif %} 12 | 13 | 14 | 15 | 16 | 17 | {{ post.user.username }} 18 | 19 | 20 | 21 |
22 |
23 | 24 | 25 | 26 | Go to Post 27 | 28 | 29 | 30 |
31 |
32 |
33 | 34 | 35 | 36 | 37 |
38 | 39 | 40 | {% if post.text %} 41 |
42 |

{{ post.text }}

43 |
44 | {% endif %} 45 | 46 |
47 |
-------------------------------------------------------------------------------- /InstaClone/templates/components/post_detail_card.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 | 6 | 7 | 8 | 9 |
10 |
11 |
12 |
13 |
14 | 15 | 16 | {% if post.user.picture %} 17 | 18 | {% else %} 19 | 20 | {% endif %} 21 | 22 | 23 | 24 | 25 | 26 | {{ post.user.username }} 27 | 28 | 29 |
30 |
31 |
32 |
33 | 53 |
54 | 55 | 56 | 57 | {{ post.comments_count }} 58 | 59 |
60 |
61 |
62 |
63 | 64 | 65 | 66 | {% if not post_saved %} 67 |
68 | {% csrf_token %} 69 | 72 |
73 | {% else %} 74 |
75 | {% csrf_token %} 76 | 79 |
80 | {% endif %} 81 | 82 | 83 |
84 |
85 |
86 | 87 | 88 | {% if post.text %} 89 |
90 |

{{ post.text }}

91 |
92 | {% endif %} 93 | 94 |
95 | Comments 96 |
97 |
98 | 99 | 100 | {% for comment in post.comment_set.all %} 101 | 102 | 129 | 130 | {% endfor %} 131 | 132 | 133 |
134 |
135 | 136 | 137 |
138 | {% csrf_token %} 139 | 140 | 141 |
142 | 143 | 144 |
145 |
146 |
147 |
-------------------------------------------------------------------------------- /InstaClone/templates/core/base.html: -------------------------------------------------------------------------------- 1 | {% load static %} 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | {% block extra_head %}{% endblock %} 15 | 16 | Insta Clone 17 | 18 | 19 | 20 | {% include 'components/navbar.html' %} 21 | 22 |
23 | {% block content %}{% endblock %} 24 |
25 | 26 | 27 | 28 | {% block extra_body %}{% endblock %} 29 | 30 | 31 | -------------------------------------------------------------------------------- /InstaClone/templates/core/feed.html: -------------------------------------------------------------------------------- 1 | {% extends 'core/base.html' %} 2 | {% load static %} 3 | 4 | {% block extra_head %} 5 | 6 | {% endblock %} 7 | 8 | {% block content %} 9 | 10 | 11 | {% if messages %} 12 | {% for message in messages %} 13 | 16 | {% endfor %} 17 | {% endif %} 18 | 19 |
20 |
21 |
22 |
23 |
24 |
25 | 26 | 27 |
28 | {% csrf_token %} 29 | {% for field in form %} 30 |
{{ field }}
31 | {% endfor %} 32 | 33 |
34 | 35 | 36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 | 44 | 45 | {% for post in all_posts %} 46 | 47 | 48 | {% include 'components/post_card.html' %} 49 | 50 | {% endfor %} 51 | 52 | 53 |
54 |
55 |
56 | {% endblock %} 57 | -------------------------------------------------------------------------------- /InstaClone/templates/core/liked_posts.html: -------------------------------------------------------------------------------- 1 | {% extends 'core/base.html' %} 2 | {% load static %} 3 | 4 | {% block content %} 5 | 6 |
7 |
8 | 9 | 10 | {% for like_obj in request.user.like_set.all %} 11 | {% with post=like_obj.post %} 12 | 13 | 14 | 38 | 39 | 40 | {% endwith %} 41 | {% endfor %} 42 | 43 | 44 |
45 |
46 | 47 | {% endblock %} 48 | -------------------------------------------------------------------------------- /InstaClone/templates/core/post_detail.html: -------------------------------------------------------------------------------- 1 | {% extends 'core/base.html' %} 2 | {% load static %} 3 | 4 | {% block extra_head %} 5 | 6 | {% endblock %} 7 | 8 | {% block content %} 9 | 10 |
11 |
12 |
13 | 14 | 15 | {% include 'components/post_detail_card.html' %} 16 | 17 |
18 |
19 |
20 | 21 | {% endblock %} 22 | -------------------------------------------------------------------------------- /InstaClone/templates/core/posts_explore.html: -------------------------------------------------------------------------------- 1 | {% extends 'core/base.html' %} 2 | {% load static %} 3 | 4 | {% block content %} 5 | 6 |
7 |
8 | 9 | 10 | {% for post in all_posts %} 11 | 12 | 36 | 37 | 38 | {% endfor %} 39 | 40 | 41 |
42 |
43 | 44 | {% endblock %} 45 | -------------------------------------------------------------------------------- /InstaClone/templates/core/saved_posts.html: -------------------------------------------------------------------------------- 1 | {% extends 'core/base.html' %} 2 | {% load static %} 3 | 4 | {% block content %} 5 | 6 |
7 |
8 | 9 | 10 | {% for savedpost_obj in request.user.savedpost_set.all %} 11 | {% with post=savedpost_obj.post %} 12 | 13 | 14 | 38 | 39 | 40 | {% endwith %} 41 | {% endfor %} 42 | 43 | 44 |
45 |
46 | 47 | {% endblock %} 48 | -------------------------------------------------------------------------------- /InstaClone/templates/user/all_profiles.html: -------------------------------------------------------------------------------- 1 | {% extends 'core/base.html' %} 2 | {% load static %} 3 | 4 | {% block extra_head %} 5 | 6 | {% endblock %} 7 | 8 | {% block content %} 9 |
10 |
11 |
12 | {% if all_profiles %} 13 | 14 | 15 | {% for user in all_profiles %} 16 | 17 | 18 | 19 |
20 | 21 | 22 | {% if user.picture %} 23 | 24 | {% else %} 25 | 26 | {% endif %} 27 | 28 | 29 |
30 | 31 | 32 |

{{ user.full_name }}

33 | 34 |
35 |
36 | 37 |
38 |
39 |
40 | 41 | 42 | {% endfor %} 43 | 44 | 45 | {% else %} 46 | 47 | 48 |

No Results to display

49 | 50 | {% endif %} 51 |
52 |
53 |
54 | {% endblock %} -------------------------------------------------------------------------------- /InstaClone/templates/user/anonymous_profile.html: -------------------------------------------------------------------------------- 1 | {% extends 'core/base.html' %} 2 | {% load static %} 3 | 4 | {% block extra_head %} 5 | 6 | {% endblock %} 7 | 8 | {% block content %} 9 |
10 |
11 |
12 | 25 |
26 |
27 | 28 |
29 | 30 | 31 |

{{ user.username }}

32 | 33 | {% if not is_follows_this_user %} 34 | 35 |
36 | {% csrf_token %} 37 | 38 | 39 |
40 | 41 | {% else %} 42 | 43 |
44 | {% csrf_token %} 45 | 46 | 47 |
48 | {% endif %} 49 | 50 |
51 | 52 |
53 | 54 | 55 | 56 | 57 | {{ user.posts_count }} 58 | posts 59 | 60 | 61 | 62 | 63 | 64 | 65 | {{ user.follower_count }} 66 | followers 67 | 68 | 69 | 70 | 71 | 72 | 73 | {{ user.following_count }} 74 | following 75 | 76 | 77 |
78 |
79 | 80 | {{ user.full_name }} 81 | 82 | 83 | 84 | {% if user.bio %} 85 | 86 | {{ user.bio }} 87 | 88 | {% endif %} 89 | 90 | 91 | {% if user.website %} 92 | 93 | {{ user.website }} 94 | 95 | {% endif %} 96 | 97 |
98 |
99 |
100 |
101 |
102 | 110 | 161 |
162 |
163 |
164 | 165 | {% endblock %} -------------------------------------------------------------------------------- /InstaClone/templates/user/authenticated_profile.html: -------------------------------------------------------------------------------- 1 | {% extends 'core/base.html' %} 2 | {% load static %} 3 | 4 | {% block extra_head %} 5 | 6 | {% endblock %} 7 | 8 | {% block content %} 9 |
10 |
11 |
12 | 25 |
26 |
27 | 28 |
29 | 30 | 31 |

{{ user.username }}

32 | 33 | 34 | Edit Profile 35 | 36 | 37 | 38 | 39 | 40 | 41 |
42 | 43 |
44 | 45 | 46 | 47 | 48 | {{ request.user.posts_count }} 49 | posts 50 | 51 | 52 | 53 | 54 | 55 | 56 | {{ request.user.follower_count }} 57 | followers 58 | 59 | 60 | 61 | 62 | 63 | 64 | {{ request.user.following_count }} 65 | following 66 | 67 | 68 |
69 |
70 | 71 | 72 | 73 | {{ user.full_name }} 74 | 75 | 76 | 77 | 78 | {% if user.bio %} 79 | 80 | {{ user.bio }} 81 | 82 | {% endif %} 83 | 84 | 85 | {% if user.website %} 86 | 87 | {{ user.website }} 88 | 89 | {% endif %} 90 | 91 |
92 |
93 |
94 |
95 |
96 | 107 | 223 |
224 |
225 |
226 | 227 | 228 | 229 | 230 | 231 | 273 | 274 | 275 | {% endblock %} -------------------------------------------------------------------------------- /InstaClone/templates/user/profile_edit.html: -------------------------------------------------------------------------------- 1 | {% extends 'core/base.html' %} 2 | {% load static %} 3 | 4 | {% block extra_head %} 5 | 6 | {% endblock %} 7 | 8 | {% block content %} 9 |
10 |
11 |
12 | 13 | {% if messages %} 14 | {% for message in messages %} 15 | 18 | {% endfor %} 19 | {% endif %} 20 | 21 |
22 |
23 |

Edit Profile

24 |
25 |
26 | 27 | 28 | {% if request.user.picture %} 29 |
30 | 31 |
32 | {% else %} 33 | 34 | {% endif %} 35 | 36 | 37 | 38 |
39 | {% csrf_token %} 40 | 41 | {% for field in form %} 42 |
43 | 44 |
45 | {{ field }} 46 | 47 | {{ field.help_text }} 48 | 49 |
50 | {{ field.errors }} 51 |
52 |
53 |
54 | {% endfor %} 55 |
56 | 57 |
58 |
59 | 60 | 61 |
62 |
63 |
64 |
65 |
66 | {% endblock %} -------------------------------------------------------------------------------- /InstaClone/user/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mnamegaurav/easy_django/a9b959f1e436a74a513ff5f9d948eb6cd8813a10/InstaClone/user/__init__.py -------------------------------------------------------------------------------- /InstaClone/user/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from django.contrib.auth import get_user_model 3 | from django.contrib.auth.admin import UserAdmin 4 | from authentication.forms import UserForm, CustomUserChangeForm 5 | # Register your models here. 6 | 7 | User = get_user_model() 8 | 9 | # ModelAdmin 10 | 11 | class CustomUserAdmin(UserAdmin): 12 | add_form = UserForm 13 | form = CustomUserChangeForm 14 | model = User 15 | add_fieldsets = ( 16 | ('Personal Details', {'fields': ('email', 'full_name', 'username', 'picture', 'password1', 'password2')}), 17 | ('Permissions', {'fields': ('is_staff', 'is_active')}), 18 | ('Optional', {'fields': ('bio', 'website')}), 19 | ) 20 | fieldsets = ( 21 | ('Personal Details', {'fields': ('email', 'full_name', 'username', 'picture')}), 22 | ('Permissions', {'fields': ('is_staff', 'is_active')}), 23 | ('Optional', {'fields': ('bio', 'website')}), 24 | ) 25 | 26 | 27 | admin.site.register(User, CustomUserAdmin) -------------------------------------------------------------------------------- /InstaClone/user/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class UserConfig(AppConfig): 5 | name = 'user' 6 | -------------------------------------------------------------------------------- /InstaClone/user/forms.py: -------------------------------------------------------------------------------- 1 | from django.contrib.auth import get_user_model 2 | from django import forms 3 | 4 | 5 | User = get_user_model() 6 | 7 | class UserEditForm(forms.ModelForm): 8 | class Meta: 9 | model = User 10 | fields = ( 11 | 'picture', 12 | 'full_name', 13 | 'username', 14 | 'email', 15 | 'bio', 16 | 'website', 17 | 'phone_number', 18 | 'gender', 19 | 'is_private_account', 20 | ) 21 | labels = { 22 | 'is_private_account': 'Do you want to make your account private ?', 23 | 'phone_number': 'Phone' 24 | } 25 | 26 | def __init__(self, *args, **kwargs): 27 | super().__init__(*args, **kwargs) 28 | 29 | for field in self.fields: 30 | if field == 'picture': 31 | self.fields[field].widget.attrs.update({'class': 'form-control-file'}) 32 | elif field == 'is_private_account': 33 | self.fields[field].widget.attrs.update({'class': 'form-check-input'}) 34 | else: 35 | self.fields[field].widget.attrs.update({'class': 'form-control form-control-sm'}) -------------------------------------------------------------------------------- /InstaClone/user/managers.py: -------------------------------------------------------------------------------- 1 | from django.contrib.auth.models import BaseUserManager 2 | from django.utils.translation import ugettext_lazy 3 | 4 | 5 | class CustomUserManager(BaseUserManager) : 6 | 7 | def create_user(self, email, password, username, **extra_fields): 8 | if not email: 9 | raise ValueError(ugettext_lazy('The Email must be set')) 10 | email = self.normalize_email(email) 11 | user = self.model(email=email, username=username, **extra_fields) 12 | user.set_password(password) 13 | user.save() 14 | return user 15 | 16 | def create_superuser(self, email, password, username, **extra_fields): 17 | extra_fields.setdefault('is_active', True) 18 | extra_fields.setdefault('is_staff', True) 19 | extra_fields.setdefault('is_superuser', True) 20 | 21 | if extra_fields.get('is_staff') is not True: 22 | raise ValueError(ugettext_lazy('Superuser must have is_staff=True.')) 23 | if extra_fields.get('is_superuser') is not True: 24 | raise ValueError(ugettext_lazy('Superuser must have is_superuser=True.')) 25 | return self.create_user(email, password, username, **extra_fields) -------------------------------------------------------------------------------- /InstaClone/user/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.1.3 on 2020-12-01 16:42 2 | 3 | import django.contrib.auth.validators 4 | from django.db import migrations, models 5 | import django.utils.timezone 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | initial = True 11 | 12 | dependencies = [ 13 | ('auth', '0012_alter_user_first_name_max_length'), 14 | ] 15 | 16 | operations = [ 17 | migrations.CreateModel( 18 | name='User', 19 | fields=[ 20 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 21 | ('password', models.CharField(max_length=128, verbose_name='password')), 22 | ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')), 23 | ('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')), 24 | ('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')), 25 | ('first_name', models.CharField(blank=True, max_length=150, verbose_name='first name')), 26 | ('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')), 27 | ('email', models.EmailField(blank=True, max_length=254, verbose_name='email address')), 28 | ('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')), 29 | ('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')), 30 | ('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')), 31 | ('picture', models.ImageField(upload_to='profile_pictures')), 32 | ('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.Group', verbose_name='groups')), 33 | ('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions')), 34 | ], 35 | options={ 36 | 'verbose_name': 'user', 37 | 'verbose_name_plural': 'users', 38 | 'abstract': False, 39 | }, 40 | ), 41 | ] 42 | -------------------------------------------------------------------------------- /InstaClone/user/migrations/0002_auto_20201201_1649.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.1.3 on 2020-12-01 16:49 2 | 3 | import django.contrib.auth.models 4 | from django.db import migrations 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('user', '0001_initial'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AlterModelManagers( 15 | name='user', 16 | managers=[ 17 | ('objects', django.contrib.auth.models.UserManager()), 18 | ], 19 | ), 20 | ] 21 | -------------------------------------------------------------------------------- /InstaClone/user/migrations/0003_auto_20201203_1638.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.1.3 on 2020-12-03 16:38 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('user', '0002_auto_20201201_1649'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterModelManagers( 14 | name='user', 15 | managers=[ 16 | ], 17 | ), 18 | migrations.AddField( 19 | model_name='user', 20 | name='full_name', 21 | field=models.CharField(default='gaurav', max_length=100), 22 | preserve_default=False, 23 | ), 24 | migrations.AlterField( 25 | model_name='user', 26 | name='email', 27 | field=models.EmailField(max_length=254, unique=True), 28 | ), 29 | ] 30 | -------------------------------------------------------------------------------- /InstaClone/user/migrations/0004_auto_20201203_1638.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.1.3 on 2020-12-03 16:38 2 | 3 | from django.db import migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('user', '0003_auto_20201203_1638'), 10 | ] 11 | 12 | operations = [ 13 | migrations.RemoveField( 14 | model_name='user', 15 | name='first_name', 16 | ), 17 | migrations.RemoveField( 18 | model_name='user', 19 | name='last_name', 20 | ), 21 | ] 22 | -------------------------------------------------------------------------------- /InstaClone/user/migrations/0005_auto_20201211_1656.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.1.3 on 2020-12-11 16:56 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('user', '0004_auto_20201203_1638'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='user', 15 | name='picture', 16 | field=models.ImageField(blank=True, null=True, upload_to='profile_pictures'), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /InstaClone/user/migrations/0006_auto_20210219_1614.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.1.3 on 2021-02-19 16:14 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('user', '0005_auto_20201211_1656'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='user', 15 | name='bio', 16 | field=models.TextField(blank=True, null=True), 17 | ), 18 | migrations.AddField( 19 | model_name='user', 20 | name='website', 21 | field=models.URLField(blank=True, null=True), 22 | ), 23 | ] 24 | -------------------------------------------------------------------------------- /InstaClone/user/migrations/0007_auto_20210222_1610.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.1.3 on 2021-02-22 16:10 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('user', '0006_auto_20210219_1614'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='user', 15 | name='gender', 16 | field=models.CharField(blank=True, choices=[('M', 'Male'), ('F', 'Female'), ('None', 'Prefer not to say.')], max_length=10, null=True), 17 | ), 18 | migrations.AddField( 19 | model_name='user', 20 | name='is_private_account', 21 | field=models.BooleanField(blank=True, null=True), 22 | ), 23 | migrations.AddField( 24 | model_name='user', 25 | name='phone_number', 26 | field=models.CharField(blank=True, max_length=20, null=True), 27 | ), 28 | ] 29 | -------------------------------------------------------------------------------- /InstaClone/user/migrations/0008_auto_20210224_1546.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.1.3 on 2021-02-24 15:46 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('user', '0007_auto_20210222_1610'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='user', 15 | name='bio', 16 | field=models.TextField(blank=True, help_text="Provide your personal information, even if the account is used for a business, a pet or something else. This won't be a part of your public profile.", null=True), 17 | ), 18 | migrations.AlterField( 19 | model_name='user', 20 | name='full_name', 21 | field=models.CharField(help_text="Help people discover your account by using the name you're known by: either your full name, nickname, or business name.", max_length=100), 22 | ), 23 | ] 24 | -------------------------------------------------------------------------------- /InstaClone/user/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mnamegaurav/easy_django/a9b959f1e436a74a513ff5f9d948eb6cd8813a10/InstaClone/user/migrations/__init__.py -------------------------------------------------------------------------------- /InstaClone/user/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | from django.contrib.auth.models import AbstractUser 3 | from user.managers import CustomUserManager 4 | # Create your models here. 5 | 6 | 7 | GENDER_CHOICES = [ 8 | ('M', 'Male'), 9 | ('F', 'Female'), 10 | ('None', 'Prefer not to say.'), 11 | ] 12 | 13 | 14 | class User(AbstractUser): 15 | picture = models.ImageField(upload_to='profile_pictures', null=True, blank=True) 16 | full_name = models.CharField(max_length=100, help_text='Help people discover your account by using the name you\'re known by: either your full name, nickname, or business name.') 17 | email = models.EmailField(unique=True) 18 | 19 | # Optional fields 20 | bio = models.TextField(null=True, blank=True, help_text='Provide your personal information, even if the account is used for a business, a pet or something else. This won\'t be a part of your public profile.') 21 | website = models.URLField(null=True, blank=True) 22 | phone_number = models.CharField(max_length=20, null=True, blank=True) 23 | gender = models.CharField(max_length=10, choices=GENDER_CHOICES, null=True, blank=True) 24 | is_private_account = models.BooleanField(null=True, blank=True) 25 | 26 | first_name = None 27 | last_name = None 28 | 29 | USERNAME_FIELD = 'email' 30 | REQUIRED_FIELDS = ['full_name','username',] 31 | 32 | objects = CustomUserManager() 33 | 34 | def __str__(self): 35 | return self.email 36 | 37 | @property 38 | def follower_count(self): 39 | count = self.follow_followed.count() 40 | return count 41 | 42 | @property 43 | def following_count(self): 44 | count = self.follow_follower.count() 45 | return count 46 | 47 | @property 48 | def posts_count(self): 49 | count = self.post_set.count() 50 | return count -------------------------------------------------------------------------------- /InstaClone/user/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /InstaClone/user/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | from user.views import ( 3 | ProfileView, 4 | ProfileEditView, 5 | AllProfilesView, 6 | ) 7 | from django.contrib.auth.decorators import login_required 8 | 9 | urlpatterns = [ 10 | path( 11 | 'in//', 12 | login_required(ProfileView.as_view()), 13 | name='profile_view' 14 | ), 15 | path( 16 | 'in//edit/', 17 | login_required(ProfileEditView.as_view()), 18 | name='profile_edit_view' 19 | ), 20 | path( 21 | 'profiles/', 22 | login_required(AllProfilesView.as_view()), 23 | name='all_profiles_view' 24 | ), 25 | ] -------------------------------------------------------------------------------- /InstaClone/user/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render, redirect 2 | from django.views.generic import View 3 | from django.http import HttpResponse 4 | from django.contrib.auth import get_user_model 5 | from django.contrib import messages 6 | from django.db.models import Q 7 | 8 | from user.forms import UserEditForm 9 | from core.models import Follow 10 | # Create your views here. 11 | 12 | User = get_user_model() 13 | 14 | class ProfileView(View): 15 | template_name_anon = 'user/anonymous_profile.html' 16 | template_name_auth = 'user/authenticated_profile.html' 17 | 18 | def get(self, request, *args, **kwargs): 19 | username = kwargs.get('username') 20 | 21 | try: 22 | user = User.objects.get(username=username) 23 | except Exception as e: 24 | return HttpResponse('

This page does not exist.

') 25 | 26 | 27 | if username == request.user.username: 28 | context = { 'user': user } 29 | return render(request, self.template_name_auth, context=context) 30 | else: 31 | try: 32 | Follow.objects.get(user=request.user, followed=user) 33 | is_follows_this_user = True 34 | except Exception as e: 35 | is_follows_this_user = False 36 | 37 | context = { 'user': user, 'is_follows_this_user': is_follows_this_user } 38 | return render(request, self.template_name_anon, context=context) 39 | 40 | 41 | class ProfileEditView(View): 42 | template_name = 'user/profile_edit.html' 43 | form_class = UserEditForm 44 | 45 | def get(self, request, *args, **kwargs): 46 | username = kwargs.get('username') 47 | 48 | if username != request.user.username: 49 | return HttpResponse('

This page does not exist.

') 50 | 51 | form = self.form_class(instance=request.user) 52 | context = {'form': form} 53 | return render(request, self.template_name, context=context) 54 | 55 | def post(self, request, *args, **kwargs): 56 | form = self.form_class(request.POST, request.FILES, instance=request.user) 57 | 58 | if form.is_valid(): 59 | form.save() 60 | messages.success(request, 'Saved your details in a safe place.') 61 | return redirect('profile_edit_view', request.user.username) 62 | else: 63 | for field in form.errors: 64 | form[field].field.widget.attrs['class'] += ' is-invalid' 65 | context = {'form': form} 66 | return render(request, self.template_name, context=context) 67 | 68 | 69 | class AllProfilesView(View): 70 | template_name = 'user/all_profiles.html' 71 | 72 | def get(self, request, *args, **kwargs): 73 | search_term = request.GET.get('query') 74 | 75 | if search_term: 76 | all_profiles = User.objects.filter( 77 | Q(username__contains=search_term) | Q(full_name__contains=search_term) 78 | ).exclude( 79 | username=request.user.username 80 | ) 81 | else: 82 | all_profiles = User.objects.none() 83 | 84 | context = {'all_profiles': all_profiles} 85 | return render(request, self.template_name, context=context) -------------------------------------------------------------------------------- /ToDoApp/manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Django's command-line utility for administrative tasks.""" 3 | import os 4 | import sys 5 | 6 | 7 | def main(): 8 | """Run administrative tasks.""" 9 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'todo.settings') 10 | try: 11 | from django.core.management import execute_from_command_line 12 | except ImportError as exc: 13 | raise ImportError( 14 | "Couldn't import Django. Are you sure it's installed and " 15 | "available on your PYTHONPATH environment variable? Did you " 16 | "forget to activate a virtual environment?" 17 | ) from exc 18 | execute_from_command_line(sys.argv) 19 | 20 | 21 | if __name__ == '__main__': 22 | main() 23 | -------------------------------------------------------------------------------- /ToDoApp/mytodo/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mnamegaurav/easy_django/a9b959f1e436a74a513ff5f9d948eb6cd8813a10/ToDoApp/mytodo/__init__.py -------------------------------------------------------------------------------- /ToDoApp/mytodo/__pycache__/__init__.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mnamegaurav/easy_django/a9b959f1e436a74a513ff5f9d948eb6cd8813a10/ToDoApp/mytodo/__pycache__/__init__.cpython-38.pyc -------------------------------------------------------------------------------- /ToDoApp/mytodo/__pycache__/admin.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mnamegaurav/easy_django/a9b959f1e436a74a513ff5f9d948eb6cd8813a10/ToDoApp/mytodo/__pycache__/admin.cpython-38.pyc -------------------------------------------------------------------------------- /ToDoApp/mytodo/__pycache__/forms.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mnamegaurav/easy_django/a9b959f1e436a74a513ff5f9d948eb6cd8813a10/ToDoApp/mytodo/__pycache__/forms.cpython-38.pyc -------------------------------------------------------------------------------- /ToDoApp/mytodo/__pycache__/models.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mnamegaurav/easy_django/a9b959f1e436a74a513ff5f9d948eb6cd8813a10/ToDoApp/mytodo/__pycache__/models.cpython-38.pyc -------------------------------------------------------------------------------- /ToDoApp/mytodo/__pycache__/urls.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mnamegaurav/easy_django/a9b959f1e436a74a513ff5f9d948eb6cd8813a10/ToDoApp/mytodo/__pycache__/urls.cpython-38.pyc -------------------------------------------------------------------------------- /ToDoApp/mytodo/__pycache__/views.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mnamegaurav/easy_django/a9b959f1e436a74a513ff5f9d948eb6cd8813a10/ToDoApp/mytodo/__pycache__/views.cpython-38.pyc -------------------------------------------------------------------------------- /ToDoApp/mytodo/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from mytodo.models import ToDo 3 | 4 | # Register your models here. 5 | admin.site.register(ToDo) -------------------------------------------------------------------------------- /ToDoApp/mytodo/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class MytodoConfig(AppConfig): 5 | name = 'mytodo' 6 | -------------------------------------------------------------------------------- /ToDoApp/mytodo/forms.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | 3 | class ToDoForm(forms.Form): 4 | todo_text = forms.CharField(widget=forms.TextInput(attrs={ 5 | 'class': 'form-control', 6 | 'placeholder':'Add Your Todo!'})) -------------------------------------------------------------------------------- /ToDoApp/mytodo/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.1.3 on 2020-11-18 16:42 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | initial = True 9 | 10 | dependencies = [ 11 | ] 12 | 13 | operations = [ 14 | migrations.CreateModel( 15 | name='ToDo', 16 | fields=[ 17 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 18 | ('todo_text', models.CharField(max_length=200)), 19 | ('added_date', models.DateTimeField(auto_now=True)), 20 | ], 21 | ), 22 | ] 23 | -------------------------------------------------------------------------------- /ToDoApp/mytodo/migrations/0002_auto_20201120_1628.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.1.3 on 2020-11-20 16:28 2 | 3 | from django.db import migrations, models 4 | import django.utils.timezone 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('mytodo', '0001_initial'), 11 | ] 12 | 13 | operations = [ 14 | migrations.RenameField( 15 | model_name='todo', 16 | old_name='added_date', 17 | new_name='updated_on', 18 | ), 19 | migrations.AddField( 20 | model_name='todo', 21 | name='added_on', 22 | field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now), 23 | preserve_default=False, 24 | ), 25 | ] 26 | -------------------------------------------------------------------------------- /ToDoApp/mytodo/migrations/0003_auto_20201128_1440.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.1.3 on 2020-11-28 14:40 2 | 3 | from django.db import migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('mytodo', '0002_auto_20201120_1628'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterModelOptions( 14 | name='todo', 15 | options={'ordering': ['-added_on']}, 16 | ), 17 | ] 18 | -------------------------------------------------------------------------------- /ToDoApp/mytodo/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mnamegaurav/easy_django/a9b959f1e436a74a513ff5f9d948eb6cd8813a10/ToDoApp/mytodo/migrations/__init__.py -------------------------------------------------------------------------------- /ToDoApp/mytodo/migrations/__pycache__/0001_initial.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mnamegaurav/easy_django/a9b959f1e436a74a513ff5f9d948eb6cd8813a10/ToDoApp/mytodo/migrations/__pycache__/0001_initial.cpython-38.pyc -------------------------------------------------------------------------------- /ToDoApp/mytodo/migrations/__pycache__/0002_auto_20201120_1628.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mnamegaurav/easy_django/a9b959f1e436a74a513ff5f9d948eb6cd8813a10/ToDoApp/mytodo/migrations/__pycache__/0002_auto_20201120_1628.cpython-38.pyc -------------------------------------------------------------------------------- /ToDoApp/mytodo/migrations/__pycache__/0003_auto_20201128_1440.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mnamegaurav/easy_django/a9b959f1e436a74a513ff5f9d948eb6cd8813a10/ToDoApp/mytodo/migrations/__pycache__/0003_auto_20201128_1440.cpython-38.pyc -------------------------------------------------------------------------------- /ToDoApp/mytodo/migrations/__pycache__/__init__.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mnamegaurav/easy_django/a9b959f1e436a74a513ff5f9d948eb6cd8813a10/ToDoApp/mytodo/migrations/__pycache__/__init__.cpython-38.pyc -------------------------------------------------------------------------------- /ToDoApp/mytodo/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | # Create your models here. 4 | class ToDo(models.Model): 5 | # id = models.AutoField(primary_key=True) 6 | todo_text = models.CharField(max_length=200) 7 | added_on = models.DateTimeField(auto_now_add=True) 8 | updated_on = models.DateTimeField(auto_now=True) 9 | 10 | def __str__(self): 11 | return self.todo_text 12 | 13 | class Meta: 14 | ordering = ['-added_on'] -------------------------------------------------------------------------------- /ToDoApp/mytodo/static/styles.css: -------------------------------------------------------------------------------- 1 | footer{ 2 | position: fixed; 3 | bottom: 0; 4 | width: 100%; 5 | } -------------------------------------------------------------------------------- /ToDoApp/mytodo/templates/base.html: -------------------------------------------------------------------------------- 1 | {% load static %} 2 | 3 | 4 | 5 | 6 | Todo App 7 | 8 | 9 | 10 | {% block styles %}{% endblock %} 11 | 12 | 13 | 14 | 15 |
16 | 19 |
20 | 21 | {% block content %}{% endblock %} 22 | 23 | {% include 'components/footer.html' %} 24 | 25 | 26 | 27 | {% block script %}{% endblock %} 28 | 29 | -------------------------------------------------------------------------------- /ToDoApp/mytodo/templates/components/footer.html: -------------------------------------------------------------------------------- 1 | {% block styles %} 2 | {% endblock %} 3 | 4 |
5 |
6 |
7 | Copyright © 2020 - DevJunction 8 |
9 |
10 |
11 | 12 | 13 | {% block script %} 14 | 17 | {% endblock %} -------------------------------------------------------------------------------- /ToDoApp/mytodo/templates/edit.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | {% block content %} 4 |
5 | 6 |
7 |
8 |

Edit Your Todo Here!

9 |
10 |
11 | 12 |
13 |
14 |
15 | {% csrf_token %} 16 |
17 | {{ form.todo_text }} 18 |
19 | 20 |
21 |
22 |
23 |
24 | {% endblock %} -------------------------------------------------------------------------------- /ToDoApp/mytodo/templates/home.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | {% block content %} 4 |
5 |
6 |
7 |

Add Your Todo Here!

8 |
9 |
10 | 11 |
12 |
13 |
14 | {% csrf_token %} 15 |
16 | {{ form.todo_text }} 17 |
18 | 19 |
20 |
21 |
22 | 23 |
24 |
25 | 26 | 27 | {% for todo in todo_list %} 28 | 29 | 38 | 44 | 47 | 48 | {% endfor %} 49 | 50 |
30 |

{{ todo.todo_text }}

31 |

Added On:{{ todo.added_on }}

32 | 33 | 34 | {% if todo.added_on != todo.updated_on %} 35 |

Updated On:{{ todo.updated_on }}

36 | {% endif %} 37 |
39 |
40 | {% csrf_token %} 41 | 42 |
43 |
45 | EDIT 46 |
51 |
52 |
53 |
54 | {% endblock %} 55 | -------------------------------------------------------------------------------- /ToDoApp/mytodo/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /ToDoApp/mytodo/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | from mytodo.views import home, add_todo, delete_todo, edit_todo 3 | # importing functions from views.py 4 | 5 | urlpatterns = [ 6 | path('', home, name='home'), # End point (By Default First url when user visit on the website) 7 | path('add_todo/', add_todo, name='add_todo'), 8 | path('delete_todo/', delete_todo, name='delete_todo'), 9 | path('edit_todo/', edit_todo, name='edit_todo'), 10 | ] 11 | -------------------------------------------------------------------------------- /ToDoApp/mytodo/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render, redirect 2 | from django.http import HttpResponse 3 | from mytodo.models import ToDo 4 | from mytodo.forms import ToDoForm 5 | 6 | # Create your views here. 7 | def home(request): 8 | template_name = 'home.html' 9 | todo_list = ToDo.objects.all() # returns queryset 10 | form = ToDoForm() 11 | # print(todo_list) 12 | context = {'app_name': "ToDo App", 'todo_list': todo_list, 'form': form} 13 | return render(request, template_name, context=context) 14 | 15 | def add_todo(request): 16 | if request.method == 'POST': 17 | # save the todo 18 | form = ToDoForm(request.POST) 19 | if form.is_valid(): 20 | todo_text = form.cleaned_data.get('todo_text') 21 | ToDo.objects.create(todo_text=todo_text) 22 | 23 | return redirect('home') 24 | 25 | 26 | def delete_todo(request, todo_id): 27 | if request.method == 'POST': 28 | todo_obj = ToDo.objects.get(pk=todo_id) 29 | todo_obj.delete() 30 | 31 | return redirect('home') 32 | 33 | 34 | def edit_todo(request, todo_id): 35 | todo_obj = ToDo.objects.get(pk=todo_id) 36 | 37 | if request.method == 'POST': 38 | form = ToDoForm(request.POST, initial={'todo_text': todo_obj.todo_text}) 39 | if form.is_valid(): 40 | todo_obj.todo_text = form.cleaned_data.get('todo_text') 41 | todo_obj.save() 42 | return redirect('home') 43 | 44 | template_name = 'edit.html' 45 | form = ToDoForm(initial={'todo_text': todo_obj.todo_text}) 46 | context = {'app_name': "ToDo App", 'form': form, 'todo_obj': todo_obj} 47 | return render(request, template_name, context) 48 | -------------------------------------------------------------------------------- /ToDoApp/requirements.txt: -------------------------------------------------------------------------------- 1 | asgiref==3.3.1 2 | certifi==2020.11.8 3 | chardet==3.0.4 4 | Django==3.1.3 5 | gunicorn==20.0.4 6 | idna==2.10 7 | pytz==2020.4 8 | requests==2.25.0 9 | sqlparse==0.4.1 10 | urllib3==1.26.2 11 | whitenoise==5.2.0 12 | -------------------------------------------------------------------------------- /ToDoApp/todo/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mnamegaurav/easy_django/a9b959f1e436a74a513ff5f9d948eb6cd8813a10/ToDoApp/todo/__init__.py -------------------------------------------------------------------------------- /ToDoApp/todo/__pycache__/__init__.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mnamegaurav/easy_django/a9b959f1e436a74a513ff5f9d948eb6cd8813a10/ToDoApp/todo/__pycache__/__init__.cpython-38.pyc -------------------------------------------------------------------------------- /ToDoApp/todo/__pycache__/settings.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mnamegaurav/easy_django/a9b959f1e436a74a513ff5f9d948eb6cd8813a10/ToDoApp/todo/__pycache__/settings.cpython-38.pyc -------------------------------------------------------------------------------- /ToDoApp/todo/__pycache__/urls.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mnamegaurav/easy_django/a9b959f1e436a74a513ff5f9d948eb6cd8813a10/ToDoApp/todo/__pycache__/urls.cpython-38.pyc -------------------------------------------------------------------------------- /ToDoApp/todo/__pycache__/wsgi.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mnamegaurav/easy_django/a9b959f1e436a74a513ff5f9d948eb6cd8813a10/ToDoApp/todo/__pycache__/wsgi.cpython-38.pyc -------------------------------------------------------------------------------- /ToDoApp/todo/asgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | ASGI config for todo project. 3 | 4 | It exposes the ASGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.1/howto/deployment/asgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.asgi import get_asgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'todo.settings') 15 | 16 | application = get_asgi_application() 17 | -------------------------------------------------------------------------------- /ToDoApp/todo/settings.py: -------------------------------------------------------------------------------- 1 | """ 2 | Django settings for todo project. 3 | 4 | Generated by 'django-admin startproject' using Django 3.1.3. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.1/topics/settings/ 8 | 9 | For the full list of settings and their values, see 10 | https://docs.djangoproject.com/en/3.1/ref/settings/ 11 | """ 12 | 13 | from pathlib import Path 14 | 15 | # Build paths inside the project like this: BASE_DIR / 'subdir'. 16 | BASE_DIR = Path(__file__).resolve().parent.parent 17 | 18 | 19 | # Quick-start development settings - unsuitable for production 20 | # See https://docs.djangoproject.com/en/3.1/howto/deployment/checklist/ 21 | 22 | # SECURITY WARNING: keep the secret key used in production secret! 23 | SECRET_KEY = 'hzx4@55aqc@l61m97wy27#h_ej8@k2mt+txcffmp%nr_hc8-d*' 24 | 25 | # SECURITY WARNING: don't run with debug turned on in production! 26 | DEBUG = True 27 | 28 | ALLOWED_HOSTS = ['*'] 29 | 30 | 31 | # Application definition 32 | 33 | INSTALLED_APPS = [ 34 | 'django.contrib.admin', 35 | 'django.contrib.auth', 36 | 'django.contrib.contenttypes', 37 | 'django.contrib.sessions', 38 | 'django.contrib.messages', 39 | 'django.contrib.staticfiles', 40 | 'mytodo', 41 | ] 42 | 43 | MIDDLEWARE = [ 44 | 'django.middleware.security.SecurityMiddleware', 45 | 'whitenoise.middleware.WhiteNoiseMiddleware', 46 | 'django.contrib.sessions.middleware.SessionMiddleware', 47 | 'django.middleware.common.CommonMiddleware', 48 | 'django.middleware.csrf.CsrfViewMiddleware', 49 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 50 | 'django.contrib.messages.middleware.MessageMiddleware', 51 | 'django.middleware.clickjacking.XFrameOptionsMiddleware', 52 | ] 53 | 54 | ROOT_URLCONF = 'todo.urls' 55 | 56 | TEMPLATES = [ 57 | { 58 | 'BACKEND': 'django.template.backends.django.DjangoTemplates', 59 | 'DIRS': [], 60 | 'APP_DIRS': True, 61 | 'OPTIONS': { 62 | 'context_processors': [ 63 | 'django.template.context_processors.debug', 64 | 'django.template.context_processors.request', 65 | 'django.contrib.auth.context_processors.auth', 66 | 'django.contrib.messages.context_processors.messages', 67 | ], 68 | }, 69 | }, 70 | ] 71 | 72 | WSGI_APPLICATION = 'todo.wsgi.application' 73 | 74 | 75 | # Database 76 | # https://docs.djangoproject.com/en/3.1/ref/settings/#databases 77 | 78 | DATABASES = { 79 | 'default': { 80 | 'ENGINE': 'django.db.backends.sqlite3', 81 | 'NAME': BASE_DIR / 'db.sqlite3', 82 | } 83 | } 84 | 85 | 86 | # Password validation 87 | # https://docs.djangoproject.com/en/3.1/ref/settings/#auth-password-validators 88 | 89 | AUTH_PASSWORD_VALIDATORS = [ 90 | { 91 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', 92 | }, 93 | { 94 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 95 | }, 96 | { 97 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', 98 | }, 99 | { 100 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', 101 | }, 102 | ] 103 | 104 | 105 | # Internationalization 106 | # https://docs.djangoproject.com/en/3.1/topics/i18n/ 107 | 108 | LANGUAGE_CODE = 'en-us' 109 | 110 | TIME_ZONE = 'UTC' 111 | 112 | USE_I18N = True 113 | 114 | USE_L10N = True 115 | 116 | USE_TZ = True 117 | 118 | 119 | # Static files (CSS, JavaScript, Images) 120 | # https://docs.djangoproject.com/en/3.1/howto/static-files/ 121 | 122 | STATIC_URL = '/static/' 123 | STATIC_ROOT = BASE_DIR / '/static/' 124 | -------------------------------------------------------------------------------- /ToDoApp/todo/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path, include 2 | from django.contrib import admin 3 | 4 | urlpatterns = [ 5 | path('admin/', admin.site.urls), 6 | path('', include('mytodo.urls')), 7 | ] -------------------------------------------------------------------------------- /ToDoApp/todo/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for todo project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.1/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'todo.settings') 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /WeatherDashboard/WeatherDashboard/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mnamegaurav/easy_django/a9b959f1e436a74a513ff5f9d948eb6cd8813a10/WeatherDashboard/WeatherDashboard/__init__.py -------------------------------------------------------------------------------- /WeatherDashboard/WeatherDashboard/__pycache__/__init__.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mnamegaurav/easy_django/a9b959f1e436a74a513ff5f9d948eb6cd8813a10/WeatherDashboard/WeatherDashboard/__pycache__/__init__.cpython-38.pyc -------------------------------------------------------------------------------- /WeatherDashboard/WeatherDashboard/__pycache__/settings.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mnamegaurav/easy_django/a9b959f1e436a74a513ff5f9d948eb6cd8813a10/WeatherDashboard/WeatherDashboard/__pycache__/settings.cpython-38.pyc -------------------------------------------------------------------------------- /WeatherDashboard/WeatherDashboard/__pycache__/urls.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mnamegaurav/easy_django/a9b959f1e436a74a513ff5f9d948eb6cd8813a10/WeatherDashboard/WeatherDashboard/__pycache__/urls.cpython-38.pyc -------------------------------------------------------------------------------- /WeatherDashboard/WeatherDashboard/__pycache__/wsgi.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mnamegaurav/easy_django/a9b959f1e436a74a513ff5f9d948eb6cd8813a10/WeatherDashboard/WeatherDashboard/__pycache__/wsgi.cpython-38.pyc -------------------------------------------------------------------------------- /WeatherDashboard/WeatherDashboard/asgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | ASGI config for WeatherDashboard project. 3 | 4 | It exposes the ASGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.1/howto/deployment/asgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.asgi import get_asgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'WeatherDashboard.settings') 15 | 16 | application = get_asgi_application() 17 | -------------------------------------------------------------------------------- /WeatherDashboard/WeatherDashboard/settings.py: -------------------------------------------------------------------------------- 1 | """ 2 | Django settings for WeatherDashboard project. 3 | 4 | Generated by 'django-admin startproject' using Django 3.1.3. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.1/topics/settings/ 8 | 9 | For the full list of settings and their values, see 10 | https://docs.djangoproject.com/en/3.1/ref/settings/ 11 | """ 12 | 13 | from pathlib import Path 14 | 15 | # Build paths inside the project like this: BASE_DIR / 'subdir'. 16 | BASE_DIR = Path(__file__).resolve().parent.parent 17 | 18 | 19 | # Quick-start development settings - unsuitable for production 20 | # See https://docs.djangoproject.com/en/3.1/howto/deployment/checklist/ 21 | 22 | # SECURITY WARNING: keep the secret key used in production secret! 23 | SECRET_KEY = 'e!c$z^0vu28i)#p($rc-dhqo%ng@tu6d)f9y#b6c-mkrn1m3o8' 24 | 25 | # SECURITY WARNING: don't run with debug turned on in production! 26 | DEBUG = False 27 | 28 | ALLOWED_HOSTS = ['*'] 29 | 30 | 31 | # Application definition 32 | 33 | INSTALLED_APPS = [ 34 | 'django.contrib.admin', 35 | 'django.contrib.auth', 36 | 'django.contrib.contenttypes', 37 | 'django.contrib.sessions', 38 | 'django.contrib.messages', 39 | 'django.contrib.staticfiles', 40 | 'dashboard', 41 | ] 42 | 43 | MIDDLEWARE = [ 44 | 'django.middleware.security.SecurityMiddleware', 45 | 'whitenoise.middleware.WhiteNoiseMiddleware', 46 | 'django.contrib.sessions.middleware.SessionMiddleware', 47 | 'django.middleware.common.CommonMiddleware', 48 | 'django.middleware.csrf.CsrfViewMiddleware', 49 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 50 | 'django.contrib.messages.middleware.MessageMiddleware', 51 | 'django.middleware.clickjacking.XFrameOptionsMiddleware', 52 | ] 53 | 54 | ROOT_URLCONF = 'WeatherDashboard.urls' 55 | 56 | TEMPLATES = [ 57 | { 58 | 'BACKEND': 'django.template.backends.django.DjangoTemplates', 59 | 'DIRS': [], 60 | 'APP_DIRS': True, 61 | 'OPTIONS': { 62 | 'context_processors': [ 63 | 'django.template.context_processors.debug', 64 | 'django.template.context_processors.request', 65 | 'django.contrib.auth.context_processors.auth', 66 | 'django.contrib.messages.context_processors.messages', 67 | ], 68 | }, 69 | }, 70 | ] 71 | 72 | WSGI_APPLICATION = 'WeatherDashboard.wsgi.application' 73 | 74 | 75 | # Database 76 | # https://docs.djangoproject.com/en/3.1/ref/settings/#databases 77 | 78 | DATABASES = { 79 | 'default': { 80 | 'ENGINE': 'django.db.backends.postgresql', 81 | 'NAME': 'd12ir0kk1vjhrr', 82 | 'USER': 'tfkjklgydmeggs', 83 | 'PASSWORD': 'bd0724b2750605c44e878d90fc1ea3c69ae965ae1ab210863e51edb0039ab0cc', 84 | 'HOST': 'ec2-35-171-109-11.compute-1.amazonaws.com', 85 | 'PORT': 5432, 86 | } 87 | } 88 | 89 | 90 | # Password validation 91 | # https://docs.djangoproject.com/en/3.1/ref/settings/#auth-password-validators 92 | 93 | AUTH_PASSWORD_VALIDATORS = [ 94 | { 95 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', 96 | }, 97 | { 98 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 99 | }, 100 | { 101 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', 102 | }, 103 | { 104 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', 105 | }, 106 | ] 107 | 108 | 109 | # Internationalization 110 | # https://docs.djangoproject.com/en/3.1/topics/i18n/ 111 | 112 | LANGUAGE_CODE = 'en-us' 113 | 114 | TIME_ZONE = 'UTC' 115 | 116 | USE_I18N = True 117 | 118 | USE_L10N = True 119 | 120 | USE_TZ = True 121 | 122 | 123 | # Static files (CSS, JavaScript, Images) 124 | # https://docs.djangoproject.com/en/3.1/howto/static-files/ 125 | 126 | STATIC_URL = '/static/' 127 | STATIC_ROOT = BASE_DIR / 'staticfiles' 128 | 129 | OWM_API_KEY = '66ff3434ba88fffc04bf3e1812207117' -------------------------------------------------------------------------------- /WeatherDashboard/WeatherDashboard/urls.py: -------------------------------------------------------------------------------- 1 | """WeatherDashboard URL Configuration 2 | 3 | The `urlpatterns` list routes URLs to views. For more information please see: 4 | https://docs.djangoproject.com/en/3.1/topics/http/urls/ 5 | Examples: 6 | Function views 7 | 1. Add an import: from my_app import views 8 | 2. Add a URL to urlpatterns: path('', views.home, name='home') 9 | Class-based views 10 | 1. Add an import: from other_app.views import Home 11 | 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') 12 | Including another URLconf 13 | 1. Import the include() function: from django.urls import include, path 14 | 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) 15 | """ 16 | from django.contrib import admin 17 | from django.urls import path 18 | from dashboard.views import ( 19 | home, history 20 | ) 21 | 22 | urlpatterns = [ 23 | path('admin/', admin.site.urls), 24 | path('', home, name='home'), 25 | path('history/', history, name='history'), 26 | ] 27 | -------------------------------------------------------------------------------- /WeatherDashboard/WeatherDashboard/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for WeatherDashboard project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.1/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'WeatherDashboard.settings') 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /WeatherDashboard/dashboard/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mnamegaurav/easy_django/a9b959f1e436a74a513ff5f9d948eb6cd8813a10/WeatherDashboard/dashboard/__init__.py -------------------------------------------------------------------------------- /WeatherDashboard/dashboard/__pycache__/__init__.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mnamegaurav/easy_django/a9b959f1e436a74a513ff5f9d948eb6cd8813a10/WeatherDashboard/dashboard/__pycache__/__init__.cpython-38.pyc -------------------------------------------------------------------------------- /WeatherDashboard/dashboard/__pycache__/admin.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mnamegaurav/easy_django/a9b959f1e436a74a513ff5f9d948eb6cd8813a10/WeatherDashboard/dashboard/__pycache__/admin.cpython-38.pyc -------------------------------------------------------------------------------- /WeatherDashboard/dashboard/__pycache__/forms.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mnamegaurav/easy_django/a9b959f1e436a74a513ff5f9d948eb6cd8813a10/WeatherDashboard/dashboard/__pycache__/forms.cpython-38.pyc -------------------------------------------------------------------------------- /WeatherDashboard/dashboard/__pycache__/helper.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mnamegaurav/easy_django/a9b959f1e436a74a513ff5f9d948eb6cd8813a10/WeatherDashboard/dashboard/__pycache__/helper.cpython-38.pyc -------------------------------------------------------------------------------- /WeatherDashboard/dashboard/__pycache__/models.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mnamegaurav/easy_django/a9b959f1e436a74a513ff5f9d948eb6cd8813a10/WeatherDashboard/dashboard/__pycache__/models.cpython-38.pyc -------------------------------------------------------------------------------- /WeatherDashboard/dashboard/__pycache__/views.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mnamegaurav/easy_django/a9b959f1e436a74a513ff5f9d948eb6cd8813a10/WeatherDashboard/dashboard/__pycache__/views.cpython-38.pyc -------------------------------------------------------------------------------- /WeatherDashboard/dashboard/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from dashboard.models import City 3 | # Register your models here. 4 | admin.site.register(City) -------------------------------------------------------------------------------- /WeatherDashboard/dashboard/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class DashboardConfig(AppConfig): 5 | name = 'dashboard' 6 | -------------------------------------------------------------------------------- /WeatherDashboard/dashboard/forms.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | from dashboard.models import City 3 | 4 | class CityForm(forms.ModelForm): 5 | 6 | class Meta: 7 | model = City 8 | fields = ('city_name',) 9 | widgets = { 10 | 'city_name': forms.TextInput(attrs={'class': 'form-control my-3 city-input w-75 mx-auto','placeholder':'City name!'}) 11 | } -------------------------------------------------------------------------------- /WeatherDashboard/dashboard/helper.py: -------------------------------------------------------------------------------- 1 | from django.conf import settings 2 | import requests 3 | 4 | 5 | def get_weather_data(city_name): 6 | url = 'https://api.openweathermap.org/data/2.5/weather' 7 | 8 | params = { 9 | 'q': city_name, 10 | 'appid': settings.OWM_API_KEY, 11 | 'units': 'metric', 12 | } 13 | 14 | response = requests.get(url, params=params) 15 | 16 | if response.status_code != 200: 17 | return 18 | 19 | json_response = response.json() 20 | 21 | weather_data = { 22 | 'temp': json_response['main']['temp'], 23 | 'temp_min': json_response['main']['temp_min'], 24 | 'temp_max': json_response['main']['temp_max'], 25 | 'city_name': json_response['name'], 26 | 'country': json_response['sys']['country'], 27 | 'lat': json_response['coord']['lat'], 28 | 'lon': json_response['coord']['lon'], 29 | 'weather': json_response['weather'][0]['main'], 30 | 'weather_desc': json_response['weather'][0]['description'], 31 | 'pressure': json_response['main']['pressure'], 32 | 'humidity': json_response['main']['humidity'], 33 | 'wind_speed': json_response['wind']['speed'], 34 | } 35 | 36 | return weather_data -------------------------------------------------------------------------------- /WeatherDashboard/dashboard/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.1.3 on 2020-11-26 16:13 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | initial = True 9 | 10 | dependencies = [ 11 | ] 12 | 13 | operations = [ 14 | migrations.CreateModel( 15 | name='City', 16 | fields=[ 17 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 18 | ('city_name', models.CharField(max_length=50)), 19 | ('date_added', models.DateTimeField(auto_now_add=True)), 20 | ], 21 | ), 22 | ] 23 | -------------------------------------------------------------------------------- /WeatherDashboard/dashboard/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mnamegaurav/easy_django/a9b959f1e436a74a513ff5f9d948eb6cd8813a10/WeatherDashboard/dashboard/migrations/__init__.py -------------------------------------------------------------------------------- /WeatherDashboard/dashboard/migrations/__pycache__/0001_initial.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mnamegaurav/easy_django/a9b959f1e436a74a513ff5f9d948eb6cd8813a10/WeatherDashboard/dashboard/migrations/__pycache__/0001_initial.cpython-38.pyc -------------------------------------------------------------------------------- /WeatherDashboard/dashboard/migrations/__pycache__/__init__.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mnamegaurav/easy_django/a9b959f1e436a74a513ff5f9d948eb6cd8813a10/WeatherDashboard/dashboard/migrations/__pycache__/__init__.cpython-38.pyc -------------------------------------------------------------------------------- /WeatherDashboard/dashboard/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | # Create your models here. 4 | class City(models.Model): 5 | city_name = models.CharField(max_length=50) 6 | date_added = models.DateTimeField(auto_now_add=True) 7 | 8 | def __str__(self): 9 | return self.city_name -------------------------------------------------------------------------------- /WeatherDashboard/dashboard/static/styles.css: -------------------------------------------------------------------------------- 1 | @media only screen and (min-width: 767px){ 2 | #sideform{ 3 | min-height: 94vh; 4 | } 5 | } 6 | 7 | #sideform{ 8 | background: linear-gradient(45deg, #fff, #8893ff); 9 | } 10 | 11 | .btn, .city-input{ 12 | border-radius: 20px; 13 | } 14 | 15 | #sideform p{ 16 | font-size: 1.2rem; 17 | } 18 | 19 | #dashboard-card{ 20 | background-image: url(weather-cloud.jpg); 21 | background-size: cover; 22 | background-blend-mode: hard-light; 23 | background-repeat: no-repeat; 24 | } 25 | 26 | footer{ 27 | position: fixed; 28 | bottom: 0; 29 | width: 100%; 30 | } -------------------------------------------------------------------------------- /WeatherDashboard/dashboard/static/weather-cloud.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mnamegaurav/easy_django/a9b959f1e436a74a513ff5f9d948eb6cd8813a10/WeatherDashboard/dashboard/static/weather-cloud.jpg -------------------------------------------------------------------------------- /WeatherDashboard/dashboard/templates/base.html: -------------------------------------------------------------------------------- 1 | {% load static %} 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | Weather Dashboard 15 | 16 | 17 | 18 | {% block content %}{% endblock %} 19 | 20 | {% include 'components/footer.html' %} 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /WeatherDashboard/dashboard/templates/components/card.html: -------------------------------------------------------------------------------- 1 | {% if weather_data %} 2 |
3 | 4 | 5 | 6 | 12 | 29 | 30 | 31 |
7 |
8 |

{{ weather_data.temp }}° C

9 |

{{ weather_data.temp_min }}°C - {{ weather_data.temp_max }}°C

10 |
11 |
13 |
14 |

{{ weather_data.city_name }}({{ weather_data.country }})

15 |
16 |
17 | 18 | Lattitude: 19 | {{ weather_data.lat }} 20 | 21 |
22 |
23 | 24 | Longitude: 25 | {{ weather_data.lon }} 26 | 27 |
28 |
32 |
33 |
34 | 35 | 36 | 37 | 43 | 44 | 45 | 51 | 52 | 53 | 58 | 59 | 60 | 66 | 67 | 68 |
38 |

39 | Weather: {{ weather_data.weather }} 40 | {{ weather_data.weather_desc }} 41 |

42 |
46 |

47 | Pressure: {{ weather_data.pressure }} 48 | hPa 49 |

50 |
54 |

55 | Humidity: {{ weather_data.humidity }} % 56 |

57 |
61 |

62 | Wind Speed: {{ weather_data.wind_speed }} 63 | m/s 64 |

65 |
69 |
70 |
71 |
72 | {% else %} 73 |
74 |
75 |

Data Not Found

76 |
77 |
78 | {% endif %} -------------------------------------------------------------------------------- /WeatherDashboard/dashboard/templates/components/footer.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /WeatherDashboard/dashboard/templates/components/sideform.html: -------------------------------------------------------------------------------- 1 |
2 |

What is Weather Like ?

3 |
4 |
5 | {% csrf_token %} 6 | {{ form.city_name }} 7 | 8 | History 9 |
10 |
11 |
-------------------------------------------------------------------------------- /WeatherDashboard/dashboard/templates/history.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | {% block content %} 4 | 10 | {% for weather_data in weather_data_list %} 11 | {% include 'components/card.html' %} 12 | {% endfor %} 13 | {% endblock %} -------------------------------------------------------------------------------- /WeatherDashboard/dashboard/templates/home.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | {% block content %} 4 | 5 |
6 |
7 |
8 | 9 | {% include 'components/sideform.html' %} 10 |
11 |
12 | 13 | {% include 'components/card.html' %} 14 |
15 |
16 |
17 | 18 | 19 | {% endblock %} 20 | -------------------------------------------------------------------------------- /WeatherDashboard/dashboard/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /WeatherDashboard/dashboard/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render 2 | from django.http import HttpResponse 3 | from dashboard.forms import CityForm 4 | from dashboard.models import City 5 | from dashboard.helper import get_weather_data 6 | # Create your views here. 7 | 8 | def home(request): 9 | form = CityForm() 10 | 11 | if request.method == 'POST': 12 | form = CityForm(request.POST) 13 | if form.is_valid(): 14 | form.save() 15 | city_name = form.cleaned_data.get('city_name') 16 | print(city_name) 17 | weather_data = get_weather_data(city_name) 18 | elif request.method == 'GET': 19 | try: 20 | city_name = City.objects.latest('date_added').city_name 21 | weather_data = get_weather_data(city_name) 22 | except Exception as e: 23 | weather_data = None 24 | 25 | template_name = 'home.html' 26 | context = {'form': form, 'weather_data': weather_data} 27 | return render(request, template_name, context=context) 28 | 29 | 30 | def history(request): 31 | template_name = 'history.html' 32 | cities = City.objects.all().order_by('-date_added')[:5] 33 | 34 | weather_data_list = [] 35 | for city in cities: 36 | city_name = city.city_name 37 | weather_data_list.append(get_weather_data(city_name)) 38 | 39 | context = {'weather_data_list': weather_data_list} 40 | return render(request, template_name, context) -------------------------------------------------------------------------------- /WeatherDashboard/manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Django's command-line utility for administrative tasks.""" 3 | import os 4 | import sys 5 | 6 | 7 | def main(): 8 | """Run administrative tasks.""" 9 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'WeatherDashboard.settings') 10 | try: 11 | from django.core.management import execute_from_command_line 12 | except ImportError as exc: 13 | raise ImportError( 14 | "Couldn't import Django. Are you sure it's installed and " 15 | "available on your PYTHONPATH environment variable? Did you " 16 | "forget to activate a virtual environment?" 17 | ) from exc 18 | execute_from_command_line(sys.argv) 19 | 20 | 21 | if __name__ == '__main__': 22 | main() 23 | -------------------------------------------------------------------------------- /WeatherDashboard/requirements.txt: -------------------------------------------------------------------------------- 1 | asgiref==3.3.1 2 | certifi==2020.11.8 3 | chardet==3.0.4 4 | Django==3.1.3 5 | gunicorn==20.0.4 6 | idna==2.10 7 | psycopg2==2.8.6 8 | pytz==2020.4 9 | requests==2.25.0 10 | sqlparse==0.4.1 11 | urllib3==1.26.2 12 | whitenoise==5.2.0 13 | --------------------------------------------------------------------------------