├── README.md ├── authy ├── __init__.py ├── __pycache__ │ ├── __init__.cpython-36.pyc │ ├── __init__.cpython-38.pyc │ ├── admin.cpython-36.pyc │ ├── admin.cpython-38.pyc │ ├── forms.cpython-36.pyc │ ├── forms.cpython-38.pyc │ ├── models.cpython-36.pyc │ ├── models.cpython-38.pyc │ ├── urls.cpython-36.pyc │ ├── urls.cpython-38.pyc │ ├── views.cpython-36.pyc │ └── views.cpython-38.pyc ├── admin.py ├── apps.py ├── forms.py ├── migrations │ ├── 0001_initial.py │ ├── 0002_profile_favorites.py │ ├── 0003_auto_20200718_1728.py │ ├── 0004_auto_20200814_0659.py │ ├── __init__.py │ └── __pycache__ │ │ ├── 0001_initial.cpython-36.pyc │ │ ├── 0001_initial.cpython-38.pyc │ │ ├── 0002_profile_favorites.cpython-36.pyc │ │ ├── 0003_auto_20200718_1728.cpython-36.pyc │ │ ├── 0004_auto_20200814_0659.cpython-36.pyc │ │ ├── __init__.cpython-36.pyc │ │ └── __init__.cpython-38.pyc ├── models.py ├── tests.py ├── urls.py └── views.py ├── comment ├── __init__.py ├── __pycache__ │ ├── __init__.cpython-36.pyc │ ├── admin.cpython-36.pyc │ ├── forms.cpython-36.pyc │ └── models.cpython-36.pyc ├── admin.py ├── apps.py ├── forms.py ├── migrations │ ├── 0001_initial.py │ ├── __init__.py │ └── __pycache__ │ │ ├── 0001_initial.cpython-36.pyc │ │ └── __init__.cpython-36.pyc ├── models.py ├── tests.py └── views.py ├── db.sqlite3 ├── direct ├── __init__.py ├── __pycache__ │ ├── __init__.cpython-36.pyc │ ├── admin.cpython-36.pyc │ ├── models.cpython-36.pyc │ ├── urls.cpython-36.pyc │ └── views.cpython-36.pyc ├── admin.py ├── apps.py ├── migrations │ ├── 0001_initial.py │ ├── 0002_auto_20200728_1611.py │ ├── 0003_auto_20200728_2032.py │ ├── __init__.py │ └── __pycache__ │ │ ├── 0001_initial.cpython-36.pyc │ │ ├── 0002_auto_20200728_1611.cpython-36.pyc │ │ ├── 0003_auto_20200728_2032.cpython-36.pyc │ │ └── __init__.cpython-36.pyc ├── models.py ├── tests.py ├── urls.py └── views.py ├── instagram_clone ├── __init__.py ├── __pycache__ │ ├── __init__.cpython-36.pyc │ ├── __init__.cpython-38.pyc │ ├── celery.cpython-36.pyc │ ├── settings.cpython-36.pyc │ ├── settings.cpython-38.pyc │ ├── urls.cpython-36.pyc │ ├── urls.cpython-38.pyc │ ├── wsgi.cpython-36.pyc │ └── wsgi.cpython-38.pyc ├── asgi.py ├── celery.py ├── settings.py ├── static │ ├── css │ │ ├── bulma-rtl.css │ │ ├── bulma-rtl.css.map │ │ ├── bulma-rtl.min.css │ │ ├── bulma.css │ │ ├── bulma.css.map │ │ ├── bulma.min.css │ │ └── style.css │ ├── img │ │ ├── 1-bezos.jpg │ │ ├── 1-elon.jpg │ │ ├── 1-zuckerberg.jpg │ │ ├── background1.jpg │ │ ├── background2.jpg │ │ ├── background3.jpg │ │ ├── default-thumbnail.jpg │ │ ├── instagram_black.png │ │ ├── instagram_black_logo.png │ │ ├── person.jpg │ │ └── profile_banner.jpg │ └── js │ │ ├── init.js │ │ └── slider.js ├── templates │ ├── base.html │ ├── change_password.html │ ├── change_password_done.html │ ├── direct │ │ ├── direct.html │ │ └── search_user.html │ ├── edit_profile.html │ ├── index.html │ ├── login.html │ ├── newpost.html │ ├── newstory.html │ ├── notifications.html │ ├── post_detail.html │ ├── profile.html │ ├── profile_favorite.html │ ├── registration │ │ ├── password_reset_complete.html │ │ ├── password_reset_confirm.html │ │ ├── password_reset_done.html │ │ ├── password_reset_email.html │ │ ├── password_reset_form.html │ │ └── password_reset_subject.txt │ ├── signup.html │ └── tag.html ├── urls.py └── wsgi.py ├── manage.py ├── media ├── profile_pictures │ └── bill.jpg ├── uploads │ └── 2020 │ │ └── 06 │ │ └── 26 │ │ ├── a0002587_main.jpg │ │ ├── hibana.jpg │ │ ├── spacex.jpg │ │ ├── spacex_gnKvd23.jpg │ │ └── spacex_tzgKL89.jpg ├── user_1 │ ├── a0002587_main.jpg │ ├── a0002587_main_iJ1w7EO.jpg │ ├── a0002587_main_iMSuoF3.jpg │ ├── a0002587_main_ndO2OEP.jpg │ ├── a0002587_main_r9k1cIr.jpg │ ├── darksouls.jpg │ ├── darksouls2.jpg │ ├── darksouls2_2vXOblt.jpg │ ├── darksouls2_5UaL8Wj.jpg │ ├── darksouls2_BSfQRxg.jpg │ ├── darksouls2_IN0tTC6.jpg │ ├── darksouls2_fOXXHZu.jpg │ ├── subaru.jpg │ ├── subaru_S8GJMym.jpg │ ├── teslamodel3.jpg │ ├── teslamodel3_Wv2aEl0.jpg │ ├── teslamodel3_aIaYMO3.jpg │ ├── teslamodel3_le2UcGV.jpg │ └── teslamodel3_sfWVsyZ.jpg ├── user_10 │ └── profile.jpg ├── user_11 │ └── profile.jpg ├── user_2 │ ├── a0002587_main.jpg │ ├── a0002587_main_8BuBEhp.jpg │ ├── a0002587_main_A5WqTlr.jpg │ ├── a0002587_main_Qfd0luw.jpg │ ├── a0002587_main_RaWvmHy.jpg │ ├── a0002587_main_V0oyt5X.jpg │ ├── a0002587_main_n2yfSyP.jpg │ ├── darksouls.jpg │ ├── darksouls2.jpg │ ├── hibana.jpg │ ├── hibana_BpkXLTU.jpg │ ├── hibana_OCTcqhF.jpg │ ├── hibana_Qhgg6n9.jpg │ ├── hibana_WbbqbZi.jpg │ ├── hibana_dJYMDvR.jpg │ ├── subaru.jpg │ ├── subaru_7MsJh7S.jpg │ ├── teslamodel3.jpg │ ├── teslamodel3_0KhTs3Z.jpg │ ├── teslamodel3_FUxb2Dv.jpg │ ├── teslamodel3_MteRF8i.jpg │ ├── teslamodel3_VT0FT0F.jpg │ ├── teslamodel3_d9T59JI.jpg │ ├── teslamodel3_dYKGv0J.jpg │ └── teslamodel3_mo9yYcT.jpg ├── user_3 │ ├── darksouls.jpg │ └── profile.jpg ├── user_4 │ ├── 1473746638306.jpg │ ├── 1473746638306_bhzROKZ.jpg │ ├── When_they_have_face_tattoos.mp4 │ ├── When_they_have_face_tattoos_HQaN9Gq.mp4 │ ├── When_they_have_face_tattoos_VBk3yun.mp4 │ ├── a0002587_main.jpg │ ├── dims.jpg │ ├── dims_HH8EK5N.jpg │ ├── galaxy-clusters.jpg │ ├── mclaren-720s-1.jpg │ ├── microsoft.jpeg │ ├── microsoft_44PwWTl.jpeg │ ├── porsche911gt3rs_01.jpg │ └── rauh-welt-begriff-porsche-911-on-forgestar-wheels.jpg ├── user_5 │ ├── ca-times.brightspotcdn.com.jpeg │ ├── image.jpg │ └── profile.jpg ├── user_7 │ ├── .jpg │ ├── Porsche-911-1-1024x555.jpg │ ├── Porsche-911-1-1024x555_HQg1ikd.jpg │ └── profile.jpg └── user_9 │ └── profile.jpg ├── notifications ├── __init__.py ├── __pycache__ │ ├── __init__.cpython-36.pyc │ ├── admin.cpython-36.pyc │ ├── models.cpython-36.pyc │ ├── urls.cpython-36.pyc │ └── views.cpython-36.pyc ├── admin.py ├── apps.py ├── migrations │ ├── 0001_initial.py │ ├── 0002_auto_20200801_1835.py │ ├── 0003_notification_date.py │ ├── 0004_auto_20200809_0634.py │ ├── 0005_auto_20200810_0018.py │ ├── 0006_auto_20200810_0149.py │ ├── 0007_auto_20200810_0157.py │ ├── __init__.py │ └── __pycache__ │ │ ├── 0001_initial.cpython-36.pyc │ │ ├── 0002_auto_20200801_1835.cpython-36.pyc │ │ ├── 0003_notification_date.cpython-36.pyc │ │ ├── 0004_auto_20200809_0634.cpython-36.pyc │ │ ├── 0005_auto_20200810_0018.cpython-36.pyc │ │ ├── 0006_auto_20200810_0149.cpython-36.pyc │ │ ├── 0007_auto_20200810_0157.cpython-36.pyc │ │ └── __init__.cpython-36.pyc ├── models.py ├── tests.py ├── urls.py └── views.py ├── post ├── __init__.py ├── __pycache__ │ ├── __init__.cpython-36.pyc │ ├── admin.cpython-36.pyc │ ├── forms.cpython-36.pyc │ ├── models.cpython-36.pyc │ ├── urls.cpython-36.pyc │ └── views.cpython-36.pyc ├── admin.py ├── apps.py ├── forms.py ├── migrations │ ├── 0001_initial.py │ ├── 0002_auto_20200626_1656.py │ ├── 0003_auto_20200626_1823.py │ ├── 0004_auto_20200626_1846.py │ ├── 0005_auto_20200705_0042.py │ ├── 0006_auto_20200705_0158.py │ ├── 0007_likes.py │ ├── 0008_auto_20200717_2200.py │ ├── 0009_auto_20200717_2227.py │ ├── 0010_auto_20201015_0542.py │ ├── __init__.py │ └── __pycache__ │ │ ├── 0001_initial.cpython-36.pyc │ │ ├── 0002_auto_20200626_1656.cpython-36.pyc │ │ ├── 0003_auto_20200626_1823.cpython-36.pyc │ │ ├── 0004_auto_20200626_1846.cpython-36.pyc │ │ ├── 0005_auto_20200705_0042.cpython-36.pyc │ │ ├── 0006_auto_20200705_0158.cpython-36.pyc │ │ ├── 0007_likes.cpython-36.pyc │ │ ├── 0008_auto_20200717_2200.cpython-36.pyc │ │ ├── 0009_auto_20200717_2227.cpython-36.pyc │ │ ├── 0010_auto_20201015_0542.cpython-36.pyc │ │ └── __init__.cpython-36.pyc ├── models.py ├── tests.py ├── urls.py └── views.py ├── requirements.txt ├── screenshots ├── screen1.png ├── screen2.png ├── screen3.png ├── screen4.png ├── screen5.png ├── screen6.png ├── screen7.png └── screen8.png └── stories ├── __init__.py ├── __pycache__ ├── __init__.cpython-36.pyc ├── admin.cpython-36.pyc ├── forms.cpython-36.pyc ├── models.cpython-36.pyc ├── tasks.cpython-36.pyc ├── urls.cpython-36.pyc └── views.cpython-36.pyc ├── admin.py ├── apps.py ├── forms.py ├── migrations ├── 0001_initial.py ├── __init__.py └── __pycache__ │ ├── 0001_initial.cpython-36.pyc │ └── __init__.cpython-36.pyc ├── models.py ├── tasks.py ├── tests.py ├── urls.py └── views.py /README.md: -------------------------------------------------------------------------------- 1 | # Instagram clone in Django 2 | 3 | Basic Instagram clone website built in django web framework using Python. 4 | 5 | ## Getting Started 6 | 7 | -Install the prerequisites 8 | -Run the server 9 | 10 | admin: 11 | demo 12 | password: 13 | demo1234 14 | 15 | ### Prerequisites 16 | 17 | You can install the Prerequisites by running the command: 18 | 19 | ``` 20 | pip install -r requirements.txt 21 | ``` 22 | 23 | ``` 24 | asgiref==3.2.10 25 | Django==3.0.7 26 | Pillow==7.1.2 27 | pkg-resources==0.0.0 28 | pytz==2020.1 29 | sqlparse==0.3.1 30 | celery==5.0.0 31 | django-celery-beat==2.0.0 32 | ``` 33 | 34 | ## Screenshots 35 | 36 | ![Screen](screenshots/screen1.png?raw=true) 37 | ![Screen](screenshots/screen2.png?raw=true) 38 | ![Screen](screenshots/screen3.png?raw=true) 39 | ![Screen](screenshots/screen4.png?raw=true) 40 | ![Screen](screenshots/screen5.png?raw=true) 41 | ![Screen](screenshots/screen6.png?raw=true) 42 | ![Screen](screenshots/screen7.png?raw=true) 43 | ![Screen](screenshots/screen8.png?raw=true) 44 | 45 | 46 | 47 | 48 | ## Built With 49 | 50 | * [Bulma](https://bulma.io/) - Bulma is a free, open source CSS framework based on Flexbox 51 | * [Django](https://www.djangoproject.com/) - Web framework 52 | -------------------------------------------------------------------------------- /authy/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byronlara5/django_instagram_clone_youtube/a5204bf07e22ce17f9a22e724656502a3e7cd627/authy/__init__.py -------------------------------------------------------------------------------- /authy/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byronlara5/django_instagram_clone_youtube/a5204bf07e22ce17f9a22e724656502a3e7cd627/authy/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /authy/__pycache__/__init__.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byronlara5/django_instagram_clone_youtube/a5204bf07e22ce17f9a22e724656502a3e7cd627/authy/__pycache__/__init__.cpython-38.pyc -------------------------------------------------------------------------------- /authy/__pycache__/admin.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byronlara5/django_instagram_clone_youtube/a5204bf07e22ce17f9a22e724656502a3e7cd627/authy/__pycache__/admin.cpython-36.pyc -------------------------------------------------------------------------------- /authy/__pycache__/admin.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byronlara5/django_instagram_clone_youtube/a5204bf07e22ce17f9a22e724656502a3e7cd627/authy/__pycache__/admin.cpython-38.pyc -------------------------------------------------------------------------------- /authy/__pycache__/forms.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byronlara5/django_instagram_clone_youtube/a5204bf07e22ce17f9a22e724656502a3e7cd627/authy/__pycache__/forms.cpython-36.pyc -------------------------------------------------------------------------------- /authy/__pycache__/forms.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byronlara5/django_instagram_clone_youtube/a5204bf07e22ce17f9a22e724656502a3e7cd627/authy/__pycache__/forms.cpython-38.pyc -------------------------------------------------------------------------------- /authy/__pycache__/models.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byronlara5/django_instagram_clone_youtube/a5204bf07e22ce17f9a22e724656502a3e7cd627/authy/__pycache__/models.cpython-36.pyc -------------------------------------------------------------------------------- /authy/__pycache__/models.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byronlara5/django_instagram_clone_youtube/a5204bf07e22ce17f9a22e724656502a3e7cd627/authy/__pycache__/models.cpython-38.pyc -------------------------------------------------------------------------------- /authy/__pycache__/urls.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byronlara5/django_instagram_clone_youtube/a5204bf07e22ce17f9a22e724656502a3e7cd627/authy/__pycache__/urls.cpython-36.pyc -------------------------------------------------------------------------------- /authy/__pycache__/urls.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byronlara5/django_instagram_clone_youtube/a5204bf07e22ce17f9a22e724656502a3e7cd627/authy/__pycache__/urls.cpython-38.pyc -------------------------------------------------------------------------------- /authy/__pycache__/views.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byronlara5/django_instagram_clone_youtube/a5204bf07e22ce17f9a22e724656502a3e7cd627/authy/__pycache__/views.cpython-36.pyc -------------------------------------------------------------------------------- /authy/__pycache__/views.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byronlara5/django_instagram_clone_youtube/a5204bf07e22ce17f9a22e724656502a3e7cd627/authy/__pycache__/views.cpython-38.pyc -------------------------------------------------------------------------------- /authy/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from authy.models import Profile 3 | # Register your models here. 4 | 5 | admin.site.register(Profile) -------------------------------------------------------------------------------- /authy/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class AuthyConfig(AppConfig): 5 | name = 'authy' 6 | -------------------------------------------------------------------------------- /authy/forms.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | from django.contrib.auth.models import User 3 | from django.core.exceptions import ValidationError 4 | from authy.models import Profile 5 | 6 | def ForbiddenUsers(value): 7 | forbidden_users = ['admin', 'css', 'js', 'authenticate', 'login', 'logout', 'administrator', 'root', 8 | 'email', 'user', 'join', 'sql', 'static', 'python', 'delete'] 9 | if value.lower() in forbidden_users: 10 | raise ValidationError('Invalid name for user, this is a reserverd word.') 11 | 12 | def InvalidUser(value): 13 | if '@' in value or '+' in value or '-' in value: 14 | raise ValidationError('This is an Invalid user, Do not user these chars: @ , - , + ') 15 | 16 | def UniqueEmail(value): 17 | if User.objects.filter(email__iexact=value).exists(): 18 | raise ValidationError('User with this email already exists.') 19 | 20 | def UniqueUser(value): 21 | if User.objects.filter(username__iexact=value).exists(): 22 | raise ValidationError('User with this username already exists.') 23 | 24 | class SignupForm(forms.ModelForm): 25 | username = forms.CharField(widget=forms.TextInput(), max_length=30, required=True,) 26 | email = forms.CharField(widget=forms.EmailInput(), max_length=100, required=True,) 27 | password = forms.CharField(widget=forms.PasswordInput()) 28 | confirm_password = forms.CharField(widget=forms.PasswordInput(), required=True, label="Confirm your password.") 29 | 30 | class Meta: 31 | 32 | model = User 33 | fields = ('username', 'email', 'password') 34 | 35 | def __init__(self, *args, **kwargs): 36 | super(SignupForm, self).__init__(*args, **kwargs) 37 | self.fields['username'].validators.append(ForbiddenUsers) 38 | self.fields['username'].validators.append(InvalidUser) 39 | self.fields['username'].validators.append(UniqueUser) 40 | self.fields['email'].validators.append(UniqueEmail) 41 | 42 | def clean(self): 43 | super(SignupForm, self).clean() 44 | password = self.cleaned_data.get('password') 45 | confirm_password = self.cleaned_data.get('confirm_password') 46 | 47 | if password != confirm_password: 48 | self._errors['password'] = self.error_class(['Passwords do not match. Try again']) 49 | return self.cleaned_data 50 | 51 | class ChangePasswordForm(forms.ModelForm): 52 | id = forms.CharField(widget=forms.HiddenInput()) 53 | old_password = forms.CharField(widget=forms.PasswordInput(attrs={'class': 'input is-medium'}), label="Old password", required=True) 54 | new_password = forms.CharField(widget=forms.PasswordInput(attrs={'class': 'input is-medium'}), label="New password", required=True) 55 | confirm_password = forms.CharField(widget=forms.PasswordInput(attrs={'class': 'input is-medium'}), label="Confirm new password", required=True) 56 | 57 | class Meta: 58 | model = User 59 | fields = ('id', 'old_password', 'new_password', 'confirm_password') 60 | 61 | def clean(self): 62 | super(ChangePasswordForm, self).clean() 63 | id = self.cleaned_data.get('id') 64 | old_password = self.cleaned_data.get('old_password') 65 | new_password = self.cleaned_data.get('new_password') 66 | confirm_password = self.cleaned_data.get('confirm_password') 67 | user = User.objects.get(pk=id) 68 | if not user.check_password(old_password): 69 | self._errors['old_password'] =self.error_class(['Old password do not match.']) 70 | if new_password != confirm_password: 71 | self._errors['new_password'] =self.error_class(['Passwords do not match.']) 72 | return self.cleaned_data 73 | 74 | class EditProfileForm(forms.ModelForm): 75 | picture = forms.ImageField(required=False) 76 | first_name = forms.CharField(widget=forms.TextInput(), max_length=50, required=False) 77 | last_name = forms.CharField(widget=forms.TextInput(), max_length=50, required=False) 78 | location = forms.CharField(widget=forms.TextInput(), max_length=25, required=False) 79 | url = forms.URLField(widget=forms.TextInput(), max_length=60, required=False) 80 | profile_info = forms.CharField(widget=forms.TextInput(), max_length=260, required=False) 81 | 82 | class Meta: 83 | model = Profile 84 | fields = ('picture', 'first_name', 'last_name', 'location', 'url', 'profile_info') -------------------------------------------------------------------------------- /authy/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.0.7 on 2020-06-18 15:38 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='Profile', 19 | fields=[ 20 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 21 | ('first_name', models.CharField(blank=True, max_length=50, null=True)), 22 | ('last_name', models.CharField(blank=True, max_length=50, null=True)), 23 | ('location', models.CharField(blank=True, max_length=50, null=True)), 24 | ('url', models.CharField(blank=True, max_length=80, null=True)), 25 | ('profile_info', models.TextField(blank=True, max_length=150, null=True)), 26 | ('created', models.DateField(auto_now_add=True)), 27 | ('picture', models.ImageField(blank=True, null=True, upload_to='profile_pictures', verbose_name='Picture')), 28 | ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), 29 | ], 30 | ), 31 | ] 32 | -------------------------------------------------------------------------------- /authy/migrations/0002_profile_favorites.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.0.7 on 2020-07-11 21:30 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('post', '0007_likes'), 10 | ('authy', '0001_initial'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AddField( 15 | model_name='profile', 16 | name='favorites', 17 | field=models.ManyToManyField(to='post.Post'), 18 | ), 19 | ] 20 | -------------------------------------------------------------------------------- /authy/migrations/0003_auto_20200718_1728.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.0.7 on 2020-07-18 17:28 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 | ('authy', '0002_profile_favorites'), 13 | ] 14 | 15 | operations = [ 16 | migrations.AlterField( 17 | model_name='profile', 18 | name='user', 19 | field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='profile', to=settings.AUTH_USER_MODEL), 20 | ), 21 | ] 22 | -------------------------------------------------------------------------------- /authy/migrations/0004_auto_20200814_0659.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.0.7 on 2020-08-14 06:59 2 | 3 | import authy.models 4 | from django.db import migrations, models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('authy', '0003_auto_20200718_1728'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AlterField( 15 | model_name='profile', 16 | name='picture', 17 | field=models.ImageField(blank=True, null=True, upload_to=authy.models.user_directory_path, verbose_name='Picture'), 18 | ), 19 | ] 20 | -------------------------------------------------------------------------------- /authy/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byronlara5/django_instagram_clone_youtube/a5204bf07e22ce17f9a22e724656502a3e7cd627/authy/migrations/__init__.py -------------------------------------------------------------------------------- /authy/migrations/__pycache__/0001_initial.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byronlara5/django_instagram_clone_youtube/a5204bf07e22ce17f9a22e724656502a3e7cd627/authy/migrations/__pycache__/0001_initial.cpython-36.pyc -------------------------------------------------------------------------------- /authy/migrations/__pycache__/0001_initial.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byronlara5/django_instagram_clone_youtube/a5204bf07e22ce17f9a22e724656502a3e7cd627/authy/migrations/__pycache__/0001_initial.cpython-38.pyc -------------------------------------------------------------------------------- /authy/migrations/__pycache__/0002_profile_favorites.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byronlara5/django_instagram_clone_youtube/a5204bf07e22ce17f9a22e724656502a3e7cd627/authy/migrations/__pycache__/0002_profile_favorites.cpython-36.pyc -------------------------------------------------------------------------------- /authy/migrations/__pycache__/0003_auto_20200718_1728.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byronlara5/django_instagram_clone_youtube/a5204bf07e22ce17f9a22e724656502a3e7cd627/authy/migrations/__pycache__/0003_auto_20200718_1728.cpython-36.pyc -------------------------------------------------------------------------------- /authy/migrations/__pycache__/0004_auto_20200814_0659.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byronlara5/django_instagram_clone_youtube/a5204bf07e22ce17f9a22e724656502a3e7cd627/authy/migrations/__pycache__/0004_auto_20200814_0659.cpython-36.pyc -------------------------------------------------------------------------------- /authy/migrations/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byronlara5/django_instagram_clone_youtube/a5204bf07e22ce17f9a22e724656502a3e7cd627/authy/migrations/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /authy/migrations/__pycache__/__init__.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byronlara5/django_instagram_clone_youtube/a5204bf07e22ce17f9a22e724656502a3e7cd627/authy/migrations/__pycache__/__init__.cpython-38.pyc -------------------------------------------------------------------------------- /authy/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | from django.contrib.auth.models import User 3 | from post.models import Post 4 | 5 | from django.db.models.signals import post_save 6 | 7 | from PIL import Image 8 | from django.conf import settings 9 | import os 10 | 11 | def user_directory_path(instance, filename): 12 | # file will be uploaded to MEDIA_ROOT/user_/ 13 | profile_pic_name = 'user_{0}/profile.jpg'.format(instance.user.id) 14 | full_path = os.path.join(settings.MEDIA_ROOT, profile_pic_name) 15 | 16 | if os.path.exists(full_path): 17 | os.remove(full_path) 18 | 19 | return profile_pic_name 20 | 21 | # Create your models here. 22 | class Profile(models.Model): 23 | user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='profile') 24 | first_name = models.CharField(max_length=50, null=True, blank=True) 25 | last_name = models.CharField(max_length=50, null=True, blank=True) 26 | location = models.CharField(max_length=50, null=True, blank=True) 27 | url = models.CharField(max_length=80, null=True, blank=True) 28 | profile_info = models.TextField(max_length=150, null=True, blank=True) 29 | created = models.DateField(auto_now_add=True) 30 | favorites = models.ManyToManyField(Post) 31 | picture = models.ImageField(upload_to=user_directory_path, blank=True, null=True, verbose_name='Picture') 32 | 33 | def save(self, *args, **kwargs): 34 | super().save(*args, **kwargs) 35 | SIZE = 250, 250 36 | 37 | if self.picture: 38 | pic = Image.open(self.picture.path) 39 | pic.thumbnail(SIZE, Image.LANCZOS) 40 | pic.save(self.picture.path) 41 | 42 | def __str__(self): 43 | return self.user.username 44 | 45 | 46 | def create_user_profile(sender, instance, created, **kwargs): 47 | if created: 48 | Profile.objects.create(user=instance) 49 | 50 | def save_user_profile(sender, instance, **kwargs): 51 | instance.profile.save() 52 | 53 | post_save.connect(create_user_profile, sender=User) 54 | post_save.connect(save_user_profile, sender=User) -------------------------------------------------------------------------------- /authy/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /authy/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | from authy.views import UserProfile, Signup, PasswordChange, PasswordChangeDone, EditProfile 3 | 4 | from django.contrib.auth import views as authViews 5 | 6 | 7 | 8 | urlpatterns = [ 9 | 10 | path('profile/edit', EditProfile, name='edit-profile'), 11 | path('signup/', Signup, name='signup'), 12 | path('login/', authViews.LoginView.as_view(template_name='login.html'), name='login'), 13 | path('logout/', authViews.LogoutView.as_view(), {'next_page' : 'index'}, name='logout'), 14 | path('changepassword/', PasswordChange, name='change_password'), 15 | path('changepassword/done', PasswordChangeDone, name='change_password_done'), 16 | path('passwordreset/', authViews.PasswordResetView.as_view(), name='password_reset'), 17 | path('passwordreset/done', authViews.PasswordResetDoneView.as_view(), name='password_reset_done'), 18 | path('passwordreset///', authViews.PasswordResetConfirmView.as_view(), name='password_reset_confirm'), 19 | path('passwordreset/complete/', authViews.PasswordResetCompleteView.as_view(), name='password_reset_complete'), 20 | 21 | 22 | ] -------------------------------------------------------------------------------- /authy/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render, redirect, get_object_or_404 2 | from authy.forms import SignupForm, ChangePasswordForm, EditProfileForm 3 | from django.contrib.auth.models import User 4 | 5 | from django.contrib.auth.decorators import login_required 6 | from django.contrib.auth import update_session_auth_hash 7 | 8 | from authy.models import Profile 9 | from post.models import Post, Follow, Stream 10 | from django.db import transaction 11 | from django.template import loader 12 | from django.http import HttpResponse, HttpResponseRedirect 13 | from django.urls import reverse 14 | 15 | from django.core.paginator import Paginator 16 | 17 | from django.urls import resolve 18 | 19 | # Create your views here. 20 | def UserProfile(request, username): 21 | user = get_object_or_404(User, username=username) 22 | profile = Profile.objects.get(user=user) 23 | url_name = resolve(request.path).url_name 24 | 25 | if url_name == 'profile': 26 | posts = Post.objects.filter(user=user).order_by('-posted') 27 | 28 | else: 29 | posts = profile.favorites.all() 30 | 31 | #Profile info box 32 | posts_count = Post.objects.filter(user=user).count() 33 | following_count = Follow.objects.filter(follower=user).count() 34 | followers_count = Follow.objects.filter(following=user).count() 35 | 36 | #follow status 37 | follow_status = Follow.objects.filter(following=user, follower=request.user).exists() 38 | 39 | #Pagination 40 | paginator = Paginator(posts, 8) 41 | page_number = request.GET.get('page') 42 | posts_paginator = paginator.get_page(page_number) 43 | 44 | template = loader.get_template('profile.html') 45 | 46 | context = { 47 | 'posts': posts_paginator, 48 | 'profile':profile, 49 | 'following_count':following_count, 50 | 'followers_count':followers_count, 51 | 'posts_count':posts_count, 52 | 'follow_status':follow_status, 53 | 'url_name':url_name, 54 | } 55 | 56 | return HttpResponse(template.render(context, request)) 57 | 58 | def UserProfileFavorites(request, username): 59 | user = get_object_or_404(User, username=username) 60 | profile = Profile.objects.get(user=user) 61 | 62 | posts = profile.favorites.all() 63 | 64 | #Profile info box 65 | posts_count = Post.objects.filter(user=user).count() 66 | following_count = Follow.objects.filter(follower=user).count() 67 | followers_count = Follow.objects.filter(following=user).count() 68 | 69 | #Pagination 70 | paginator = Paginator(posts, 8) 71 | page_number = request.GET.get('page') 72 | posts_paginator = paginator.get_page(page_number) 73 | 74 | template = loader.get_template('profile_favorite.html') 75 | 76 | context = { 77 | 'posts': posts_paginator, 78 | 'profile':profile, 79 | 'following_count':following_count, 80 | 'followers_count':followers_count, 81 | 'posts_count':posts_count, 82 | } 83 | 84 | return HttpResponse(template.render(context, request)) 85 | 86 | 87 | def Signup(request): 88 | if request.method == 'POST': 89 | form = SignupForm(request.POST) 90 | if form.is_valid(): 91 | username = form.cleaned_data.get('username') 92 | email = form.cleaned_data.get('email') 93 | password = form.cleaned_data.get('password') 94 | User.objects.create_user(username=username, email=email, password=password) 95 | return redirect('index') 96 | else: 97 | form = SignupForm() 98 | 99 | context = { 100 | 'form':form, 101 | } 102 | 103 | return render(request, 'signup.html', context) 104 | 105 | 106 | @login_required 107 | def PasswordChange(request): 108 | user = request.user 109 | if request.method == 'POST': 110 | form = ChangePasswordForm(request.POST) 111 | if form.is_valid(): 112 | new_password = form.cleaned_data.get('new_password') 113 | user.set_password(new_password) 114 | user.save() 115 | update_session_auth_hash(request, user) 116 | return redirect('change_password_done') 117 | else: 118 | form = ChangePasswordForm(instance=user) 119 | 120 | context = { 121 | 'form':form, 122 | } 123 | 124 | return render(request, 'change_password.html', context) 125 | 126 | def PasswordChangeDone(request): 127 | return render(request, 'change_password_done.html') 128 | 129 | 130 | @login_required 131 | def EditProfile(request): 132 | user = request.user.id 133 | profile = Profile.objects.get(user__id=user) 134 | BASE_WIDTH = 400 135 | 136 | if request.method == 'POST': 137 | form = EditProfileForm(request.POST, request.FILES) 138 | if form.is_valid(): 139 | profile.picture = form.cleaned_data.get('picture') 140 | profile.first_name = form.cleaned_data.get('first_name') 141 | profile.last_name = form.cleaned_data.get('last_name') 142 | profile.location = form.cleaned_data.get('location') 143 | profile.url = form.cleaned_data.get('url') 144 | profile.profile_info = form.cleaned_data.get('profile_info') 145 | profile.save() 146 | return redirect('index') 147 | else: 148 | form = EditProfileForm() 149 | 150 | context = { 151 | 'form':form, 152 | } 153 | 154 | return render(request, 'edit_profile.html', context) 155 | 156 | 157 | @login_required 158 | def follow(request, username, option): 159 | following = get_object_or_404(User, username=username) 160 | 161 | try: 162 | f, created = Follow.objects.get_or_create(follower=request.user, following=following) 163 | 164 | if int(option) == 0: 165 | f.delete() 166 | Stream.objects.filter(following=following, user=request.user).all().delete() 167 | else: 168 | posts = Post.objects.all().filter(user=following)[:25] 169 | 170 | with transaction.atomic(): 171 | for post in posts: 172 | stream = Stream(post=post, user=request.user, date=post.posted, following=following) 173 | stream.save() 174 | 175 | return HttpResponseRedirect(reverse('profile', args=[username])) 176 | except User.DoesNotExist: 177 | return HttpResponseRedirect(reverse('profile', args=[username])) -------------------------------------------------------------------------------- /comment/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byronlara5/django_instagram_clone_youtube/a5204bf07e22ce17f9a22e724656502a3e7cd627/comment/__init__.py -------------------------------------------------------------------------------- /comment/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byronlara5/django_instagram_clone_youtube/a5204bf07e22ce17f9a22e724656502a3e7cd627/comment/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /comment/__pycache__/admin.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byronlara5/django_instagram_clone_youtube/a5204bf07e22ce17f9a22e724656502a3e7cd627/comment/__pycache__/admin.cpython-36.pyc -------------------------------------------------------------------------------- /comment/__pycache__/forms.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byronlara5/django_instagram_clone_youtube/a5204bf07e22ce17f9a22e724656502a3e7cd627/comment/__pycache__/forms.cpython-36.pyc -------------------------------------------------------------------------------- /comment/__pycache__/models.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byronlara5/django_instagram_clone_youtube/a5204bf07e22ce17f9a22e724656502a3e7cd627/comment/__pycache__/models.cpython-36.pyc -------------------------------------------------------------------------------- /comment/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from comment.models import Comment 3 | # Register your models here. 4 | 5 | admin.site.register(Comment) -------------------------------------------------------------------------------- /comment/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class CommentConfig(AppConfig): 5 | name = 'comment' 6 | -------------------------------------------------------------------------------- /comment/forms.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | from comment.models import Comment 3 | 4 | class CommentForm(forms.ModelForm): 5 | body = forms.CharField(widget=forms.Textarea(attrs={'class': 'textarea'}), required=True) 6 | 7 | class Meta: 8 | model = Comment 9 | fields = ('body',) -------------------------------------------------------------------------------- /comment/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.0.7 on 2020-07-18 17:28 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 | ('post', '0009_auto_20200717_2227'), 15 | ] 16 | 17 | operations = [ 18 | migrations.CreateModel( 19 | name='Comment', 20 | fields=[ 21 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 22 | ('body', models.TextField()), 23 | ('date', models.DateTimeField(auto_now_add=True)), 24 | ('post', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='comments', to='post.Post')), 25 | ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), 26 | ], 27 | ), 28 | ] 29 | -------------------------------------------------------------------------------- /comment/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byronlara5/django_instagram_clone_youtube/a5204bf07e22ce17f9a22e724656502a3e7cd627/comment/migrations/__init__.py -------------------------------------------------------------------------------- /comment/migrations/__pycache__/0001_initial.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byronlara5/django_instagram_clone_youtube/a5204bf07e22ce17f9a22e724656502a3e7cd627/comment/migrations/__pycache__/0001_initial.cpython-36.pyc -------------------------------------------------------------------------------- /comment/migrations/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byronlara5/django_instagram_clone_youtube/a5204bf07e22ce17f9a22e724656502a3e7cd627/comment/migrations/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /comment/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | from post.models import Post 3 | from django.contrib.auth.models import User 4 | from notifications.models import Notification 5 | 6 | from django.db.models.signals import post_save, post_delete 7 | 8 | # Create your models here. 9 | 10 | class Comment(models.Model): 11 | post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='comments') 12 | user = models.ForeignKey(User, on_delete=models.CASCADE) 13 | body = models.TextField() 14 | date = models.DateTimeField(auto_now_add=True) 15 | 16 | def user_comment_post(sender, instance, *args, **kwargs): 17 | comment = instance 18 | post = comment.post 19 | text_preview = comment.body[:90] 20 | sender = comment.user 21 | notify = Notification(post=post, sender=sender, user=post.user, text_preview=text_preview ,notification_type=2) 22 | notify.save() 23 | 24 | def user_del_comment_post(sender, instance, *args, **kwargs): 25 | like = instance 26 | post = like.post 27 | sender = like.user 28 | 29 | notify = Notification.objects.filter(post=post, sender=sender, notification_type=2) 30 | notify.delete() 31 | 32 | #Comment 33 | post_save.connect(Comment.user_comment_post, sender=Comment) 34 | post_delete.connect(Comment.user_del_comment_post, sender=Comment) -------------------------------------------------------------------------------- /comment/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /comment/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render 2 | 3 | # Create your views here. 4 | -------------------------------------------------------------------------------- /db.sqlite3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byronlara5/django_instagram_clone_youtube/a5204bf07e22ce17f9a22e724656502a3e7cd627/db.sqlite3 -------------------------------------------------------------------------------- /direct/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byronlara5/django_instagram_clone_youtube/a5204bf07e22ce17f9a22e724656502a3e7cd627/direct/__init__.py -------------------------------------------------------------------------------- /direct/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byronlara5/django_instagram_clone_youtube/a5204bf07e22ce17f9a22e724656502a3e7cd627/direct/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /direct/__pycache__/admin.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byronlara5/django_instagram_clone_youtube/a5204bf07e22ce17f9a22e724656502a3e7cd627/direct/__pycache__/admin.cpython-36.pyc -------------------------------------------------------------------------------- /direct/__pycache__/models.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byronlara5/django_instagram_clone_youtube/a5204bf07e22ce17f9a22e724656502a3e7cd627/direct/__pycache__/models.cpython-36.pyc -------------------------------------------------------------------------------- /direct/__pycache__/urls.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byronlara5/django_instagram_clone_youtube/a5204bf07e22ce17f9a22e724656502a3e7cd627/direct/__pycache__/urls.cpython-36.pyc -------------------------------------------------------------------------------- /direct/__pycache__/views.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byronlara5/django_instagram_clone_youtube/a5204bf07e22ce17f9a22e724656502a3e7cd627/direct/__pycache__/views.cpython-36.pyc -------------------------------------------------------------------------------- /direct/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from direct.models import Message 3 | 4 | # Register your models here. 5 | admin.site.register(Message) -------------------------------------------------------------------------------- /direct/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class DirectConfig(AppConfig): 5 | name = 'direct' 6 | -------------------------------------------------------------------------------- /direct/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.0.7 on 2020-07-25 05:14 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='Message', 19 | fields=[ 20 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 21 | ('body', models.TextField(max_length=1000)), 22 | ('date', models.DateTimeField(auto_now_add=True)), 23 | ('is_read', models.BooleanField(default=False)), 24 | ('recipient', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='to_user', to=settings.AUTH_USER_MODEL)), 25 | ('sender', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='from_user', to=settings.AUTH_USER_MODEL)), 26 | ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='user', to=settings.AUTH_USER_MODEL)), 27 | ], 28 | ), 29 | ] 30 | -------------------------------------------------------------------------------- /direct/migrations/0002_auto_20200728_1611.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.0.7 on 2020-07-28 16:11 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('direct', '0001_initial'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='message', 15 | name='body', 16 | field=models.TextField(blank=True, max_length=1000), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /direct/migrations/0003_auto_20200728_2032.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 3.0.7 on 2020-07-28 20:32 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('direct', '0002_auto_20200728_1611'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='message', 15 | name='body', 16 | field=models.TextField(blank=True, max_length=1000, null=True), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /direct/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byronlara5/django_instagram_clone_youtube/a5204bf07e22ce17f9a22e724656502a3e7cd627/direct/migrations/__init__.py -------------------------------------------------------------------------------- /direct/migrations/__pycache__/0001_initial.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byronlara5/django_instagram_clone_youtube/a5204bf07e22ce17f9a22e724656502a3e7cd627/direct/migrations/__pycache__/0001_initial.cpython-36.pyc -------------------------------------------------------------------------------- /direct/migrations/__pycache__/0002_auto_20200728_1611.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byronlara5/django_instagram_clone_youtube/a5204bf07e22ce17f9a22e724656502a3e7cd627/direct/migrations/__pycache__/0002_auto_20200728_1611.cpython-36.pyc -------------------------------------------------------------------------------- /direct/migrations/__pycache__/0003_auto_20200728_2032.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byronlara5/django_instagram_clone_youtube/a5204bf07e22ce17f9a22e724656502a3e7cd627/direct/migrations/__pycache__/0003_auto_20200728_2032.cpython-36.pyc -------------------------------------------------------------------------------- /direct/migrations/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byronlara5/django_instagram_clone_youtube/a5204bf07e22ce17f9a22e724656502a3e7cd627/direct/migrations/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /direct/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | from django.contrib.auth.models import User 3 | from django.db.models import Max 4 | 5 | # Create your models here. 6 | class Message(models.Model): 7 | user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='user') 8 | sender = models.ForeignKey(User, on_delete=models.CASCADE, related_name='from_user') 9 | recipient = models.ForeignKey(User, on_delete=models.CASCADE, related_name='to_user') 10 | body = models.TextField(max_length=1000, blank=True, null=True) 11 | date = models.DateTimeField(auto_now_add=True) 12 | is_read = models.BooleanField(default=False) 13 | 14 | def send_message(from_user, to_user, body): 15 | sender_message = Message( 16 | user=from_user, 17 | sender=from_user, 18 | recipient=to_user, 19 | body=body, 20 | is_read=True) 21 | sender_message.save() 22 | 23 | recipient_message = Message( 24 | user=to_user, 25 | sender=from_user, 26 | body=body, 27 | recipient=from_user,) 28 | recipient_message.save() 29 | return sender_message 30 | 31 | def get_messages(user): 32 | messages = Message.objects.filter(user=user).values('recipient').annotate(last=Max('date')).order_by('-last') 33 | users = [] 34 | for message in messages: 35 | users.append({ 36 | 'user': User.objects.get(pk=message['recipient']), 37 | 'last': message['last'], 38 | 'unread': Message.objects.filter(user=user, recipient__pk=message['recipient'], is_read=False).count() 39 | }) 40 | return users -------------------------------------------------------------------------------- /direct/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /direct/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | from direct.views import Inbox, UserSearch, Directs, NewConversation, SendDirect 3 | urlpatterns = [ 4 | path('', Inbox, name='inbox'), 5 | path('directs/', Directs, name='directs'), 6 | path('new/', UserSearch, name='usersearch'), 7 | path('new/', NewConversation, name='newconversation'), 8 | path('send/', SendDirect, name='send_direct'), 9 | 10 | ] -------------------------------------------------------------------------------- /direct/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render, redirect 2 | from django.template import loader, RequestContext 3 | from django.http import HttpResponse, HttpResponseRedirect, HttpResponseBadRequest 4 | 5 | from django.contrib.auth.decorators import login_required 6 | 7 | from django.contrib.auth.models import User 8 | from direct.models import Message 9 | 10 | 11 | from django.db.models import Q 12 | from django.core.paginator import Paginator 13 | # Create your views here. 14 | 15 | @login_required 16 | def Inbox(request): 17 | messages = Message.get_messages(user=request.user) 18 | active_direct = None 19 | directs = None 20 | 21 | if messages: 22 | message = messages[0] 23 | active_direct = message['user'].username 24 | directs = Message.objects.filter(user=request.user, recipient=message['user']) 25 | directs.update(is_read=True) 26 | for message in messages: 27 | if message['user'].username == active_direct: 28 | message['unread'] = 0 29 | 30 | context = { 31 | 'directs': directs, 32 | 'messages': messages, 33 | 'active_direct': active_direct, 34 | } 35 | 36 | template = loader.get_template('direct/direct.html') 37 | 38 | return HttpResponse(template.render(context, request)) 39 | 40 | @login_required 41 | def UserSearch(request): 42 | query = request.GET.get("q") 43 | context = {} 44 | 45 | if query: 46 | users = User.objects.filter(Q(username__icontains=query)) 47 | 48 | #Pagination 49 | paginator = Paginator(users, 6) 50 | page_number = request.GET.get('page') 51 | users_paginator = paginator.get_page(page_number) 52 | 53 | context = { 54 | 'users': users_paginator, 55 | } 56 | 57 | template = loader.get_template('direct/search_user.html') 58 | 59 | return HttpResponse(template.render(context, request)) 60 | 61 | @login_required 62 | def Directs(request, username): 63 | user = request.user 64 | messages = Message.get_messages(user=user) 65 | active_direct = username 66 | directs = Message.objects.filter(user=user, recipient__username=username) 67 | directs.update(is_read=True) 68 | for message in messages: 69 | if message['user'].username == username: 70 | message['unread'] = 0 71 | 72 | context = { 73 | 'directs': directs, 74 | 'messages': messages, 75 | 'active_direct':active_direct, 76 | } 77 | 78 | template = loader.get_template('direct/direct.html') 79 | 80 | return HttpResponse(template.render(context, request)) 81 | 82 | 83 | @login_required 84 | def NewConversation(request, username): 85 | from_user = request.user 86 | body = '' 87 | try: 88 | to_user = User.objects.get(username=username) 89 | except Exception as e: 90 | return redirect('usersearch') 91 | if from_user != to_user: 92 | Message.send_message(from_user, to_user, body) 93 | return redirect('inbox') 94 | 95 | @login_required 96 | def SendDirect(request): 97 | from_user = request.user 98 | to_user_username = request.POST.get('to_user') 99 | body = request.POST.get('body') 100 | 101 | if request.method == 'POST': 102 | to_user = User.objects.get(username=to_user_username) 103 | Message.send_message(from_user, to_user, body) 104 | return redirect('inbox') 105 | else: 106 | HttpResponseBadRequest() 107 | 108 | def checkDirects(request): 109 | directs_count = 0 110 | if request.user.is_authenticated: 111 | directs_count = Message.objects.filter(user=request.user, is_read=False).count() 112 | 113 | return {'directs_count':directs_count} 114 | 115 | 116 | 117 | -------------------------------------------------------------------------------- /instagram_clone/__init__.py: -------------------------------------------------------------------------------- 1 | # This will make sure the app is always imported when 2 | # Django starts so that shared_task will use this app. 3 | from .celery import app as celery_app 4 | 5 | __all__ = ('celery_app',) -------------------------------------------------------------------------------- /instagram_clone/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byronlara5/django_instagram_clone_youtube/a5204bf07e22ce17f9a22e724656502a3e7cd627/instagram_clone/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /instagram_clone/__pycache__/__init__.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byronlara5/django_instagram_clone_youtube/a5204bf07e22ce17f9a22e724656502a3e7cd627/instagram_clone/__pycache__/__init__.cpython-38.pyc -------------------------------------------------------------------------------- /instagram_clone/__pycache__/celery.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byronlara5/django_instagram_clone_youtube/a5204bf07e22ce17f9a22e724656502a3e7cd627/instagram_clone/__pycache__/celery.cpython-36.pyc -------------------------------------------------------------------------------- /instagram_clone/__pycache__/settings.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byronlara5/django_instagram_clone_youtube/a5204bf07e22ce17f9a22e724656502a3e7cd627/instagram_clone/__pycache__/settings.cpython-36.pyc -------------------------------------------------------------------------------- /instagram_clone/__pycache__/settings.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byronlara5/django_instagram_clone_youtube/a5204bf07e22ce17f9a22e724656502a3e7cd627/instagram_clone/__pycache__/settings.cpython-38.pyc -------------------------------------------------------------------------------- /instagram_clone/__pycache__/urls.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byronlara5/django_instagram_clone_youtube/a5204bf07e22ce17f9a22e724656502a3e7cd627/instagram_clone/__pycache__/urls.cpython-36.pyc -------------------------------------------------------------------------------- /instagram_clone/__pycache__/urls.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byronlara5/django_instagram_clone_youtube/a5204bf07e22ce17f9a22e724656502a3e7cd627/instagram_clone/__pycache__/urls.cpython-38.pyc -------------------------------------------------------------------------------- /instagram_clone/__pycache__/wsgi.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byronlara5/django_instagram_clone_youtube/a5204bf07e22ce17f9a22e724656502a3e7cd627/instagram_clone/__pycache__/wsgi.cpython-36.pyc -------------------------------------------------------------------------------- /instagram_clone/__pycache__/wsgi.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byronlara5/django_instagram_clone_youtube/a5204bf07e22ce17f9a22e724656502a3e7cd627/instagram_clone/__pycache__/wsgi.cpython-38.pyc -------------------------------------------------------------------------------- /instagram_clone/asgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | ASGI config for instagram_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.0/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', 'instagram_clone.settings') 15 | 16 | application = get_asgi_application() 17 | -------------------------------------------------------------------------------- /instagram_clone/celery.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from celery import Celery 4 | 5 | # set the default Django settings module for the 'celery' program. 6 | # IMPORTANT check the name of your project and replace it here 'yourproject.settings' 7 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'instagram_clone.settings') 8 | 9 | # IMPORTANT check the name of your project and replace it here 'yourproject' 10 | app = Celery('instagram_clone') 11 | 12 | # Using a string here means the worker doesn't have to serialize 13 | # the configuration object to child processes. 14 | # - namespace='CELERY' means all celery-related configuration keys 15 | # should have a `CELERY_` prefix. 16 | app.config_from_object('django.conf:settings', namespace='CELERY') 17 | 18 | # Load task modules from all registered Django app configs. 19 | app.autodiscover_tasks() 20 | 21 | 22 | @app.task(bind=True) 23 | def debug_task(self): 24 | print(f'Request: {self.request!r}') -------------------------------------------------------------------------------- /instagram_clone/settings.py: -------------------------------------------------------------------------------- 1 | """ 2 | Django settings for instagram_clone project. 3 | 4 | Generated by 'django-admin startproject' using Django 3.0.7. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.0/topics/settings/ 8 | 9 | For the full list of settings and their values, see 10 | https://docs.djangoproject.com/en/3.0/ref/settings/ 11 | """ 12 | 13 | import os 14 | 15 | # Build paths inside the project like this: os.path.join(BASE_DIR, ...) 16 | BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 17 | 18 | 19 | # Quick-start development settings - unsuitable for production 20 | # See https://docs.djangoproject.com/en/3.0/howto/deployment/checklist/ 21 | 22 | # SECURITY WARNING: keep the secret key used in production secret! 23 | SECRET_KEY = 'wkpwid&=r9wp2nl9jyr_%66zjgq4fku9*%g%^%-4iijga+t2lg' 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 | 'django.contrib.humanize', 41 | 'authy', 42 | 'post', 43 | 'comment', 44 | 'direct', 45 | 'notifications', 46 | 'stories', 47 | 'django_celery_beat', 48 | 49 | ] 50 | 51 | MIDDLEWARE = [ 52 | 'django.middleware.security.SecurityMiddleware', 53 | 'django.contrib.sessions.middleware.SessionMiddleware', 54 | 'django.middleware.common.CommonMiddleware', 55 | 'django.middleware.csrf.CsrfViewMiddleware', 56 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 57 | 'django.contrib.messages.middleware.MessageMiddleware', 58 | 'django.middleware.clickjacking.XFrameOptionsMiddleware', 59 | ] 60 | 61 | ROOT_URLCONF = 'instagram_clone.urls' 62 | 63 | TEMPLATES = [ 64 | { 65 | 'BACKEND': 'django.template.backends.django.DjangoTemplates', 66 | 'DIRS': [os.path.join(BASE_DIR, 'instagram_clone/templates')], 67 | 'APP_DIRS': True, 68 | 'OPTIONS': { 69 | 'context_processors': [ 70 | 'django.template.context_processors.debug', 71 | 'django.template.context_processors.request', 72 | 'django.contrib.auth.context_processors.auth', 73 | 'django.contrib.messages.context_processors.messages', 74 | 'notifications.views.CountNotifications', 75 | 'direct.views.checkDirects', 76 | ], 77 | }, 78 | }, 79 | ] 80 | 81 | WSGI_APPLICATION = 'instagram_clone.wsgi.application' 82 | 83 | 84 | # Database 85 | # https://docs.djangoproject.com/en/3.0/ref/settings/#databases 86 | 87 | DATABASES = { 88 | 'default': { 89 | 'ENGINE': 'django.db.backends.sqlite3', 90 | 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), 91 | } 92 | } 93 | 94 | 95 | # Password validation 96 | # https://docs.djangoproject.com/en/3.0/ref/settings/#auth-password-validators 97 | 98 | AUTH_PASSWORD_VALIDATORS = [ 99 | { 100 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', 101 | }, 102 | { 103 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 104 | }, 105 | { 106 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', 107 | }, 108 | { 109 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', 110 | }, 111 | ] 112 | 113 | 114 | # Internationalization 115 | # https://docs.djangoproject.com/en/3.0/topics/i18n/ 116 | 117 | LANGUAGE_CODE = 'en-us' 118 | 119 | TIME_ZONE = 'UTC' 120 | 121 | USE_I18N = True 122 | 123 | USE_L10N = True 124 | 125 | USE_TZ = True 126 | 127 | 128 | # Static files (CSS, JavaScript, Images) 129 | # https://docs.djangoproject.com/en/3.0/howto/static-files/ 130 | 131 | STATIC_URL = '/static/' 132 | STATICFILES_DIRS = [ 133 | os.path.join(BASE_DIR, 'instagram_clone/static') 134 | ] 135 | 136 | MEDIA_URL = '/media/' 137 | MEDIA_ROOT = os.path.join(BASE_DIR, 'media') 138 | 139 | EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' 140 | 141 | LOGIN_REDIRECT_URL = 'index' 142 | LOGOUT_REDIRECT_URL = 'login' 143 | LOGIN_URL = '/user/login/' 144 | 145 | 146 | #Celery Broker 147 | CELERY_BROKER_URL = 'amqp://localhost:5672' -------------------------------------------------------------------------------- /instagram_clone/static/css/style.css: -------------------------------------------------------------------------------- 1 | .badge { 2 | position: absolute; 3 | top: 1px; 4 | right: -4px; 5 | padding: 1px 7px; 6 | border-radius: 50%; 7 | background: red; 8 | color: white; 9 | font-weight: bold; 10 | } 11 | 12 | 13 | * {box-sizing:border-box} 14 | 15 | /* Slideshow container */ 16 | .slideshow-container { 17 | max-width: 1000px; 18 | position: relative; 19 | margin: auto; 20 | } 21 | 22 | /* Hide the images by default */ 23 | .mySlides { 24 | display: none; 25 | } 26 | 27 | /* Next & previous buttons */ 28 | .prev, .next { 29 | cursor: pointer; 30 | position: absolute; 31 | top: 50%; 32 | width: auto; 33 | margin-top: -22px; 34 | padding: 16px; 35 | color: white; 36 | font-weight: bold; 37 | font-size: 18px; 38 | transition: 0.6s ease; 39 | border-radius: 0 3px 3px 0; 40 | user-select: none; 41 | } 42 | 43 | /* Position the "next button" to the right */ 44 | .next { 45 | right: 0; 46 | border-radius: 3px 0 0 3px; 47 | } 48 | 49 | /* On hover, add a black background color with a little bit see-through */ 50 | .prev:hover, .next:hover { 51 | background-color: rgba(0,0,0,0.8); 52 | } 53 | 54 | /* Caption text */ 55 | .text { 56 | color: #f2f2f2; 57 | font-size: 15px; 58 | padding: 8px 12px; 59 | position: absolute; 60 | bottom: 8px; 61 | width: 100%; 62 | text-align: center; 63 | } 64 | 65 | /* Number text (1/3 etc) */ 66 | .numbertext { 67 | color: #f2f2f2; 68 | font-size: 12px; 69 | padding: 8px 12px; 70 | position: absolute; 71 | top: 0; 72 | } 73 | 74 | /* The dots/bullets/indicators */ 75 | .dot { 76 | cursor: pointer; 77 | height: 15px; 78 | width: 15px; 79 | margin: 0 2px; 80 | background-color: #bbb; 81 | border-radius: 50%; 82 | display: inline-block; 83 | transition: background-color 0.6s ease; 84 | } 85 | 86 | .active, .dot:hover { 87 | background-color: #717171; 88 | } 89 | 90 | /* Fading animation */ 91 | .fade { 92 | -webkit-animation-name: fade; 93 | -webkit-animation-duration: 1.5s; 94 | animation-name: fade; 95 | animation-duration: 1.5s; 96 | } 97 | 98 | @-webkit-keyframes fade { 99 | from {opacity: .4} 100 | to {opacity: 1} 101 | } 102 | 103 | @keyframes fade { 104 | from {opacity: .4} 105 | to {opacity: 1} 106 | } -------------------------------------------------------------------------------- /instagram_clone/static/img/1-bezos.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byronlara5/django_instagram_clone_youtube/a5204bf07e22ce17f9a22e724656502a3e7cd627/instagram_clone/static/img/1-bezos.jpg -------------------------------------------------------------------------------- /instagram_clone/static/img/1-elon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byronlara5/django_instagram_clone_youtube/a5204bf07e22ce17f9a22e724656502a3e7cd627/instagram_clone/static/img/1-elon.jpg -------------------------------------------------------------------------------- /instagram_clone/static/img/1-zuckerberg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byronlara5/django_instagram_clone_youtube/a5204bf07e22ce17f9a22e724656502a3e7cd627/instagram_clone/static/img/1-zuckerberg.jpg -------------------------------------------------------------------------------- /instagram_clone/static/img/background1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byronlara5/django_instagram_clone_youtube/a5204bf07e22ce17f9a22e724656502a3e7cd627/instagram_clone/static/img/background1.jpg -------------------------------------------------------------------------------- /instagram_clone/static/img/background2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byronlara5/django_instagram_clone_youtube/a5204bf07e22ce17f9a22e724656502a3e7cd627/instagram_clone/static/img/background2.jpg -------------------------------------------------------------------------------- /instagram_clone/static/img/background3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byronlara5/django_instagram_clone_youtube/a5204bf07e22ce17f9a22e724656502a3e7cd627/instagram_clone/static/img/background3.jpg -------------------------------------------------------------------------------- /instagram_clone/static/img/default-thumbnail.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byronlara5/django_instagram_clone_youtube/a5204bf07e22ce17f9a22e724656502a3e7cd627/instagram_clone/static/img/default-thumbnail.jpg -------------------------------------------------------------------------------- /instagram_clone/static/img/instagram_black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byronlara5/django_instagram_clone_youtube/a5204bf07e22ce17f9a22e724656502a3e7cd627/instagram_clone/static/img/instagram_black.png -------------------------------------------------------------------------------- /instagram_clone/static/img/instagram_black_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byronlara5/django_instagram_clone_youtube/a5204bf07e22ce17f9a22e724656502a3e7cd627/instagram_clone/static/img/instagram_black_logo.png -------------------------------------------------------------------------------- /instagram_clone/static/img/person.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byronlara5/django_instagram_clone_youtube/a5204bf07e22ce17f9a22e724656502a3e7cd627/instagram_clone/static/img/person.jpg -------------------------------------------------------------------------------- /instagram_clone/static/img/profile_banner.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/byronlara5/django_instagram_clone_youtube/a5204bf07e22ce17f9a22e724656502a3e7cd627/instagram_clone/static/img/profile_banner.jpg -------------------------------------------------------------------------------- /instagram_clone/static/js/init.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function(){ 2 | 3 | const modal = $('.modal'); 4 | slideIndex = 1; 5 | 6 | $('.showModal').click(function(event){ 7 | 8 | var storyid = event.currentTarget.name; 9 | 10 | $.ajax({ 11 | type: 'GET', 12 | url: 'http://127.0.0.1:8000/stories/showmedia/'+ storyid, 13 | dataType: 'json', 14 | 15 | success: function(data){ 16 | $.each(data,function(i,v){ 17 | 18 | if (v.content.slice(v.content.length - 3) === 'mp4'){ 19 | var div_slides_html = '
' 20 | } else { 21 | var div_slides_html = '
'+ v.caption +'
' 22 | } 23 | 24 | $('#jsondata').append(div_slides_html); 25 | 26 | 27 | }); 28 | 29 | }, 30 | 31 | complete: function(){ 32 | showSlides(slideIndex); 33 | } 34 | 35 | }); 36 | 37 | modal.addClass('is-active'); 38 | }); 39 | 40 | $('#closeModal').click(function(){ 41 | const slides = document.getElementById('jsondata'); 42 | slides.innerHTML = ''; 43 | modal.removeClass('is-active'); 44 | }); 45 | 46 | 47 | }); -------------------------------------------------------------------------------- /instagram_clone/static/js/slider.js: -------------------------------------------------------------------------------- 1 | 2 | // Next/previous controls 3 | function plusSlides(n) { 4 | showSlides(slideIndex += n); 5 | } 6 | 7 | // Thumbnail image controls 8 | function currentSlide(n) { 9 | showSlides(slideIndex = n); 10 | } 11 | 12 | function showSlides(n) { 13 | 14 | var i; 15 | var slides = document.getElementsByClassName("mySlides"); 16 | 17 | if (n > slides.length) { 18 | slideIndex = 1 19 | } 20 | 21 | if (n < 1) { 22 | slideIndex = slides.length 23 | } 24 | 25 | for (i = 0; i < slides.length; i++) { 26 | slides[i].style.display = "none"; 27 | } 28 | 29 | slides[slideIndex-1].style.display = "block"; 30 | } -------------------------------------------------------------------------------- /instagram_clone/templates/base.html: -------------------------------------------------------------------------------- 1 | {% load static %} 2 | 3 | 4 | 5 | 6 | 7 | 8 | Hello Bulma! 9 | 10 | 11 | 13 | 14 | 15 | 16 | 97 | 98 | {% block banner %} 99 | {% endblock %} 100 | 101 |
102 |
103 | 104 | {% block content %} 105 | {% endblock %} 106 | 107 | 108 | {% block pagination %} 109 | {% endblock %} 110 | 111 |
112 |
113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | -------------------------------------------------------------------------------- /instagram_clone/templates/change_password.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | {% load static %} 3 | 4 | 5 | {% block content %} 6 | 7 |
8 |
9 | 10 |
11 | {% csrf_token %} 12 | {{ form.id }} 13 |

