├── app ├── __init__.py ├── migrations │ ├── __init__.py │ ├── __pycache__ │ │ ├── __init__.cpython-37.pyc │ │ ├── 0001_initial.cpython-37.pyc │ │ ├── 0005_contact_manager.cpython-37.pyc │ │ ├── 0002_auto_20190209_1152.cpython-37.pyc │ │ ├── 0003_auto_20190217_2103.cpython-37.pyc │ │ └── 0004_remove_contact_manager.cpython-37.pyc │ ├── 0004_remove_contact_manager.py │ ├── 0002_auto_20190209_1152.py │ ├── 0005_contact_manager.py │ ├── 0003_auto_20190217_2103.py │ └── 0001_initial.py ├── tests.py ├── apps.py ├── __pycache__ │ ├── urls.cpython-37.pyc │ ├── admin.cpython-37.pyc │ ├── models.cpython-37.pyc │ ├── views.cpython-37.pyc │ └── __init__.cpython-37.pyc ├── admin.py ├── urls.py ├── models.py └── views.py ├── contacts ├── __init__.py ├── __pycache__ │ ├── urls.cpython-37.pyc │ ├── wsgi.cpython-37.pyc │ ├── __init__.cpython-37.pyc │ └── settings.cpython-37.pyc ├── wsgi.py ├── urls.py └── settings.py ├── .gitignore ├── .vscode └── settings.json ├── media └── images │ ├── boy.jpg │ ├── girl.jpg │ ├── messi.jpg │ ├── ronaldo.jpg │ ├── bill_gates.jpg │ ├── boy_XFva2Xw.jpg │ ├── boy_q3yEobQ.jpg │ ├── elon_musk.jpg │ ├── emma_watson.png │ ├── jackie_chan.jpg │ ├── james_bond.jpg │ ├── sarukh_khan.jpg │ ├── barack_obama.jpg │ ├── donald_trump.jpg │ ├── messi_7v0emTr.jpg │ ├── messi_H4IiZAr.jpg │ ├── oprah_winfrey.jpg │ ├── taylor_swift.jpg │ ├── ronaldo_EyQB5kI.jpg │ ├── ronaldo_qy2rWAL.jpg │ ├── bill_gates_RsO78Qg.jpg │ ├── bill_gates_x83UvLx.jpg │ ├── elon_musk_FqlcciW.jpg │ ├── elon_musk_rHUiKNX.jpg │ ├── james_bond_6pP7XrW.jpg │ ├── james_bond_uVwokiJ.jpg │ ├── barack_obama_27LVOFd.jpg │ ├── barack_obama_h5PhxaQ.jpg │ ├── donald_trump_K40s1aT.jpg │ ├── donald_trump_Ld3I8nX.jpg │ ├── emma_watson_5zJrNYP.png │ ├── emma_watson_MT2gLIs.png │ ├── jackie_chan_002ZUrV.jpg │ ├── jackie_chan_69MWG5J.jpg │ ├── jackie_chan_QQyq1xV.jpg │ ├── oprah_winfrey_SVvY68g.jpg │ ├── oprah_winfrey_wPNomnv.jpg │ ├── sarukh_khan_abKBxIc.jpg │ ├── sarukh_khan_qVVY7a2.jpg │ ├── taylor_swift_OCC4Eps.jpg │ └── taylor_swift_VhVXvsP.jpg ├── static ├── images │ ├── boy.png │ ├── girl.png │ └── contact-icon.png └── css │ ├── admin.css │ └── main.css ├── templates ├── 404.html ├── 500.html ├── admin │ └── base_site.html ├── partials │ ├── _message.html │ └── _card.html ├── registration │ ├── logged_out.html │ ├── login.html │ └── signup.html ├── create.html ├── index.html ├── search.html ├── update.html ├── delete.html ├── detail.html └── base.html ├── requirements.txt └── manage.py /app/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /contacts/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/migrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | env/ 2 | db.sqlite3 -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "python.pythonPath": "env\\Scripts\\python.exe" 3 | } -------------------------------------------------------------------------------- /app/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /media/images/boy.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codersamir/django_contacts/HEAD/media/images/boy.jpg -------------------------------------------------------------------------------- /media/images/girl.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codersamir/django_contacts/HEAD/media/images/girl.jpg -------------------------------------------------------------------------------- /media/images/messi.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codersamir/django_contacts/HEAD/media/images/messi.jpg -------------------------------------------------------------------------------- /static/images/boy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codersamir/django_contacts/HEAD/static/images/boy.png -------------------------------------------------------------------------------- /static/images/girl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codersamir/django_contacts/HEAD/static/images/girl.png -------------------------------------------------------------------------------- /app/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class AppConfig(AppConfig): 5 | name = 'app' 6 | -------------------------------------------------------------------------------- /media/images/ronaldo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codersamir/django_contacts/HEAD/media/images/ronaldo.jpg -------------------------------------------------------------------------------- /media/images/bill_gates.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codersamir/django_contacts/HEAD/media/images/bill_gates.jpg -------------------------------------------------------------------------------- /media/images/boy_XFva2Xw.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codersamir/django_contacts/HEAD/media/images/boy_XFva2Xw.jpg -------------------------------------------------------------------------------- /media/images/boy_q3yEobQ.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codersamir/django_contacts/HEAD/media/images/boy_q3yEobQ.jpg -------------------------------------------------------------------------------- /media/images/elon_musk.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codersamir/django_contacts/HEAD/media/images/elon_musk.jpg -------------------------------------------------------------------------------- /media/images/emma_watson.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codersamir/django_contacts/HEAD/media/images/emma_watson.png -------------------------------------------------------------------------------- /media/images/jackie_chan.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codersamir/django_contacts/HEAD/media/images/jackie_chan.jpg -------------------------------------------------------------------------------- /media/images/james_bond.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codersamir/django_contacts/HEAD/media/images/james_bond.jpg -------------------------------------------------------------------------------- /media/images/sarukh_khan.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codersamir/django_contacts/HEAD/media/images/sarukh_khan.jpg -------------------------------------------------------------------------------- /media/images/barack_obama.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codersamir/django_contacts/HEAD/media/images/barack_obama.jpg -------------------------------------------------------------------------------- /media/images/donald_trump.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codersamir/django_contacts/HEAD/media/images/donald_trump.jpg -------------------------------------------------------------------------------- /media/images/messi_7v0emTr.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codersamir/django_contacts/HEAD/media/images/messi_7v0emTr.jpg -------------------------------------------------------------------------------- /media/images/messi_H4IiZAr.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codersamir/django_contacts/HEAD/media/images/messi_H4IiZAr.jpg -------------------------------------------------------------------------------- /media/images/oprah_winfrey.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codersamir/django_contacts/HEAD/media/images/oprah_winfrey.jpg -------------------------------------------------------------------------------- /media/images/taylor_swift.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codersamir/django_contacts/HEAD/media/images/taylor_swift.jpg -------------------------------------------------------------------------------- /static/images/contact-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codersamir/django_contacts/HEAD/static/images/contact-icon.png -------------------------------------------------------------------------------- /media/images/ronaldo_EyQB5kI.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codersamir/django_contacts/HEAD/media/images/ronaldo_EyQB5kI.jpg -------------------------------------------------------------------------------- /media/images/ronaldo_qy2rWAL.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codersamir/django_contacts/HEAD/media/images/ronaldo_qy2rWAL.jpg -------------------------------------------------------------------------------- /app/__pycache__/urls.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codersamir/django_contacts/HEAD/app/__pycache__/urls.cpython-37.pyc -------------------------------------------------------------------------------- /media/images/bill_gates_RsO78Qg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codersamir/django_contacts/HEAD/media/images/bill_gates_RsO78Qg.jpg -------------------------------------------------------------------------------- /media/images/bill_gates_x83UvLx.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codersamir/django_contacts/HEAD/media/images/bill_gates_x83UvLx.jpg -------------------------------------------------------------------------------- /media/images/elon_musk_FqlcciW.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codersamir/django_contacts/HEAD/media/images/elon_musk_FqlcciW.jpg -------------------------------------------------------------------------------- /media/images/elon_musk_rHUiKNX.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codersamir/django_contacts/HEAD/media/images/elon_musk_rHUiKNX.jpg -------------------------------------------------------------------------------- /media/images/james_bond_6pP7XrW.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codersamir/django_contacts/HEAD/media/images/james_bond_6pP7XrW.jpg -------------------------------------------------------------------------------- /media/images/james_bond_uVwokiJ.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codersamir/django_contacts/HEAD/media/images/james_bond_uVwokiJ.jpg -------------------------------------------------------------------------------- /app/__pycache__/admin.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codersamir/django_contacts/HEAD/app/__pycache__/admin.cpython-37.pyc -------------------------------------------------------------------------------- /app/__pycache__/models.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codersamir/django_contacts/HEAD/app/__pycache__/models.cpython-37.pyc -------------------------------------------------------------------------------- /app/__pycache__/views.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codersamir/django_contacts/HEAD/app/__pycache__/views.cpython-37.pyc -------------------------------------------------------------------------------- /media/images/barack_obama_27LVOFd.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codersamir/django_contacts/HEAD/media/images/barack_obama_27LVOFd.jpg -------------------------------------------------------------------------------- /media/images/barack_obama_h5PhxaQ.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codersamir/django_contacts/HEAD/media/images/barack_obama_h5PhxaQ.jpg -------------------------------------------------------------------------------- /media/images/donald_trump_K40s1aT.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codersamir/django_contacts/HEAD/media/images/donald_trump_K40s1aT.jpg -------------------------------------------------------------------------------- /media/images/donald_trump_Ld3I8nX.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codersamir/django_contacts/HEAD/media/images/donald_trump_Ld3I8nX.jpg -------------------------------------------------------------------------------- /media/images/emma_watson_5zJrNYP.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codersamir/django_contacts/HEAD/media/images/emma_watson_5zJrNYP.png -------------------------------------------------------------------------------- /media/images/emma_watson_MT2gLIs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codersamir/django_contacts/HEAD/media/images/emma_watson_MT2gLIs.png -------------------------------------------------------------------------------- /media/images/jackie_chan_002ZUrV.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codersamir/django_contacts/HEAD/media/images/jackie_chan_002ZUrV.jpg -------------------------------------------------------------------------------- /media/images/jackie_chan_69MWG5J.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codersamir/django_contacts/HEAD/media/images/jackie_chan_69MWG5J.jpg -------------------------------------------------------------------------------- /media/images/jackie_chan_QQyq1xV.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codersamir/django_contacts/HEAD/media/images/jackie_chan_QQyq1xV.jpg -------------------------------------------------------------------------------- /media/images/oprah_winfrey_SVvY68g.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codersamir/django_contacts/HEAD/media/images/oprah_winfrey_SVvY68g.jpg -------------------------------------------------------------------------------- /media/images/oprah_winfrey_wPNomnv.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codersamir/django_contacts/HEAD/media/images/oprah_winfrey_wPNomnv.jpg -------------------------------------------------------------------------------- /media/images/sarukh_khan_abKBxIc.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codersamir/django_contacts/HEAD/media/images/sarukh_khan_abKBxIc.jpg -------------------------------------------------------------------------------- /media/images/sarukh_khan_qVVY7a2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codersamir/django_contacts/HEAD/media/images/sarukh_khan_qVVY7a2.jpg -------------------------------------------------------------------------------- /media/images/taylor_swift_OCC4Eps.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codersamir/django_contacts/HEAD/media/images/taylor_swift_OCC4Eps.jpg -------------------------------------------------------------------------------- /media/images/taylor_swift_VhVXvsP.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codersamir/django_contacts/HEAD/media/images/taylor_swift_VhVXvsP.jpg -------------------------------------------------------------------------------- /app/__pycache__/__init__.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codersamir/django_contacts/HEAD/app/__pycache__/__init__.cpython-37.pyc -------------------------------------------------------------------------------- /contacts/__pycache__/urls.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codersamir/django_contacts/HEAD/contacts/__pycache__/urls.cpython-37.pyc -------------------------------------------------------------------------------- /contacts/__pycache__/wsgi.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codersamir/django_contacts/HEAD/contacts/__pycache__/wsgi.cpython-37.pyc -------------------------------------------------------------------------------- /contacts/__pycache__/__init__.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codersamir/django_contacts/HEAD/contacts/__pycache__/__init__.cpython-37.pyc -------------------------------------------------------------------------------- /contacts/__pycache__/settings.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codersamir/django_contacts/HEAD/contacts/__pycache__/settings.cpython-37.pyc -------------------------------------------------------------------------------- /app/migrations/__pycache__/__init__.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codersamir/django_contacts/HEAD/app/migrations/__pycache__/__init__.cpython-37.pyc -------------------------------------------------------------------------------- /app/migrations/__pycache__/0001_initial.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codersamir/django_contacts/HEAD/app/migrations/__pycache__/0001_initial.cpython-37.pyc -------------------------------------------------------------------------------- /app/migrations/__pycache__/0005_contact_manager.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codersamir/django_contacts/HEAD/app/migrations/__pycache__/0005_contact_manager.cpython-37.pyc -------------------------------------------------------------------------------- /app/migrations/__pycache__/0002_auto_20190209_1152.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codersamir/django_contacts/HEAD/app/migrations/__pycache__/0002_auto_20190209_1152.cpython-37.pyc -------------------------------------------------------------------------------- /app/migrations/__pycache__/0003_auto_20190217_2103.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codersamir/django_contacts/HEAD/app/migrations/__pycache__/0003_auto_20190217_2103.cpython-37.pyc -------------------------------------------------------------------------------- /app/migrations/__pycache__/0004_remove_contact_manager.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codersamir/django_contacts/HEAD/app/migrations/__pycache__/0004_remove_contact_manager.cpython-37.pyc -------------------------------------------------------------------------------- /static/css/admin.css: -------------------------------------------------------------------------------- 1 | #header,caption{ 2 | background:#29a7a6 !important; 3 | } 4 | 5 | .breadcrumbs,h2,[type="submit"]{ 6 | background:#07bdbde1 !important; 7 | color:white !important; 8 | } -------------------------------------------------------------------------------- /templates/404.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | {% block title %} 3 | 404 Error 4 | {% endblock title %} 5 | {% block content %} 6 |
7 |

