added requirements.txt
|
@ -1,3 +1,3 @@
|
|||
[ZoneTransfer]
|
||||
ZoneId=3
|
||||
ReferrerUrl=C:\Users\rushi\Downloads\segoe-ui-4-cufonfonts.zip
|
||||
[ZoneTransfer]
|
||||
ZoneId=3
|
||||
ReferrerUrl=C:\Users\rushi\Downloads\segoe-ui-4-cufonfonts.zip
|
|
@ -1,3 +1,3 @@
|
|||
[ZoneTransfer]
|
||||
ZoneId=3
|
||||
ReferrerUrl=C:\Users\rushi\Downloads\segoe-ui-4-cufonfonts.zip
|
||||
[ZoneTransfer]
|
||||
ZoneId=3
|
||||
ReferrerUrl=C:\Users\rushi\Downloads\segoe-ui-4-cufonfonts.zip
|
|
@ -1,3 +1,3 @@
|
|||
[ZoneTransfer]
|
||||
ZoneId=3
|
||||
ReferrerUrl=C:\Users\rushi\Downloads\segoe-ui-4-cufonfonts.zip
|
||||
[ZoneTransfer]
|
||||
ZoneId=3
|
||||
ReferrerUrl=C:\Users\rushi\Downloads\segoe-ui-4-cufonfonts.zip
|
|
@ -1,3 +1,3 @@
|
|||
[ZoneTransfer]
|
||||
ZoneId=3
|
||||
ReferrerUrl=C:\Users\rushi\Downloads\segoe-ui-4-cufonfonts.zip
|
||||
[ZoneTransfer]
|
||||
ZoneId=3
|
||||
ReferrerUrl=C:\Users\rushi\Downloads\segoe-ui-4-cufonfonts.zip
|
BIN
chirper/blog/static/android-chrome-192x192.png
Normal file
After Width: | Height: | Size: 12 KiB |
|
@ -0,0 +1,3 @@
|
|||
[ZoneTransfer]
|
||||
ZoneId=3
|
||||
ReferrerUrl=C:\Users\rushi\Downloads\favicon_io.zip
|
BIN
chirper/blog/static/android-chrome-512x512.png
Normal file
After Width: | Height: | Size: 38 KiB |
|
@ -0,0 +1,3 @@
|
|||
[ZoneTransfer]
|
||||
ZoneId=3
|
||||
ReferrerUrl=C:\Users\rushi\Downloads\favicon_io.zip
|
BIN
chirper/blog/static/apple-touch-icon.png
Normal file
After Width: | Height: | Size: 10 KiB |
3
chirper/blog/static/apple-touch-icon.png:Zone.Identifier
Normal file
|
@ -0,0 +1,3 @@
|
|||
[ZoneTransfer]
|
||||
ZoneId=3
|
||||
ReferrerUrl=C:\Users\rushi\Downloads\favicon_io.zip
|
BIN
chirper/blog/static/favicon-16x16.png
Normal file
After Width: | Height: | Size: 590 B |
3
chirper/blog/static/favicon-16x16.png:Zone.Identifier
Normal file
|
@ -0,0 +1,3 @@
|
|||
[ZoneTransfer]
|
||||
ZoneId=3
|
||||
ReferrerUrl=C:\Users\rushi\Downloads\favicon_io.zip
|
BIN
chirper/blog/static/favicon-32x32.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
3
chirper/blog/static/favicon-32x32.png:Zone.Identifier
Normal file
|
@ -0,0 +1,3 @@
|
|||
[ZoneTransfer]
|
||||
ZoneId=3
|
||||
ReferrerUrl=C:\Users\rushi\Downloads\favicon_io.zip
|
BIN
chirper/blog/static/favicon.ico
Normal file
After Width: | Height: | Size: 15 KiB |
3
chirper/blog/static/favicon.ico:Zone.Identifier
Normal file
|
@ -0,0 +1,3 @@
|
|||
[ZoneTransfer]
|
||||
ZoneId=3
|
||||
ReferrerUrl=C:\Users\rushi\Downloads\favicon_io.zip
|
1
chirper/blog/static/site.webmanifest
Normal file
|
@ -0,0 +1 @@
|
|||
{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
|
3
chirper/blog/static/site.webmanifest:Zone.Identifier
Normal file
|
@ -0,0 +1,3 @@
|
|||
[ZoneTransfer]
|
||||
ZoneId=3
|
||||
ReferrerUrl=C:\Users\rushi\Downloads\favicon_io.zip
|
|
@ -14,8 +14,10 @@
|
|||
|
||||
<link rel="stylesheet" type="text/css" href="{% static 'blog/styles.css' %}">
|
||||
|
||||
<!-- Favicon -->
|
||||
<link rel="shortcut icon" type="image/png" href="{% static 'favicon.ico' %}"/>
|
||||
|
||||
<title>Chirper🐦</title>
|
||||
<title>Chirper</title>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
|
|
@ -1,27 +1,27 @@
|
|||
{% extends "blog/base.html" %}
|
||||
{% block content %}
|
||||
<div class="content-section">
|
||||
<form method="post">
|
||||
{% csrf_token %}
|
||||
<fieldset class="form-group">
|
||||
<legend class="border-bottom mb-4"> Delete post </legend>
|
||||
<h2>Are you sure you want to delete this post?</h2>
|
||||
<article class="media content-section">
|
||||
<img class="rounded-circle article-img" src="{{ object.author.profile.profile_pic.url}}" alt="Profile Picture">
|
||||
<div class="media-body">
|
||||
<div class="article-metadata">
|
||||
<a class="mr-2" href="#">{{ object.author.get_full_name }}</a>
|
||||
<small class="text-muted">@{{ object.author }} · {{ object.date_posted }}</small>
|
||||
</div>
|
||||
<p class="article-content font-weight-light">{{ post.content }}</p>
|
||||
</div>
|
||||
</article>
|
||||
</fieldset>
|
||||
<div class="form-group">
|
||||
<button type="submit" class="btn btn-outline-danger">Yes, Delete</button>
|
||||
<a type="submit" class="btn btn-outline-secondary" href="{% url 'post-detail' object.id %}">No, take me back</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock content %}
|
||||
{% extends "blog/base.html" %}
|
||||
{% block content %}
|
||||
<div class="content-section">
|
||||
<form method="post">
|
||||
{% csrf_token %}
|
||||
<fieldset class="form-group">
|
||||
<legend class="border-bottom mb-4"> Delete post </legend>
|
||||
<h2>Are you sure you want to delete this post?</h2>
|
||||
<article class="media content-section">
|
||||
<img class="rounded-circle article-img" src="{{ object.author.profile.profile_pic.url}}" alt="Profile Picture">
|
||||
<div class="media-body">
|
||||
<div class="article-metadata">
|
||||
<a class="mr-2" href="#">{{ object.author.get_full_name }}</a>
|
||||
<small class="text-muted">@{{ object.author }} · {{ object.date_posted }}</small>
|
||||
</div>
|
||||
<p class="article-content font-weight-light">{{ post.content }}</p>
|
||||
</div>
|
||||
</article>
|
||||
</fieldset>
|
||||
<div class="form-group">
|
||||
<button type="submit" class="btn btn-outline-danger">Yes, Delete</button>
|
||||
<a type="submit" class="btn btn-outline-secondary" href="{% url 'post-detail' object.id %}">No, take me back</a>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock content %}
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
{% extends "blog/base.html" %}
|
||||
{% block content %}
|
||||
<article class="media content-section">
|
||||
<img class="rounded-circle article-img" src="{{ object.author.profile.profile_pic.url}}" alt="Profile Picture">
|
||||
<div class="media-body">
|
||||
<div class="article-metadata">
|
||||
<a class="mr-2" href="{% url 'user-posts' object.author.username %}">{{ object.author.get_full_name }}</a>
|
||||
<small class="text-muted">@{{ object.author }} · {{ object.date_posted }}</small>
|
||||
{% if object.author == user %}
|
||||
<div>
|
||||
<a class="btn btn-secondary btn-sm mt-1 mb-1" href="{% url 'post-update' object.id %}">Edit chirp</a>
|
||||
<a class="btn btn-danger btn-sm mt-1 mb-1" href="{% url 'post-delete' object.id %}">Delete chirp</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<p class="article-content font-weight-light">{{ post.content }}</p>
|
||||
</div>
|
||||
</article>
|
||||
{% endblock content %}
|
||||
{% extends "blog/base.html" %}
|
||||
{% block content %}
|
||||
<article class="media content-section">
|
||||
<img class="rounded-circle article-img" src="{{ object.author.profile.profile_pic.url}}" alt="Profile Picture">
|
||||
<div class="media-body">
|
||||
<div class="article-metadata">
|
||||
<a class="mr-2" href="{% url 'user-posts' object.author.username %}">{{ object.author.get_full_name }}</a>
|
||||
<small class="text-muted">@{{ object.author }} · {{ object.date_posted }}</small>
|
||||
{% if object.author == user %}
|
||||
<div>
|
||||
<a class="btn btn-secondary btn-sm mt-1 mb-1" href="{% url 'post-update' object.id %}">Edit chirp</a>
|
||||
<a class="btn btn-danger btn-sm mt-1 mb-1" href="{% url 'post-delete' object.id %}">Delete chirp</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<p class="article-content font-weight-light">{{ post.content }}</p>
|
||||
</div>
|
||||
</article>
|
||||
{% endblock content %}
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
{% extends "blog/base.html" %}
|
||||
{% load crispy_forms_tags %}
|
||||
{% block content %}
|
||||
<div class="content-section">
|
||||
<form method="post">
|
||||
{% csrf_token %}
|
||||
<fieldset class="form-group">
|
||||
{{ form | crispy}}
|
||||
</fieldset>
|
||||
<div class="form-group">
|
||||
<button type="submit" class="btn btn-outline-info">Chirp</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock content %}
|
||||
{% extends "blog/base.html" %}
|
||||
{% load crispy_forms_tags %}
|
||||
{% block content %}
|
||||
<div class="content-section">
|
||||
<form method="post">
|
||||
{% csrf_token %}
|
||||
<fieldset class="form-group">
|
||||
{{ form | crispy}}
|
||||
</fieldset>
|
||||
<div class="form-group">
|
||||
<button type="submit" class="btn btn-outline-info">Chirp</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock content %}
|
||||
|
|
|
@ -1,37 +1,37 @@
|
|||
{% extends "blog/base.html" %}
|
||||
{% block content %}
|
||||
<h1 class="mb-3">Posts by {{ view.kwargs.username }} ({{ page_obj.paginator.count }})</h1></h1>
|
||||
{% for post in posts %}
|
||||
<article class="media content-section">
|
||||
<img class="rounded-circle article-img" src="{{ post.author.profile.profile_pic.url}}" alt="Profile Picture">
|
||||
<div class="media-body">
|
||||
<div class="article-metadata">
|
||||
<a class="mr-2" href="{% url 'user-posts' post.author.username %}">{{ post.author.get_full_name }}</a>
|
||||
<small class="text-muted">@{{ post.author }} · {{ post.date_posted }}</small>
|
||||
</div>
|
||||
<p class="article-content font-weight-light"><a class="nounderline" href="{% url 'post-detail' post.id %}">{{ post.content }}</a></p>
|
||||
</div>
|
||||
</article>
|
||||
{% endfor %}
|
||||
{% if is_paginated %}
|
||||
|
||||
{% if page_obj.has_previous %}
|
||||
<a class="btn btn-outline-info mb-4" href="?page=1">First</a>
|
||||
<a class="btn btn-outline-info mb-4" href="?page={{ page_obj.previous_page_number }}">Previous</a>
|
||||
{% endif %}
|
||||
|
||||
{% for num in page_obj.paginator.page_range %}
|
||||
{% if page_obj.number == num %}
|
||||
<a class="btn btn-info mb-4" href="?page={{ num }}">{{ num }}</a>
|
||||
{% elif num > page_obj.number|add:'-3' and num < page_obj.number|add:'3' %}
|
||||
<a class="btn btn-outline-info mb-4" href="?page={{ num }}">{{ num }}</a>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{% if page_obj.has_next %}
|
||||
<a class="btn btn-outline-info mb-4" href="?page={{ page_obj.next_page_number }}">Next</a>
|
||||
<a class="btn btn-outline-info mb-4" href="?page={{ page_obj.paginator.num_pages }}">Last</a>
|
||||
{% endif %}
|
||||
|
||||
{% endif %}
|
||||
{% endblock content %}
|
||||
{% extends "blog/base.html" %}
|
||||
{% block content %}
|
||||
<h1 class="mb-3">Posts by {{ view.kwargs.username }} ({{ page_obj.paginator.count }})</h1></h1>
|
||||
{% for post in posts %}
|
||||
<article class="media content-section">
|
||||
<img class="rounded-circle article-img" src="{{ post.author.profile.profile_pic.url}}" alt="Profile Picture">
|
||||
<div class="media-body">
|
||||
<div class="article-metadata">
|
||||
<a class="mr-2" href="{% url 'user-posts' post.author.username %}">{{ post.author.get_full_name }}</a>
|
||||
<small class="text-muted">@{{ post.author }} · {{ post.date_posted }}</small>
|
||||
</div>
|
||||
<p class="article-content font-weight-light"><a class="nounderline" href="{% url 'post-detail' post.id %}">{{ post.content }}</a></p>
|
||||
</div>
|
||||
</article>
|
||||
{% endfor %}
|
||||
{% if is_paginated %}
|
||||
|
||||
{% if page_obj.has_previous %}
|
||||
<a class="btn btn-outline-info mb-4" href="?page=1">First</a>
|
||||
<a class="btn btn-outline-info mb-4" href="?page={{ page_obj.previous_page_number }}">Previous</a>
|
||||
{% endif %}
|
||||
|
||||
{% for num in page_obj.paginator.page_range %}
|
||||
{% if page_obj.number == num %}
|
||||
<a class="btn btn-info mb-4" href="?page={{ num }}">{{ num }}</a>
|
||||
{% elif num > page_obj.number|add:'-3' and num < page_obj.number|add:'3' %}
|
||||
<a class="btn btn-outline-info mb-4" href="?page={{ num }}">{{ num }}</a>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{% if page_obj.has_next %}
|
||||
<a class="btn btn-outline-info mb-4" href="?page={{ page_obj.next_page_number }}">Next</a>
|
||||
<a class="btn btn-outline-info mb-4" href="?page={{ page_obj.paginator.num_pages }}">Last</a>
|
||||
{% endif %}
|
||||
|
||||
{% endif %}
|
||||
{% endblock content %}
|
||||
|
|
0
chirper/manage.py
Normal file → Executable file
0
chirper/media/default2.jpg
Normal file → Executable file
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
|
@ -1,22 +1,22 @@
|
|||
from django import forms
|
||||
from django.contrib.auth.models import User
|
||||
from .models import Profile
|
||||
|
||||
class UserUpdateForm(forms.ModelForm):
|
||||
|
||||
email = forms.EmailField()
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(UserUpdateForm, self).__init__(*args, **kwargs)
|
||||
instance = getattr(self, 'instance', None)
|
||||
if instance and instance.pk:
|
||||
self.fields['username'].widget.attrs['readonly'] = True
|
||||
|
||||
class Meta:
|
||||
model = User
|
||||
fields = ['username', 'email']
|
||||
|
||||
class ProfileUpdateForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Profile
|
||||
fields = ['profile_pic']
|
||||
from django import forms
|
||||
from django.contrib.auth.models import User
|
||||
from .models import Profile
|
||||
|
||||
class UserUpdateForm(forms.ModelForm):
|
||||
|
||||
email = forms.EmailField()
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(UserUpdateForm, self).__init__(*args, **kwargs)
|
||||
instance = getattr(self, 'instance', None)
|
||||
if instance and instance.pk:
|
||||
self.fields['username'].widget.attrs['readonly'] = True
|
||||
|
||||
class Meta:
|
||||
model = User
|
||||
fields = ['username', 'email']
|
||||
|
||||
class ProfileUpdateForm(forms.ModelForm):
|
||||
class Meta:
|
||||
model = Profile
|
||||
fields = ['profile_pic']
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
from django.db.models.signals import post_save
|
||||
from django.contrib.auth.models import User
|
||||
from django.dispatch import receiver
|
||||
from .models import Profile
|
||||
|
||||
@receiver(post_save, sender=User)
|
||||
def create_profile(sender, instance, created, **kwargs):
|
||||
if created:
|
||||
Profile.objects.create(user=instance)
|
||||
|
||||
@receiver(post_save, sender=User)
|
||||
def save_profile(sender, instance, **kwargs):
|
||||
instance.profile.save()
|
||||
from django.db.models.signals import post_save
|
||||
from django.contrib.auth.models import User
|
||||
from django.dispatch import receiver
|
||||
from .models import Profile
|
||||
|
||||
@receiver(post_save, sender=User)
|
||||
def create_profile(sender, instance, created, **kwargs):
|
||||
if created:
|
||||
Profile.objects.create(user=instance)
|
||||
|
||||
@receiver(post_save, sender=User)
|
||||
def save_profile(sender, instance, **kwargs):
|
||||
instance.profile.save()
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
{% extends "blog/base.html" %}
|
||||
{% block content %}
|
||||
<h2>You have been logged out</h2>
|
||||
<div class="border-top pt-2">
|
||||
<small class="text-muted text-large">
|
||||
<a href="{% url 'login' %}">Log In Again</a>
|
||||
</small>
|
||||
</div>
|
||||
{% endblock content %}
|
||||
{% extends "blog/base.html" %}
|
||||
{% block content %}
|
||||
<h2>You have been logged out</h2>
|
||||
<div class="border-top pt-2">
|
||||
<small class="text-muted text-large">
|
||||
<a href="{% url 'login' %}">Log In Again</a>
|
||||
</small>
|
||||
</div>
|
||||
{% endblock content %}
|
||||
|
|
|
@ -1,25 +1,25 @@
|
|||
{% extends "blog/base.html" %}
|
||||
{% load crispy_forms_tags %}
|
||||
{% block content %}
|
||||
<div class="content-section">
|
||||
<div class="media">
|
||||
<img class="rounded-circle account-img" src="{{ user.profile.profile_pic.url }}">
|
||||
<div class="media-body">
|
||||
<h2 class="account-heading">{{ user.username }}</h2>
|
||||
<p class="text-secondary">{{ user.email }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<form method="post" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
<fieldset class="form-group">
|
||||
<legend class="border-bottom mb-4"> Your profile </legend>
|
||||
{{ userForm|crispy}}
|
||||
{{ profileForm|crispy }}
|
||||
</fieldset>
|
||||
<div class="form-group">
|
||||
<button type="submit" class="btn btn-outline-info">Update</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock content %}
|
||||
{% extends "blog/base.html" %}
|
||||
{% load crispy_forms_tags %}
|
||||
{% block content %}
|
||||
<div class="content-section">
|
||||
<div class="media">
|
||||
<img class="rounded-circle account-img" src="{{ user.profile.profile_pic.url }}">
|
||||
<div class="media-body">
|
||||
<h2 class="account-heading">{{ user.username }}</h2>
|
||||
<p class="text-secondary">{{ user.email }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<form method="post" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
<fieldset class="form-group">
|
||||
<legend class="border-bottom mb-4"> Your profile </legend>
|
||||
{{ userForm|crispy}}
|
||||
{{ profileForm|crispy }}
|
||||
</fieldset>
|
||||
<div class="form-group">
|
||||
<button type="submit" class="btn btn-outline-info">Update</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock content %}
|
||||
|
|
31
requirements.txt
Normal file
|
@ -0,0 +1,31 @@
|
|||
asgiref==3.2.7
|
||||
certifi==2020.4.5.1
|
||||
cffi==1.14.0
|
||||
chardet==3.0.4
|
||||
cryptography==2.9.2
|
||||
defusedxml==0.7.0rc1
|
||||
Django==3.0.6
|
||||
django-cors-headers==3.2.1
|
||||
django-crispy-forms==1.9.1
|
||||
django-oauth-toolkit==1.3.2
|
||||
idna==2.9
|
||||
ion-oauth==0.1
|
||||
mongoengine==0.20.0
|
||||
oauth2-provider==0.0
|
||||
oauthlib==3.1.0
|
||||
Pillow==7.1.2
|
||||
pkg-resources==0.0.0
|
||||
pycparser==2.20
|
||||
PyJWT==1.7.1
|
||||
pymongo==3.10.1
|
||||
python-social-auth==0.3.6
|
||||
python3-openid==3.1.0
|
||||
pytz==2020.1
|
||||
requests==2.23.0
|
||||
requests-oauth==0.4.1
|
||||
requests-oauthlib==1.3.0
|
||||
six==1.15.0
|
||||
social-auth-core==3.3.3
|
||||
social-auth-storage-mongoengine==1.0.1
|
||||
sqlparse==0.3.1
|
||||
urllib3==1.25.9
|