Change password

14 |
15 | {{ form.old_password }} 16 | 17 |
18 |
19 |
20 |
21 | {{ form.new_password }} 22 | 23 |
24 |
25 |
26 |
27 | {{ form.confirm_password }} 28 | 29 |
30 |
31 |
32 |
33 | {{ form.errors }} 34 |
35 |
36 | 37 |
38 |
39 | 40 | {% endblock %} -------------------------------------------------------------------------------- /instagram_clone/templates/change_password_done.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | {% block content %} 4 | 5 |
6 |
7 |
8 |
9 |
10 |
11 | check_circle 12 |
13 |
14 |

Your password has been succesfully changed

15 |
16 | 17 | 18 |
19 | 20 |
21 |
22 | {% endblock %} -------------------------------------------------------------------------------- /instagram_clone/templates/direct/direct.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | {% load static %} 4 | 5 | {% block content %} 6 | 7 |
8 | 9 | 10 | 59 | 60 |
61 | 62 |
63 | 64 | {% for direct in directs %} 65 |
66 |
67 |
68 |
69 |
70 |
71 |

72 | {{ direct.sender.profile.first_name }} {{ direct.sender.profile.last_name }} @{{ direct.sender.username }} on: {{ direct.date|date:'N d G:i'}} 73 |

74 | {{ direct.body }} 75 |
76 |
77 |
78 |
79 | {% endfor %} 80 | 81 | 82 |
83 | 84 | 85 |
86 | {% csrf_token %} 87 |
88 |
89 |