404 (Page not found)

8 | 9 |
10 | {% endblock content %} 11 | -------------------------------------------------------------------------------- /templates/500.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | {% block title %} 3 | 500 Error 4 | {% endblock title %} 5 | {% block content %} 6 |
7 |

500 (Internal Server Problem)

8 | 9 |
10 | {% endblock content %} 11 | -------------------------------------------------------------------------------- /templates/admin/base_site.html: -------------------------------------------------------------------------------- 1 | {% extends 'admin/base.html' %} 2 | {% load static %} 3 | {% block branding %} 4 |

5 | Contacts Project 6 |

7 | {% endblock branding %} 8 | 9 | {% block extrastyle %} 10 | 11 | {% endblock extrastyle %} -------------------------------------------------------------------------------- /templates/partials/_message.html: -------------------------------------------------------------------------------- 1 | {% if messages %} 2 | {% for message in messages %} 3 |
4 | 10 |
11 | {% endfor %} 12 | {% endif %} -------------------------------------------------------------------------------- /app/migrations/0004_remove_contact_manager.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.1.5 on 2019-02-17 15:35 2 | 3 | from django.db import migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('app', '0003_auto_20190217_2103'), 10 | ] 11 | 12 | operations = [ 13 | migrations.RemoveField( 14 | model_name='contact', 15 | name='manager', 16 | ), 17 | ] 18 | -------------------------------------------------------------------------------- /contacts/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for contacts project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/2.1/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'contacts.settings') 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /app/migrations/0002_auto_20190209_1152.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.1.5 on 2019-02-09 06:07 2 | 3 | import datetime 4 | from django.db import migrations, models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('app', '0001_initial'), 11 | ] 12 | 13 | operations = [ 14 | migrations.AlterField( 15 | model_name='contact', 16 | name='date_added', 17 | field=models.DateTimeField(default=datetime.datetime.now), 18 | ), 19 | ] 20 | -------------------------------------------------------------------------------- /templates/registration/logged_out.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% block title %} 3 | Logout 4 | {% endblock title %} 5 | 6 | {% block content %} 7 |
8 |