90 | 91 |

92 |
93 |
94 | 95 |
96 |

97 | 98 |

99 |
100 | 107 |
108 |
109 |
110 | 111 |
112 |
113 | 114 | {% endblock %} -------------------------------------------------------------------------------- /instagram_clone/templates/direct/search_user.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | {% load static %} 4 | 5 | {% block content %} 6 | 7 |
8 |
9 | 10 | 11 |
12 |
13 |
14 | 15 |
16 |
17 | 18 |
19 |
20 |
21 | 22 | 23 |
24 |
25 | 26 |
27 | 28 | {% for user in users %} 29 |
30 |
31 |
32 |
33 | {% if user.profile.picture %} 34 | Placeholder image 35 | {% else %} 36 | Placeholder image 37 | {% endif %} 38 |
39 |
40 |
41 |
42 |

43 | {{ user.profile.first_name }} {{ user.profile.last_name }}@{{ user.username }} 44 |

45 | Send a message! 46 |
47 |
48 |
49 |
50 | {% endfor %} 51 | 52 | 53 |
54 | 55 | {% endblock %} -------------------------------------------------------------------------------- /instagram_clone/templates/edit_profile.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | {% load static %} 3 | 4 | 5 | {% block content %} 6 | 7 |
8 |
9 | 10 |
11 |
12 | 13 |
14 | {% csrf_token %} 15 |