Logout

9 |
10 |
11 |
12 |

13 | You have been logged out.
14 | You can log in again using this link! 15 |

16 |
17 | 18 | 19 | {% endblock content %} -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | astroid==2.1.0 2 | autopep8==1.4.3 3 | colorama==0.4.1 4 | defusedxml==0.5.0 5 | diff-match-patch==20181111 6 | Django==2.1.5 7 | django-crispy-forms==1.7.2 8 | django-import-export==1.2.0 9 | et-xmlfile==1.0.1 10 | isort==4.3.4 11 | jdcal==1.4 12 | lazy-object-proxy==1.3.1 13 | mccabe==0.6.1 14 | odfpy==1.4.0 15 | openpyxl==2.6.0 16 | Pillow==5.4.1 17 | pycodestyle==2.5.0 18 | pylint==2.2.2 19 | pytz==2018.9 20 | PyYAML==3.13 21 | six==1.12.0 22 | tablib==0.12.1 23 | unicodecsv==0.14.1 24 | wrapt==1.11.1 25 | xlrd==1.2.0 26 | xlwt==1.3.0 -------------------------------------------------------------------------------- /contacts/urls.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from django.urls import path, include 3 | from django.conf import settings 4 | from django.conf.urls.static import static 5 | urlpatterns = [ 6 | path('admin/', admin.site.urls), 7 | path('', include('app.urls')), 8 | path('',include('django.contrib.auth.urls')), 9 | ]+static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) 10 | 11 | # Customizing admin texts 12 | admin.site.site_header = 'Contacts' 13 | admin.site.index_title = 'Welcome to project' 14 | admin.site.site_title = 'Control Panel' 15 | -------------------------------------------------------------------------------- /manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import sys 4 | 5 | if __name__ == '__main__': 6 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'contacts.settings') 7 | try: 8 | from django.core.management import execute_from_command_line 9 | except ImportError as exc: 10 | raise ImportError( 11 | "Couldn't import Django. Are you sure it's installed and " 12 | "available on your PYTHONPATH environment variable? Did you " 13 | "forget to activate a virtual environment?" 14 | ) from exc 15 | execute_from_command_line(sys.argv) 16 | -------------------------------------------------------------------------------- /app/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from django.contrib.auth.models import Group 3 | from .models import Contact 4 | from import_export.admin import ImportExportModelAdmin 5 | 6 | class ContactAdmin(ImportExportModelAdmin): 7 | list_display = ('id', 'name', 'gender', 'email', 'info', 'phone') 8 | list_display_links = ('id','name') 9 | list_editable = ('info',) 10 | list_per_page = 10 11 | search_fields = ('name', 'gender', 'email', 'info', 'phone') 12 | list_filter = ('gender', 'date_added') 13 | 14 | 15 | admin.site.register(Contact, ContactAdmin) 16 | admin.site.unregister(Group) 17 | -------------------------------------------------------------------------------- /templates/registration/login.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% load crispy_forms_tags %} 3 | {% block title %} 4 | Login 5 | {% endblock title %} 6 | 7 | {% block content %} 8 |
9 |