Edit Profile

16 | 17 |
18 | 19 |
20 | {{ form.picture }} 21 |
22 |
23 | 24 |
25 | 26 |
27 | {{ form.first_name }} 28 |
29 |
30 | 31 |
32 | 33 |
34 | {{ form.last_name }} 35 |
36 |
37 | 38 |
39 | 40 |
41 | {{ form.location }} 42 |
43 |
44 | 45 |
46 | 47 |
48 | {{ form.url }} 49 |
50 |
51 | 52 |
53 | 54 |
55 | {{ form.profile_info }} 56 |
57 |
58 | 59 |
60 |
61 | {{ form.errors }} 62 |
63 |
64 | 65 | 66 |
67 |

68 | 71 |

72 |
73 | 74 |
75 |
76 |
77 | 78 |
79 |
80 | 81 | {% endblock %} -------------------------------------------------------------------------------- /instagram_clone/templates/index.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | {% load static %} 4 | {% load humanize %} 5 | 6 | {% block content %} 7 | 8 | 9 |
10 | 11 | {% for story in stories %} 12 | 22 | {% endfor %} 23 | 24 |
25 | 26 | 27 | 60 | 61 | 62 | 63 | 64 | 65 |
66 | 67 |
68 |
69 | 70 | {% for post_item in post_items %} 71 |
72 |
73 | 74 | {% if post_item.content.first.file.name|slice:"-3:" == 'jpg' or post_item.content.first.file.name|slice:"-3:" == 'png' %} 75 |
76 | 77 | Placeholder image 78 | 79 |
80 | {% else %} 81 | 82 | 85 | 86 | {% endif %} 87 | 88 |
89 |
90 |
91 |
92 |
93 | {% if post_item.user.profile.picture %} 94 | Placeholder image 95 | {% else %} 96 | Placeholder image 97 | {% endif %} 98 |
99 |
100 |
101 | {% if post_item.user.profile.first_name %} 102 |