Login

10 |
11 |
12 |
13 |
14 | {% csrf_token %} 15 | {{form|crispy}} 16 | 17 |
18 |
19 | 20 | 21 | {% endblock content %} -------------------------------------------------------------------------------- /templates/registration/signup.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% load crispy_forms_tags %} 3 | {% block title %} 4 | Sign Up 5 | {% endblock title %} 6 | 7 | {% block content %} 8 |
9 |

Sign Up

10 |
11 |
12 |
13 |
14 | {% csrf_token %} 15 | {{form|crispy}} 16 | 17 |
18 |
19 | 20 | 21 | {% endblock content %} -------------------------------------------------------------------------------- /templates/create.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% load crispy_forms_tags %} 3 | {% block title %} 4 | Create a New Contact 5 | {% endblock title %} 6 | 7 | {% block content %} 8 |
9 |

Create a New Contact

10 |
11 |
12 |
13 |
14 | {% csrf_token %} 15 | {{form|crispy}} 16 | 17 |
18 |
19 | 20 | 21 | {% endblock content %} -------------------------------------------------------------------------------- /app/migrations/0005_contact_manager.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.1.5 on 2019-02-19 02:36 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 | ('app', '0004_remove_contact_manager'), 13 | ] 14 | 15 | operations = [ 16 | migrations.AddField( 17 | model_name='contact', 18 | name='manager', 19 | field=models.ForeignKey(default=None, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL), 20 | ), 21 | ] 22 | -------------------------------------------------------------------------------- /templates/index.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | {% load static %} 3 | {% block title %} 4 | My Contacts 5 | {% endblock title %} 6 | 7 | {% block content %} 8 | 9 |
10 |