{{ post_item.user.profile.first_name }} {{ post_item.user.profile.last_name }}

103 | {% else %} 104 |

Unknown

105 | {% endif %} 106 | 107 |

@{{ post_item.user.username }}

108 | 109 | {{ post_item.caption }} 110 |

{% for tag in post_item.tags.all %}#{{ tag }}{% endfor %}

111 |
112 | {{ post_item.posted | naturaltime }} 113 |
114 | 115 | 116 |
117 | favorite 118 |

{{ post_item.likes }} Likes

119 |
120 | 121 |
122 | 123 | 124 | 125 |
126 |
127 | 128 |
129 | 130 | {% endfor %} 131 | 132 |
133 |
134 | 135 | {% endblock %} -------------------------------------------------------------------------------- /instagram_clone/templates/login.html: -------------------------------------------------------------------------------- 1 | {% load static %} 2 | 3 | 4 | 5 | 6 | 7 | 8 | Hello Bulma! 9 | 10 | 11 | 13 | 14 | 15 | 16 | 17 |
18 |
19 | 20 |
21 |
22 | 23 |
24 |
25 | 26 |
27 | {% csrf_token %} 28 |

Login

29 | 30 |
31 |

32 | 33 | {{ form.username }} 34 | 35 | 36 | 37 |

38 |
39 | 40 |
41 |

42 | 43 | {{ form.password }} 44 | 45 | 46 | 47 |

48 |
49 | 50 | {% if form.errors %} 51 |
52 |
53 | Your username or password did not match. 54 |
55 |
56 | {% endif %} 57 | 58 |
59 |

60 | 63 |

64 |
65 | 66 | 67 | 68 | 69 | 70 | Create an account 71 | 72 | 73 |
74 | 75 | 76 | 77 | 78 |
79 |
80 | 81 | 82 | 83 |
84 |
85 | 86 | 87 |
88 |
89 | 90 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /instagram_clone/templates/newpost.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | {% load static %} 4 | 5 | {% block content %} 6 | 7 |
8 |
9 | 10 |
11 |
12 | 13 |
14 | {% csrf_token %} 15 |

New Post

16 | 17 |
18 |

19 | 20 | {{ form.content }} 21 | 22 | 23 | 24 |

25 |
26 | 27 |
28 |

29 | 30 | {{ form.caption }} 31 | 32 | 33 | 34 |

35 |
36 | 37 |
38 |

39 | 40 | {{ form.tags }} 41 | 42 | 43 | 44 |

45 |
46 | 47 |
48 |

49 | 52 |

53 |
54 | 55 | 56 |
57 |
58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | {% endblock %} -------------------------------------------------------------------------------- /instagram_clone/templates/newstory.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | {% load static %} 4 | 5 | {% block content %} 6 | 7 |
8 |
9 | 10 |
11 |
12 | 13 | 14 | {% csrf_token %} 15 |