Here are your contacts

11 |
12 |
13 |
14 | {% if contacts %} 15 | {% for contact in contacts %} 16 | {% include 'partials/_card.html' %} 17 | 18 | {% endfor %} 19 | {% else %} 20 |

You have not save any contacts yet!

21 | {% endif %} 22 |
23 | 24 | 25 | 26 | {% endblock content %} -------------------------------------------------------------------------------- /templates/search.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | {% load static %} 3 | {% block title %} 4 | Search Results for {{search_term}} 5 | {% endblock title %} 6 | {% block content %} 7 | 8 |
9 |

Search results for "{{search_term}}"

10 |
11 |
12 | 13 |
14 | {% if contacts %} 15 | {% for contact in contacts %} 16 | {% include 'partials/_card.html' %} 17 | 18 | {% endfor %} 19 | {% else %} 20 |

No search results!

21 | {% endif %} 22 |
23 | 24 | {% endblock content %} -------------------------------------------------------------------------------- /app/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | from . import views 3 | urlpatterns = [ 4 | # path('', views.home, name="home"), 5 | path('', views.HomePageView.as_view(), name="home"), 6 | # path('detail//', views.detail, name="detail"), 7 | path('detail//', views.ContactDetailView.as_view(), name="detail"), 8 | path('search/', views.search, name="search"), 9 | path('contacts/create', views.ContactCreateView.as_view(), name="create"), 10 | path('contacts/update/', 11 | views.ContactUpdateView.as_view(), name="update"), 12 | path('contacts/delete/', 13 | views.ContactDeleteView.as_view(), name="delete"), 14 | path('signup/', views.SignUpView.as_view(), name="signup"), 15 | ] 16 | -------------------------------------------------------------------------------- /app/migrations/0003_auto_20190217_2103.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.1.5 on 2019-02-17 15:18 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 | ('app', '0002_auto_20190209_1152'), 13 | ] 14 | 15 | operations = [ 16 | migrations.AlterModelOptions( 17 | name='contact', 18 | options={'ordering': ['-id']}, 19 | ), 20 | migrations.AddField( 21 | model_name='contact', 22 | name='manager', 23 | field=models.ForeignKey(default=None, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL), 24 | ), 25 | ] 26 | -------------------------------------------------------------------------------- /app/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | 3 | # Create your models here. 4 | from django.utils.timezone import datetime 5 | from django.contrib.auth.models import User 6 | 7 | class Contact(models.Model): 8 | manager = models.ForeignKey(User, on_delete=models.CASCADE,default=None) 9 | name = models.CharField(max_length=20) 10 | email = models.EmailField(max_length=100) 11 | phone = models.IntegerField() 12 | info = models.CharField(max_length=30) 13 | gender = models.CharField(max_length=50, choices=( 14 | ('male', 'Male'), 15 | ('feamle', 'Female') 16 | )) 17 | image = models.ImageField(upload_to='images/', blank=True) 18 | date_added = models.DateTimeField(default=datetime.now) 19 | 20 | def __str__(self): 21 | return self.name 22 | 23 | class Meta: 24 | ordering = ['-id'] 25 | -------------------------------------------------------------------------------- /templates/update.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% load crispy_forms_tags %} 3 | {% block title %} 4 | {% if contact.manager == request.user %} 5 | Update {{contact}} 6 | 7 | {% else %} 8 | You don't have access to this page! 9 | {% endif %} 10 | 11 | {% endblock title %} 12 | 13 | {% block content %} 14 | {% if contact.manager == request.user %} 15 |
16 |

Update {{contact}}

17 |
18 |
19 |
20 |
21 | {% csrf_token %} 22 | {{form|crispy}} 23 | 24 |
25 |
26 | 27 | {% else %} 28 |
29 |

You don't have access to this page!

30 |
31 | {% endif %} 32 | 33 | {% endblock content %} -------------------------------------------------------------------------------- /templates/delete.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | {% load crispy_forms_tags %} 3 | {% block title %} 4 | 5 | 6 | {% if contact.manager == request.user %} 7 | Delete {{contact}} 8 | {% else %} 9 | You don't have access to this page! 10 | {% endif %} 11 | 12 | {% endblock title %} 13 | 14 | {% block content %} 15 | {% if contact.manager == request.user %} 16 |
17 |

Delete {{contact}}

18 |
19 |
20 |
21 |
22 | {% csrf_token %} 23 | {{form|crispy}} 24 | 25 |
26 |
27 | 28 | {% else %} 29 |
30 |

You don't have access to this page!

31 |
32 | {% endif %} 33 | 34 | {% endblock content %} -------------------------------------------------------------------------------- /app/migrations/0001_initial.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 2.1.5 on 2019-02-06 12:46 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | initial = True 9 | 10 | dependencies = [ 11 | ] 12 | 13 | operations = [ 14 | migrations.CreateModel( 15 | name='Contact', 16 | fields=[ 17 | ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), 18 | ('name', models.CharField(max_length=20)), 19 | ('email', models.EmailField(max_length=100)), 20 | ('phone', models.IntegerField()), 21 | ('info', models.CharField(max_length=30)), 22 | ('gender', models.CharField(choices=[('male', 'Male'), ('feamle', 'Female')], max_length=50)), 23 | ('image', models.ImageField(blank=True, upload_to='images/')), 24 | ('date_added', models.DateField(auto_now_add=True)), 25 | ], 26 | ), 27 | ] 28 | -------------------------------------------------------------------------------- /templates/detail.html: -------------------------------------------------------------------------------- 1 | {% extends 'base.html' %} 2 | {% load static %} 3 | {% block title %} 4 | 5 | {% if contact.manager == request.user %} 6 | {{contact.name}} 7 | {% else %} 8 | You don't have access to this page! 9 | {% endif %} 10 | {% endblock title %} 11 | {% block content %} 12 | {% if contact.manager == request.user %} 13 | 14 |
15 |