New Story

16 | 17 |
18 |

19 | 20 | {{ form.content }} 21 | 22 | 23 | 24 |

25 |
26 | 27 |
28 |

29 | 30 | {{ form.caption }} 31 | 32 | 33 | 34 |

35 |
36 | 37 | 38 |
39 |

40 | 43 |

44 |
45 | 46 | 47 |
48 |
49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | {% endblock %} -------------------------------------------------------------------------------- /instagram_clone/templates/notifications.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | {% load static %} 4 | {% load humanize %} 5 | 6 | {% block content %} 7 | 8 |
9 |
10 | 11 | 12 | {% for notification in notifications %} 13 | 14 | 15 | {% if notification.notification_type == 2 %} 16 |
17 | 18 | 19 |
20 |
21 |

22 | {% if notification.sender.profile.picture %} 23 | Placeholder image 24 | {% else %} 25 | Placeholder image 26 | {% endif %} 27 |

28 |
29 |
30 |
31 | {{ notification.sender.profile.first_name }} {{ notification.sender.profile.last_name }} @{{ notification.sender.username }} 32 |
33 | Commented: 34 |

{{ notification.text_preview }}

35 | {{ notification.date|naturaltime }} 36 |
37 |
38 | 39 |
40 |
41 | 42 |
43 |
44 |
45 | 46 |
47 | {% endif %} 48 | 49 | 50 | {% if notification.notification_type == 3 %} 51 |
52 | 53 | 54 |
55 |
56 |

57 | {% if notification.sender.profile.picture %} 58 | Placeholder image 59 | {% else %} 60 | Placeholder image 61 | {% endif %} 62 |

63 |
64 |
65 |
66 | {{ notification.sender.profile.first_name }} {{ notification.sender.profile.last_name }} @{{ notification.sender.username }} 67 |
68 |

person_add Followed you!

69 | {{ notification.date|naturaltime }} 70 |
71 |
72 | 73 |
74 | 75 |
76 | {% endif %} 77 | 78 | 79 | 80 | {% if notification.notification_type == 1 %} 81 |
82 | 83 | 84 |
85 |
86 |

87 | {% if notification.sender.profile.picture %} 88 | Placeholder image 89 | {% else %} 90 | Placeholder image 91 | {% endif %} 92 |

93 |
94 |
95 |
96 | {{ notification.sender.profile.first_name }} {{ notification.sender.profile.last_name }} @{{ notification.sender.username }} 97 |
98 |

thumb_up Liked your post

99 | {{ notification.date|naturaltime }} 100 |
101 |
102 | 103 |
104 |
105 | 106 |
107 |
108 |
109 | 110 |
111 | {% endif %} 112 | 113 | 114 | {% endfor %} 115 | 116 | 117 | 118 | 119 |
120 |
121 | 122 | 123 | {% endblock %} -------------------------------------------------------------------------------- /instagram_clone/templates/post_detail.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | {% load static %} 4 | {% load humanize %} 5 | 6 | {% block content %} 7 | 8 |
9 |
10 | 11 | 12 |
13 |
14 | 15 |
16 | 17 | {% for cont in post.content.all %} 18 | 19 |
20 | {% if cont.file.name|slice:"-3:" == 'jpg' or cont.file.name|slice:"-3:" == 'png' %} 21 |
22 | 23 | Placeholder image 24 | 25 |
26 | {% else %} 27 | 28 | 31 | 32 | {% endif %} 33 |
34 | {% endfor %} 35 | 36 | 37 | 38 | 39 |
40 | 41 | 42 | 43 |
44 |
45 |
46 | 47 |
48 |
49 | {% if post.user.profile.picture %} 50 | Placeholder image 51 | {% else %} 52 | Placeholder image 53 | {% endif %} 54 |
55 |
56 | 57 |
58 | {% if post.user.profile.first_name %} 59 |