{{contact.name}}

16 |
17 |
18 |
19 | 20 | {% include 'partials/_card.html' %} 21 |
22 |
23 |
Date Added:   {{contact.date_added}}
24 |

25 | 26 |   Update 27 | 28 |      29 | 30 |   Delete 31 | 32 |

33 |
34 | 35 | {% else %} 36 |
37 |

You don't have access to this page!

38 |
39 | {% endif %} 40 | {% endblock content %} 41 | -------------------------------------------------------------------------------- /templates/partials/_card.html: -------------------------------------------------------------------------------- 1 | {% load static %} {% if contact.gender == 'male' %} 2 | 3 |
4 | 12 | 17 |
18 |

19 | 20 | {{ contact.email }} 21 |

22 |

23 | 24 | {{ contact.phone }} 25 |

26 |

{{ contact.info }}

27 |
28 |
29 | 30 | {% else %} 31 |
32 | 40 | 45 |
46 |

47 | 48 | {{ contact.email }} 49 |

50 |

51 | 52 | {{ contact.phone }} 53 |

54 |

{{ contact.info }}

55 |
56 |
57 | {% endif %} 58 | -------------------------------------------------------------------------------- /templates/base.html: -------------------------------------------------------------------------------- 1 | {% load static %} 2 | 3 | 4 | 5 | 6 | 7 | 11 | 12 | 13 | 17 | 18 | 19 | 20 | 21 | 25 | 29 | 30 | 31 | {% block title %} 32 | 33 | {% endblock title %} 34 | 35 | 36 | 37 | 38 | 39 | 72 | 73 |
74 | {% include "partials/_message.html" %} 75 | {% block content %} 76 | 77 | {% endblock content %} 78 | 79 | 80 |
81 |

© My Contacts 2019

82 |
83 | 84 | 85 | 86 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /static/css/main.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --back: #29a7a6; 3 | /* --logo: #ff70a6; */ 4 | --girl: #e64298; 5 | --boy: #2874dd; 6 | } 7 | body { 8 | font-family: Lato, sans-serif; 9 | } 10 | 11 | /* Navbar Styles */ 12 | 13 | nav { 14 | font-weight: light; 15 | display: flex; 16 | justify-content: space-around; 17 | background-color: var(--back); 18 | align-items: center; 19 | padding-top: 12px; 20 | padding-bottom: 12px; 21 | box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2); 22 | } 23 | .logo { 24 | font-size: 30px; 25 | letter-spacing: 1px; 26 | /* background: var(--logo); */ 27 | color: white; 28 | padding: 2px 12px; 29 | border-radius: 8px; 30 | font-family: cursive; 31 | } 32 | .logo:hover { 33 | color: white; 34 | text-decoration: none; 35 | } 36 | .search-box { 37 | border-radius: 0px !important; 38 | width: 250px; 39 | border: none !important; 40 | background-color: #f2f3f5 !important; 41 | box-shadow: 0 1px 8px 0 rgba(0, 0, 0, 0.2); 42 | } 43 | /* Navbar Styles end */ 44 | 45 | /* Card Styles */ 46 | 47 | .card { 48 | box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2); 49 | transition: 0.3s; 50 | min-width: 250px; 51 | box-sizing: border-box; 52 | } 53 | 54 | .card:hover { 55 | box-shadow: 0 8px 16px 0 rgba(0, 0, 0, 0.2); 56 | } 57 | img { 58 | height: 130px !important; 59 | } 60 | .card-header { 61 | font-size: 18px; 62 | letter-spacing: 0.5px; 63 | text-transform: uppercase; 64 | } 65 | .header-link:hover { 66 | text-decoration: none; 67 | } 68 | .boy-card .card-header { 69 | background-color: var(--boy); 70 | } 71 | .boy-card .card-body, 72 | .boy-card .card-body p a { 73 | color: var(--boy); 74 | } 75 | .girl-card .card-header { 76 | background-color: var(--girl); 77 | } 78 | .girl-card .card-body, 79 | .girl-card .card-body p a { 80 | color: var(--girl); 81 | } 82 | .card-body p { 83 | cursor: pointer; 84 | } 85 | /* Card Styles end */ 86 | 87 | /* Main Section */ 88 | .main-part { 89 | display: flex; 90 | flex-wrap: wrap; 91 | justify-content: space-evenly; 92 | } 93 | 94 | /* Main Section ends */ 95 | 96 | /* footer style */ 97 | footer { 98 | background-color: var(--back); 99 | color: white; 100 | font-size: 18px; 101 | border-bottom: 3px solid var(--back); 102 | } 103 | 104 | /* footer style ends*/ 105 | 106 | /* Media Queries */ 107 | @media only screen and (max-width: 768px) { 108 | /* navbar style */ 109 | nav { 110 | flex-direction: column; 111 | } 112 | 113 | .logo { 114 | font-size: 22px !important; 115 | } 116 | .feature-link { 117 | margin-top: 5px !important; 118 | margin-bottom: 5px !important; 119 | } 120 | /* navbar style ends */ 121 | 122 | /* card styles */ 123 | .card-header { 124 | font-size: 90% !important; 125 | } 126 | .card-body p { 127 | font-size: 13px; 128 | margin-bottom: 6px; 129 | } 130 | .card-body { 131 | padding: 8px 8px 0 8px; 132 | } 133 | /* card styles end */ 134 | 135 | /* footer style */ 136 | footer { 137 | font-size: 98% !important; 138 | font-weight: light; 139 | letter-spacing: 1px; 140 | } 141 | /* footer style ends */ 142 | } 143 | /* Media Queries Ends*/ 144 | -------------------------------------------------------------------------------- /app/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render, get_object_or_404, redirect 2 | from .models import Contact 3 | from django.views.generic import ListView, DetailView 4 | from django.db.models import Q 5 | from django.views.generic.edit import CreateView, UpdateView, DeleteView 6 | from django.contrib.auth.forms import UserCreationForm 7 | from django.contrib.auth.mixins import LoginRequiredMixin 8 | from django.contrib.auth.decorators import login_required 9 | from django.urls import reverse_lazy 10 | from django.contrib import messages 11 | 12 | # def home(request): 13 | # context = { 14 | # 'contacts': Contact.objects.all() 15 | # } 16 | # return render(request, 'index.html', context) 17 | 18 | 19 | # def detail(request, id): 20 | # context = { 21 | # 'contact': get_object_or_404(Contact, pk=id) 22 | # } 23 | # return render(request, 'detail.html', context) 24 | 25 | 26 | class HomePageView(LoginRequiredMixin, ListView): 27 | template_name = 'index.html' 28 | model = Contact 29 | context_object_name = 'contacts' 30 | 31 | def get_queryset(self): 32 | contacts = super().get_queryset() 33 | return contacts.filter(manager=self.request.user) 34 | 35 | 36 | class ContactDetailView(LoginRequiredMixin, DetailView): 37 | template_name = 'detail.html' 38 | model = Contact 39 | context_object_name = 'contact' 40 | 41 | 42 | @login_required 43 | def search(request): 44 | if request.GET: 45 | search_term = request.GET['search_term'] 46 | search_results = Contact.objects.filter( 47 | Q(name__icontains=search_term) | 48 | Q(email__icontains=search_term) | 49 | Q(info__icontains=search_term) | 50 | Q(phone__iexact=search_term) 51 | ) 52 | context = { 53 | 'search_term': search_term, 54 | 'contacts': search_results.filter(manager=request.user) 55 | } 56 | return render(request, 'search.html', context) 57 | else: 58 | return redirect('home') 59 | 60 | 61 | class ContactCreateView(LoginRequiredMixin, CreateView): 62 | model = Contact 63 | template_name = 'create.html' 64 | fields = ['name', 'email', 'phone', 'info', 'gender', 'image'] 65 | 66 | def form_valid(self, form): 67 | instance = form.save(commit=False) 68 | instance.manager = self.request.user 69 | instance.save() 70 | messages.success( 71 | self.request, 'Your contact has been successfully created!') 72 | return redirect('home') 73 | 74 | 75 | class ContactUpdateView(LoginRequiredMixin, UpdateView): 76 | model = Contact 77 | template_name = 'update.html' 78 | fields = ['name', 'email', 'phone', 'info', 'gender', 'image'] 79 | 80 | def form_valid(self, form): 81 | instance = form.save() 82 | messages.success( 83 | self.request, 'Your contact has been successfully updated!') 84 | return redirect('detail', instance.pk) 85 | 86 | 87 | class ContactDeleteView(LoginRequiredMixin, DeleteView): 88 | model = Contact 89 | template_name = 'delete.html' 90 | success_url = '/' 91 | 92 | def delete(self, request, *args, **kwargs): 93 | messages.success( 94 | self.request, 'Your contact has been successfully deleted!') 95 | return super().delete(self, request, *args, **kwargs) 96 | 97 | 98 | class SignUpView(CreateView): 99 | form_class = UserCreationForm 100 | template_name = 'registration/signup.html' 101 | success_url = reverse_lazy('home') 102 | -------------------------------------------------------------------------------- /contacts/settings.py: -------------------------------------------------------------------------------- 1 | """ 2 | Django settings for contacts project. 3 | 4 | Generated by 'django-admin startproject' using Django 2.1.5. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/2.1/topics/settings/ 8 | 9 | For the full list of settings and their values, see 10 | https://docs.djangoproject.com/en/2.1/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/2.1/howto/deployment/checklist/ 21 | 22 | # SECURITY WARNING: keep the secret key used in production secret! 23 | SECRET_KEY = '0bnnld8r@b@m46fqk_f@$7s*-(g#7mw*2_t8bllsio-1t*vh^a' 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 | 'app', 41 | 'crispy_forms', 42 | 'import_export', 43 | ] 44 | 45 | MIDDLEWARE = [ 46 | 'django.middleware.security.SecurityMiddleware', 47 | 'django.contrib.sessions.middleware.SessionMiddleware', 48 | 'django.middleware.common.CommonMiddleware', 49 | 'django.middleware.csrf.CsrfViewMiddleware', 50 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 51 | 'django.contrib.messages.middleware.MessageMiddleware', 52 | 'django.middleware.clickjacking.XFrameOptionsMiddleware', 53 | ] 54 | 55 | ROOT_URLCONF = 'contacts.urls' 56 | 57 | TEMPLATES = [ 58 | { 59 | 'BACKEND': 'django.template.backends.django.DjangoTemplates', 60 | 'DIRS': [os.path.join(BASE_DIR, 'templates')], 61 | 'APP_DIRS': True, 62 | 'OPTIONS': { 63 | 'context_processors': [ 64 | 'django.template.context_processors.debug', 65 | 'django.template.context_processors.request', 66 | 'django.contrib.auth.context_processors.auth', 67 | 'django.contrib.messages.context_processors.messages', 68 | ], 69 | }, 70 | }, 71 | ] 72 | 73 | WSGI_APPLICATION = 'contacts.wsgi.application' 74 | 75 | 76 | # Database 77 | # https://docs.djangoproject.com/en/2.1/ref/settings/#databases 78 | 79 | DATABASES = { 80 | 'default': { 81 | 'ENGINE': 'django.db.backends.sqlite3', 82 | 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), 83 | } 84 | } 85 | 86 | 87 | # Password validation 88 | # https://docs.djangoproject.com/en/2.1/ref/settings/#auth-password-validators 89 | 90 | AUTH_PASSWORD_VALIDATORS = [ 91 | { 92 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', 93 | }, 94 | { 95 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 96 | }, 97 | { 98 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', 99 | }, 100 | { 101 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', 102 | }, 103 | ] 104 | 105 | 106 | # Internationalization 107 | # https://docs.djangoproject.com/en/2.1/topics/i18n/ 108 | 109 | LANGUAGE_CODE = 'en-us' 110 | 111 | TIME_ZONE = 'Asia/Kathmandu' 112 | 113 | USE_I18N = True 114 | 115 | USE_L10N = True 116 | 117 | USE_TZ = True 118 | 119 | 120 | # Static files (CSS, JavaScript, Images) 121 | # https://docs.djangoproject.com/en/2.1/howto/static-files/ 122 | 123 | STATIC_URL = '/static/' 124 | STATICFILES_DIRS = ( 125 | os.path.join(BASE_DIR, 'static'), 126 | ) 127 | 128 | # Setting media files 129 | MEDIA_URL = '/media/' 130 | MEDIA_ROOT = os.path.join(BASE_DIR, 'media') 131 | 132 | # Crispy forms 133 | CRISPY_TEMPLATE_PACK = 'bootstrap4' 134 | 135 | # for authentication 136 | LOGIN_URL = 'login' 137 | LOGOUT_URL = 'logout' 138 | LOGIN_REDIRECT_URL = 'home' 139 | --------------------------------------------------------------------------------