{{ post.user.profile.first_name }} {{ post.user.profile.last_name }}

60 | {% else %} 61 |

Unknown

62 | {% endif %} 63 |

@{{ post.user.username }}

64 | 65 | {{ post.caption }} 66 |

{% for tag in post.tags.all %}#{{ tag }}{% endfor %}

67 |
68 | {{ post.posted }} 69 | 70 | 71 |
72 | 73 | 74 | {% if favorited is True %} 75 |
76 | save_alt 77 |

Remove Post

78 |
79 | {% else %} 80 | 81 |
82 | save_alt 83 |

Save Post

84 |
85 | 86 | {% endif %} 87 | 88 |
89 | favorite 90 |

{{ post.likes }} Likes

91 |
92 | 93 | 94 |
95 | 96 |
97 |
98 | 99 |
100 | 101 | {% for comment in comments %} 102 |
103 |
104 |

105 | {% if comment.user.profile.picture %} 106 | Placeholder image 107 | {% else %} 108 | Placeholder image 109 | {% endif %} 110 |

111 |
112 | 113 |
114 |
115 |

116 | {% if comment.user.profile.first_name %} 117 | {{ comment.user.profile.first_name }} {{ comment.user.profile.last_name }} @{{ comment.user.username }} 118 | {% else %} 119 | Unknown 120 | {% endif %} 121 |
122 | {{ comment.body }} 123 |
124 | {{ comment.date|naturaltime }} 125 |

126 |
127 | 128 |
129 | {% endfor %} 130 | 131 |
132 |
133 |

134 | {% if request.user.profile.picture %} 135 | Placeholder image 136 | {% else %} 137 | Placeholder image 138 | {% endif %} 139 |

140 |
141 |
142 | 143 | {% csrf_token %} 144 |
145 |

146 | {{ form.body }} 147 |

148 |
149 |
150 |

151 | 152 |

153 |
154 | 155 |
156 |
157 |
158 | 159 | 160 | 161 |
162 |
163 | 164 | {% endblock %} -------------------------------------------------------------------------------- /instagram_clone/templates/profile.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | {% load static %} 4 | 5 | {% block content %} 6 | 7 |
8 | 9 |
10 |
11 | {% if profile.picture %} 12 | 13 | {% else %} 14 | 15 | {% endif %} 16 |
17 |
18 | 19 |
20 | 21 |
22 |

{% if profile.first_name %}{{ profile.first_name }} {{ profile.last_name }} {% endif %}

23 |

@{{ profile.user }}

24 | 25 | {% if user.is_authenticated and user != profile.user %} 26 |
27 | {% if follow_status == True %} 28 | Unfollow 29 | {% else %} 30 | Follow 31 | {% endif %} 32 |
33 | {% endif %} 34 | 35 |
36 | 37 | 38 | 58 | 59 |

{% if profile.profile_info %}{{ profile.profile_info }}{% endif %}

60 | 61 | {% if user.is_authenticated and user == profile.user %} 62 | Edit profile 63 | {% endif %} 64 | 65 |
66 | 67 |
68 | 69 | 70 |
71 |
72 | 73 | 74 | 75 |
76 | 77 | 78 | 79 | 80 |
81 |
82 | 83 |
84 | 93 |
94 | 95 | 96 |
97 | 98 | {% for post in posts %} 99 |
100 |
101 | 102 | {% if post.content.first.file.name|slice:"-3:" == 'jpg' or post_item.content.first.file.name|slice:"-3:" == 'png' %} 103 |
104 | 105 | Placeholder image 106 | 107 |
108 | {% else %} 109 | 110 | 113 | 114 | {% endif %} 115 | 116 | 117 | 118 | 119 |
120 |
121 | {% empty %} 122 |
123 |

You do not have any post!

124 | {% endfor %} 125 | 126 | 127 | 128 |
129 | 130 |
131 |
132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | {% endblock %} -------------------------------------------------------------------------------- /instagram_clone/templates/profile_favorite.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | {% load static %} 3 | 4 | 5 | {% block content %} 6 | 7 |
8 |
9 |
10 | {% if profile.picture %} 11 | 12 | {% else %} 13 | 14 | {% endif %} 15 |
16 |
17 | 18 |
19 | 20 |
21 |

@{{ profile.user }}

22 |

{% if profile.first_name %}{{ profile.first_name }} {{ profile.last_name }}{% endif %}

23 | 24 |
25 | Follow 26 |
27 | 28 |
29 |
30 | 50 |

{% if profile.profile_info %}{{ profile.profile_info }}{% endif %}

51 | 52 | {% if user.is_authenticated and user == profile.user %} 53 | Edit Profile 54 | {% endif %} 55 | 56 |
57 | 58 |
59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 |
67 |
68 | 69 | 87 | 88 |
89 |
90 | 91 |
92 | 93 | {% for post in posts %} 94 |
95 |
96 |
97 | 98 |
99 |
100 |
101 | {% endfor %} 102 | 103 | 104 | 105 |
106 | 107 | {% endblock %} -------------------------------------------------------------------------------- /instagram_clone/templates/registration/password_reset_complete.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | {% block content %} 4 | 5 |
6 |
7 |
8 |
9 |
10 |
11 | check_circle 12 |
13 |
14 |

Your password has been set. Please Sign in< now. Thank you!/h4> 15 |

16 | 17 | 18 |
19 | 20 |
21 |
22 | {% endblock %} -------------------------------------------------------------------------------- /instagram_clone/templates/registration/password_reset_confirm.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | {% load static %} 3 | 4 | 5 | {% block content %} 6 | 7 |
8 |
9 | 10 |
11 | {% csrf_token %} 12 | {{ form.id }} 13 |

Set a new password

14 |
15 | {% if validlink %} 16 |
17 |
18 | {{ form.new_password1 }} 19 | 20 |
21 |
22 |
23 |
24 | {{ form.new_password2 }} 25 | 26 |
27 |
28 | {% else %} 29 |
30 |
31 | The password reset link was invalid, it has alredy been used. Please request a new one. 32 |
33 |
34 | {% endif %} 35 | 36 |
37 |
38 | 39 | {% endblock %} -------------------------------------------------------------------------------- /instagram_clone/templates/registration/password_reset_done.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | {% block content %} 4 | 5 |
6 |
7 |
8 |
9 |
10 |
11 | check_circle 12 |
13 |
14 |

We have emailed you instructions to reset your password

15 |

If an account exists with the email you entered. You will receive the token.

16 |

If you don't receive an email. Check your spam folder or make sure you entered the correct email.

17 |
18 | 19 | 20 |
21 | 22 |
23 |
24 | {% endblock %} -------------------------------------------------------------------------------- /instagram_clone/templates/registration/password_reset_email.html: -------------------------------------------------------------------------------- 1 | {% autoescape off %} 2 | 3 | Your initiate a password reset proccess your account: {{ user.get_username }} in --yourwebsite-- 4 | 5 | Click the link below continue: 6 | 7 | {{ protocol }}://{{ domain }}{% url 'password_reset_confirm' uidb64=uid token=token %} 8 | 9 | If the link doesn't work, Please copy and paste the url in a new tab. 10 | 11 | Sincerely, 12 | -Yourwebsite 13 | 14 | {% endautoescape %} -------------------------------------------------------------------------------- /instagram_clone/templates/registration/password_reset_form.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | {% load static %} 3 | 4 | 5 | {% block content %} 6 | 7 |
8 |
9 | {% csrf_token %} 10 | {{ form.id }} 11 |

Forgot password

12 |
13 |
14 | {{ form.email }} 15 | 16 |
17 |
18 |
19 |
20 | {{ form.errors }} 21 |
22 |
23 | 24 |
25 |
26 | 27 | {% endblock %} -------------------------------------------------------------------------------- /instagram_clone/templates/registration/password_reset_subject.txt: -------------------------------------------------------------------------------- 1 | Password reset for yourwebsite -------------------------------------------------------------------------------- /instagram_clone/templates/signup.html: -------------------------------------------------------------------------------- 1 | {% load static %} 2 | 3 | 4 | 5 | 6 | 7 | 8 | Hello Bulma! 9 | 10 | 11 | 13 | 14 | 15 | 16 | 17 |
18 |
19 | 20 |
21 |
22 | 23 |
24 |
25 | 26 |
27 | {% csrf_token %} 28 |

Create an account

29 | 30 |
31 |

32 | 33 | {{ form.username }} 34 | 35 | 36 | 37 |

38 |
39 | 40 |
41 |

42 | 43 | {{ form.email }} 44 | 45 | 46 | 47 |

48 |
49 | 50 |
51 |

52 | 53 | {{ form.password }} 54 | 55 | 56 | 57 |

58 |
59 | 60 |
61 |

62 | 63 | {{ form.confirm_password }} 64 | 65 | 66 | 67 |

68 |
69 | 70 |
71 |
72 | {{ form.errors }} 73 |
74 |
75 | 76 |
77 |

78 | 81 |

82 |
83 | 84 | 85 |
86 |
87 | 88 | 89 |
90 |
91 | 92 | 93 | 94 | 95 | -------------------------------------------------------------------------------- /instagram_clone/templates/tag.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | 3 | {% load static %} 4 | 5 | 6 | {% block banner %} 7 |
8 |
9 |
10 |

11 | #{{ tag.title }} 12 |

13 |
14 |
15 |
16 | {% endblock %} 17 | 18 | 19 | 20 | {% block content %} 21 | 22 |
23 | 24 | 25 | {% for post in posts %} 26 |
27 |
28 |
29 | Image 30 |
31 |
32 |
33 | {% endfor %} 34 | 35 |
36 | 37 | {% endblock %} -------------------------------------------------------------------------------- /instagram_clone/urls.py: -------------------------------------------------------------------------------- 1 | """instagram_clone URL Configuration 2 | 3 | The `urlpatterns` list routes URLs to views. For more information please see: 4 | https://docs.djangoproject.com/en/3.0/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 | from authy.views import UserProfile, UserProfileFavorites, follow 22 | 23 | urlpatterns = [ 24 | path('admin/', admin.site.urls), 25 | path('post/', include('post.urls')), 26 | path('user/', include('authy.urls')), 27 | path('direct/', include('direct.urls')), 28 | path('stories/', include('stories.urls')), 29 | path('notifications/', include('notifications.urls')), 30 | path('/', UserProfile, name='profile'), 31 | path('/saved', UserProfile, name='profilefavorites'), 32 | path('/follow/