├── .gitignore ├── README.md ├── assets ├── Answer_accepted.png ├── Darkmode.png ├── Homepage.png ├── Lightmode.png ├── Profile.png ├── Question.png ├── Self_answer.png ├── askQuestion.png └── edit_profile.png ├── requirements.txt └── stackoverflow ├── main ├── __init__.py ├── __pycache__ │ ├── __init__.cpython-36.pyc │ └── __init__.cpython-38.pyc ├── admin.py ├── apps.py ├── migrations │ ├── __init__.py │ └── __pycache__ │ │ ├── 0001_initial.cpython-38.pyc │ │ ├── 0002_auto_20201214_1613.cpython-38.pyc │ │ ├── 0002_auto_20201214_1621.cpython-38.pyc │ │ ├── __init__.cpython-36.pyc │ │ └── __init__.cpython-38.pyc ├── models.py ├── templates │ └── main │ │ ├── askquestion.html │ │ ├── base.html │ │ ├── profile.html │ │ ├── question-single.html │ │ └── questions.html ├── tests.py ├── urls.py ├── utils.py └── views.py ├── manage.py ├── media └── default_image.png ├── stackoverflow ├── __init__.py ├── __pycache__ │ ├── __init__.cpython-36.pyc │ └── __init__.cpython-38.pyc ├── asgi.py ├── settings.py ├── urls.py └── wsgi.py ├── static ├── css │ ├── editprofile.css │ ├── home.css │ └── main.css └── question │ ├── home.css │ └── main.css └── userauth ├── __init__.py ├── __pycache__ ├── __init__.cpython-36.pyc └── __init__.cpython-38.pyc ├── admin.py ├── apps.py ├── forms.py ├── migrations ├── __init__.py └── __pycache__ │ ├── 0001_initial.cpython-36.pyc │ ├── 0001_initial.cpython-38.pyc │ ├── 0002_auto_20201116_1153.cpython-36.pyc │ ├── 0002_auto_20201116_1153.cpython-38.pyc │ ├── 0002_auto_20201118_1548.cpython-36.pyc │ ├── 0002_auto_20201118_1548.cpython-38.pyc │ ├── 0003_auto_20201118_1948.cpython-36.pyc │ ├── 0003_auto_20201118_1948.cpython-38.pyc │ ├── 0004_auto_20201118_1808.cpython-36.pyc │ ├── 0004_auto_20201118_1808.cpython-38.pyc │ ├── 0005_auto_20201123_1931.cpython-38.pyc │ ├── __init__.cpython-36.pyc │ └── __init__.cpython-38.pyc ├── models.py ├── templates └── userauth │ ├── editprofile.html │ ├── login.html │ ├── logout.html │ ├── signup.html │ └── user_active_email.html ├── tests.py ├── tokens.py ├── urls.py └── views.py /.gitignore: -------------------------------------------------------------------------------- 1 | .env 2 | .dbsqlite3 3 | # media/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

3 |

4 | 5 |

StackOverflow Clone 6 |

7 | 8 |       [![](https://img.shields.io/badge/Made_with-Django-blue?style=for-the-badge&logo=Django)](https://www.djangoproject.com/) 9 |   10 | [![](https://img.shields.io/badge/Made_with-sqlite3-blue?style=for-the-badge&logo=SQLite)](https://docs.python.org/2/library/sqlite3.html) 11 |   12 | [![](https://img.shields.io/badge/IDE-Visual_Studio_Code-blue?style=for-the-badge&logo=visual-studio-code)](https://code.visualstudio.com/ "Visual Studio Code") 13 | 14 | 15 |

About

16 |

17 | The aim of the project is to implement all the basic and necesssary functionalities of Stackoverflow. 18 |

19 | For developers, by developers 20 |

21 | Stack Overflow is an open community for anyone that codes. They help you get answers to your toughest coding questions, share knowledge with your coworkers in private, and find your next dream job. 22 |

23 | 24 | ----------------------------------- 25 | 26 | ### Preview 27 | 28 |

29 | 30 |

31 | 32 | 33 | ----------------------------------- 34 | 35 | ### Question-Accepted answer 36 |

37 | 38 |

39 |

40 | 41 |

42 | 43 | 44 | ----------------------------------- 45 | 46 | ### LightMode-Darkmode 47 |

48 | 49 |

50 |

51 | 52 |

53 | 54 | 55 | ----------------------------------- 56 | 57 | ### Ask Question 58 |

59 | 60 |

61 | 62 | 63 | ----------------------------------- 64 | 65 | ### Profile-Edit Profile 66 |

67 | 68 |

69 |

70 | 71 |

72 | 73 | 74 | ----------------------------------- 75 | 76 | ### 🚀 Features 77 | 78 |

79 |

89 |

90 | 91 | 92 | ----------------------------------- 93 | ### 💻 Tech stack 94 | `Backend` : Django
95 | `Database` : SQLite
96 | `Frontend` : CSS, HTML, Bootstrap, jQuery
97 | 98 | ----------------------------------- 99 | 100 | ### :guide_dog: Installation Guide 101 | 102 | A step by step series of examples that tell you how to get a development env running 103 | 104 | In your cmd: 105 | 106 | ``` 107 | https://github.com/RugvedB/Stackoverflow-Clone 108 | ``` 109 | 110 | Then, 111 | 112 | ``` 113 | cd Stackoverflow-Clone 114 | pip install -r requirements.txt 115 | python manage.py makemigrations 116 | python manage.py migrate 117 | ``` 118 | 119 | Next 120 | 121 | 122 | Create a .env file, enter your credentials for following fields 123 | 124 | ``` 125 | EMAIL_HOST = ENTER YOUR EMAIL HOST 126 | EMAIL_PORT = ENTER YOUR EMAIL PORT 127 | EMAIL_HOST_USER = ENTER YOUR EMAIL ID 128 | DEFAULT_FROM_EMAIL = ENTER YOUR EMAIL ID 129 | EMAIL_HOST_PASSWORD = ENTER YOUR EMAIL PASSWORD 130 | SECRET_KEY = ENTER YOUR SECRET_KEY 131 | ``` 132 | Then 133 | 134 | ``` 135 | python manage.py runserver 136 | ``` 137 | 138 | You are done with the setup now! 139 | 140 | ------------------------------------------ 141 | 142 | ### 📝 To-do List 143 | 144 | - [ ] Use ajax for improving user experience. 145 | - [ ] Add search bar for user,questions,tags etc. 146 | - [ ] Create App for the same. 147 | 148 | ------------------------------------------ 149 | 150 | 151 | ### :page_with_curl: Acknowledgements & References 152 | 153 | - Django Documentation - https://docs.djangoproject.com/en/3.1/ 154 | - Stackoverflow - http://stackoverflow.com/ 155 | - Javascript - https://developer.mozilla.org/en-US/docs/Web/JavaScript 156 | 157 | ----------------------------------- 158 | 159 |

Developed with :heart: by Tushar and Rugved

160 | -------------------------------------------------------------------------------- /assets/Answer_accepted.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RugvedB/Stackoverflow-Clone/f2540f8e7812ad55b0e7201d6e669356850d1d0b/assets/Answer_accepted.png -------------------------------------------------------------------------------- /assets/Darkmode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RugvedB/Stackoverflow-Clone/f2540f8e7812ad55b0e7201d6e669356850d1d0b/assets/Darkmode.png -------------------------------------------------------------------------------- /assets/Homepage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RugvedB/Stackoverflow-Clone/f2540f8e7812ad55b0e7201d6e669356850d1d0b/assets/Homepage.png -------------------------------------------------------------------------------- /assets/Lightmode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RugvedB/Stackoverflow-Clone/f2540f8e7812ad55b0e7201d6e669356850d1d0b/assets/Lightmode.png -------------------------------------------------------------------------------- /assets/Profile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RugvedB/Stackoverflow-Clone/f2540f8e7812ad55b0e7201d6e669356850d1d0b/assets/Profile.png -------------------------------------------------------------------------------- /assets/Question.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RugvedB/Stackoverflow-Clone/f2540f8e7812ad55b0e7201d6e669356850d1d0b/assets/Question.png -------------------------------------------------------------------------------- /assets/Self_answer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RugvedB/Stackoverflow-Clone/f2540f8e7812ad55b0e7201d6e669356850d1d0b/assets/Self_answer.png -------------------------------------------------------------------------------- /assets/askQuestion.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RugvedB/Stackoverflow-Clone/f2540f8e7812ad55b0e7201d6e669356850d1d0b/assets/askQuestion.png -------------------------------------------------------------------------------- /assets/edit_profile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RugvedB/Stackoverflow-Clone/f2540f8e7812ad55b0e7201d6e669356850d1d0b/assets/edit_profile.png -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RugvedB/Stackoverflow-Clone/f2540f8e7812ad55b0e7201d6e669356850d1d0b/requirements.txt -------------------------------------------------------------------------------- /stackoverflow/main/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RugvedB/Stackoverflow-Clone/f2540f8e7812ad55b0e7201d6e669356850d1d0b/stackoverflow/main/__init__.py -------------------------------------------------------------------------------- /stackoverflow/main/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RugvedB/Stackoverflow-Clone/f2540f8e7812ad55b0e7201d6e669356850d1d0b/stackoverflow/main/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /stackoverflow/main/__pycache__/__init__.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RugvedB/Stackoverflow-Clone/f2540f8e7812ad55b0e7201d6e669356850d1d0b/stackoverflow/main/__pycache__/__init__.cpython-38.pyc -------------------------------------------------------------------------------- /stackoverflow/main/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from main.models import Questions, Answer, Tags 3 | 4 | class QuestionsAdmin(admin.ModelAdmin): 5 | list_filter = ('is_answered',) 6 | 7 | class AnswerAdmin(admin.ModelAdmin): 8 | list_filter = ('is_accepted',) 9 | 10 | admin.site.register(Questions,QuestionsAdmin) 11 | admin.site.register(Answer, AnswerAdmin) 12 | admin.site.register(Tags) 13 | 14 | 15 | -------------------------------------------------------------------------------- /stackoverflow/main/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class MainConfig(AppConfig): 5 | name = 'main' 6 | -------------------------------------------------------------------------------- /stackoverflow/main/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RugvedB/Stackoverflow-Clone/f2540f8e7812ad55b0e7201d6e669356850d1d0b/stackoverflow/main/migrations/__init__.py -------------------------------------------------------------------------------- /stackoverflow/main/migrations/__pycache__/0001_initial.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RugvedB/Stackoverflow-Clone/f2540f8e7812ad55b0e7201d6e669356850d1d0b/stackoverflow/main/migrations/__pycache__/0001_initial.cpython-38.pyc -------------------------------------------------------------------------------- /stackoverflow/main/migrations/__pycache__/0002_auto_20201214_1613.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RugvedB/Stackoverflow-Clone/f2540f8e7812ad55b0e7201d6e669356850d1d0b/stackoverflow/main/migrations/__pycache__/0002_auto_20201214_1613.cpython-38.pyc -------------------------------------------------------------------------------- /stackoverflow/main/migrations/__pycache__/0002_auto_20201214_1621.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RugvedB/Stackoverflow-Clone/f2540f8e7812ad55b0e7201d6e669356850d1d0b/stackoverflow/main/migrations/__pycache__/0002_auto_20201214_1621.cpython-38.pyc -------------------------------------------------------------------------------- /stackoverflow/main/migrations/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RugvedB/Stackoverflow-Clone/f2540f8e7812ad55b0e7201d6e669356850d1d0b/stackoverflow/main/migrations/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /stackoverflow/main/migrations/__pycache__/__init__.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RugvedB/Stackoverflow-Clone/f2540f8e7812ad55b0e7201d6e669356850d1d0b/stackoverflow/main/migrations/__pycache__/__init__.cpython-38.pyc -------------------------------------------------------------------------------- /stackoverflow/main/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | from datetime import datetime 3 | from django.utils import timezone 4 | from django.conf import settings 5 | # from userauth.models import User 6 | medium_len = 100 7 | long_len = 255 8 | 9 | 10 | class Tags(models.Model): 11 | tag_word = models.CharField(max_length=medium_len, unique = True) 12 | 13 | class Questions(models.Model): 14 | title = models.CharField(max_length=long_len) 15 | ques_content = models.TextField() 16 | tags = models.ManyToManyField(Tags) 17 | upvotes = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name='user_upvote') 18 | downvotes = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name='user_downvote') 19 | answers = models.ManyToManyField('main.Answer', related_name='answers') 20 | author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, blank=False) 21 | views = models.IntegerField(default=0) 22 | is_answered = models.BooleanField(default=False) 23 | created_at = models.DateTimeField(auto_now_add=True) 24 | updated_at = models.DateTimeField(auto_now=True) 25 | votes = models.IntegerField(default=0) 26 | has_accepted_answer = models.BooleanField(default=False) 27 | 28 | class Answer(models.Model): 29 | ans_content = models.TextField() 30 | answered_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, blank=False) 31 | question_to_ans = models.ForeignKey(Questions, on_delete=models.CASCADE, blank=False) 32 | upvotes = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name='user_a_upvote') 33 | downvotes = models.ManyToManyField(settings.AUTH_USER_MODEL, related_name='user_a_downvote') 34 | is_accepted = models.BooleanField(default=False) 35 | created_at = models.DateTimeField(auto_now_add=True) 36 | updated_at = models.DateTimeField(auto_now=True) 37 | votes = models.IntegerField(default=0) 38 | -------------------------------------------------------------------------------- /stackoverflow/main/templates/main/askquestion.html: -------------------------------------------------------------------------------- 1 | {% extends 'main/base.html' %} 2 | 3 | {% block content %} 4 | 5 | 12 | 13 | 14 |
15 |
16 | 17 |
18 |

Ask a public question

19 |
20 | 21 |
22 |
23 | 24 |
25 | {% csrf_token %} 26 |
27 |
28 |
Title
29 |

Be specific and imagine you’re asking a question to another person.

30 | 31 |
32 |
Body
33 |

Include all the information someone would need to answer your question.

34 | 35 | 38 |
39 |
Tags
40 |

Be specific and imagine you’re asking a question to another person.

41 | 42 | 43 |
44 | 45 | 46 |
47 | 48 | 56 | 57 |
58 |
59 | 60 | 61 |
62 | 63 | 64 |
65 | 66 |
67 | 68 |
69 |
70 |
Step 1: Draft Your Question
71 |

The community is here to help you with specific coding, algorithm, or language problems. 72 | Avoid asking opinion-based questions.

73 |
74 | 75 | 76 |
77 |
78 |
79 |

80 | 83 |

84 |
85 | 86 |
87 |
88 |
    89 |
  • Include details about your goal.
  • 90 | 91 |
  • Describe expected and actual results.
  • 92 | 93 |
  • any error messages.
  • 94 |
95 |
96 |
97 |
98 |
99 |
100 |

101 | 105 |

106 |
107 |
108 |
109 | Show what you’ve tried and tell us what you found (on this site or elsewhere) and why it didn’t meet your needs. You can get better answers when you provide research. 110 |
111 |
112 |
113 |
114 |
115 |

116 | 119 |

120 |
121 |
122 |
123 | When appropriate, share the minimum amount of code others need to reproduce your problem (also called a minimum, reproducible example) 124 |
125 |
126 |
127 |
128 | 129 | 130 | 131 | 132 |
133 |
134 |
135 |
136 | 137 | 138 |
139 | 140 | 141 | 142 | {% endblock %} 143 | 144 | 145 | 146 | -------------------------------------------------------------------------------- /stackoverflow/main/templates/main/base.html: -------------------------------------------------------------------------------- 1 | {% load static %} 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | Document 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 55 | 56 | 57 | 58 | 59 | 96 | 97 | 98 |
99 | 100 | {% if messages %} 101 | {% for message in messages %} 102 | 108 | {% endfor %} 109 | {% endif %} 110 |
111 | 112 | {% block content %} 113 | 114 | {% endblock %} 115 | 116 | -------------------------------------------------------------------------------- /stackoverflow/main/templates/main/profile.html: -------------------------------------------------------------------------------- 1 | {% extends 'main/base.html' %} 2 | 3 | {% block content %} 4 | 5 |
6 |
7 |
8 |
9 |
10 | ... 11 |
12 |
13 |
14 |
15 |
16 |
{{seeuser.name}}
17 | {% if showeditbutton %} 18 |

19 | {% endif %} 20 |

{{seeuser.about_me}}

21 |

Reputations: {{seeuser.reputation_score}}

22 |
23 |
24 |
25 |
26 |
27 | 28 | 29 | 30 |
31 |
32 |
33 |
Questions({{userques.count}})
34 |
35 | 48 | 49 |
50 | {% for q in userques %} 51 | 63 | {% endfor %} 64 |
65 | 66 |
67 | 68 |
69 | 70 |
71 |
Answers({{ansgiven.count}})
72 |
73 | 86 | 87 |
88 | {% for a in ansgiven %} 89 | 101 | {% endfor %} 102 |
103 | 104 |
105 |
106 | 107 |
108 | 109 | {% endblock %} -------------------------------------------------------------------------------- /stackoverflow/main/templates/main/question-single.html: -------------------------------------------------------------------------------- 1 | {% extends 'main/base.html' %} 2 | {% block content %} 3 | 4 | 5 |
6 |
7 | 8 | 9 |
10 | 11 |
12 | 13 |
14 | 15 | 16 |

{{q.title}}

17 |

Asked {{q.created_at}} Active Viewed {{q.views}} times

18 | 19 |
20 | 21 |
22 | 23 |
24 |
25 |
26 |
{{q.votes}}
27 |
28 |
29 |
30 | 31 |
32 | {{q.ques_content | safe | escape}} 33 | 34 |
35 | 36 | {% for t in q.tags.all %} 37 | 38 | {% endfor %} 39 |
40 |
41 |
42 | 43 | 44 | 45 | 46 |
47 | 48 |
49 |
50 | Asked on {{q.created_at}} 51 |
52 |
53 |
54 | ... 55 |
56 |
57 |

{{q.author.name}}
{{q.author.reputation_score}}

58 | 59 |
60 |
61 |
62 | 63 |
64 | 65 |
66 | 67 | 68 | 91 | 92 | 93 | 94 |
95 |

Answers

96 | {% for a in all_answers %} 97 |
98 |
99 | 100 |
101 |
102 |
103 |
{{a.votes}}
104 |
105 | {% if a.is_accepted %} 106 |
107 | {% endif %} 108 |
109 |
110 | 111 |
112 | {{a.ans_content|safe|escape}} 113 |
114 |
115 |
116 | 117 |
118 |
119 |
120 | Asked on {{a.created_at}} 121 |
122 |
123 |
124 | ... 125 |
126 |
127 |

{{a.answered_by.name}}
{{a.answered_by.reputation_score}}

128 |
129 |
130 |
131 |
132 | 133 | {% if showaccept and not q.has_accepted_answer %} 134 |
135 | 136 |
137 |
138 | Do you want to accept this solution? Click here! 139 |
140 |
141 |
142 | {% endif %} 143 |
144 | 145 |
146 | 147 | {% endfor %} 148 |
149 |
150 | 151 | 152 |
153 |

Your Answer

154 |
155 | {% csrf_token %} 156 | 157 | 160 | 161 |
162 |
163 | 164 |
165 | 166 |
167 |
168 | 169 |
170 | 171 | 172 | {% endblock %} -------------------------------------------------------------------------------- /stackoverflow/main/templates/main/questions.html: -------------------------------------------------------------------------------- 1 | {% extends 'main/base.html' %} 2 | 3 | {% block content %} 4 | 5 |
6 |
7 |
8 |
9 | 10 | 11 | 12 |
13 |

Questions

14 | 17 |
18 | 19 | 20 |
21 | 29 |
30 | 31 | 32 | 55 | 56 | {% for q in all_questions %} 57 |
58 | 59 |
60 | 61 |
62 |
{{q.upvotes.all.count}}
Upvotes
63 |
{{q.answers.all.count}}
Answers
64 |
{{q.views}}
Views
65 |
66 |
67 |
68 |
69 | {{q.title}} 70 |
71 | 72 |
73 | {% for t in q.tags.all %} 74 | 75 | {% endfor %} 76 |
77 | 78 | 79 |
80 | 81 |
82 | 83 |
84 | Asked on {{q.created_at}} by {{q.author.name}} 85 |
86 | 87 |
88 | {% endfor %} 89 |
90 |
91 |
92 |
93 | 99 | {% endblock %} 100 | 101 | -------------------------------------------------------------------------------- /stackoverflow/main/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /stackoverflow/main/urls.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from django.urls import path 3 | from django.conf import settings 4 | from . import views 5 | from django.conf import settings 6 | from django.conf.urls.static import static 7 | 8 | urlpatterns = [ 9 | path('', views.questions, name = 'name_questions'), 10 | path('tag//', views.questionByTag, name = 'name_questionByTag'), 11 | path('question//', views.questionsingle, name = 'name_questionsingle'), 12 | path('askquestion/', views.askquestion, name = 'name_askquestion'), 13 | path('profile//', views.profile, name = 'name_profile'), 14 | path('question///', views.is_accepted, name = 'name_is_accepted'), 15 | 16 | ] 17 | 18 | if settings.DEBUG: 19 | urlpatterns+=static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) -------------------------------------------------------------------------------- /stackoverflow/main/utils.py: -------------------------------------------------------------------------------- 1 | from .models import Tags, Questions, Answer 2 | from userauth.models import StackoverflowUser 3 | from django.db.models import Count,Q 4 | 5 | 6 | def reputation(booleanval, rate, ques_obj): 7 | if booleanval == False: 8 | userrepu = ques_obj.author 9 | else: 10 | userrepu = ques_obj.answered_by 11 | 12 | userrepu.reputation_score += rate 13 | userrepu.save() 14 | 15 | def performUpDownVote(user,isQuestion,id,action_type): 16 | id = int(id) 17 | flag = False 18 | if isQuestion == 'True': 19 | print('------> isQ') 20 | q = Questions.objects.get(pk = id) 21 | if q.author == user: 22 | return False 23 | else: 24 | print('------> isNotQ') 25 | flag=True 26 | q = Answer.objects.get(pk = id) 27 | if q.answered_by == user: 28 | return False 29 | 30 | existsInUpvote = True if user in q.upvotes.all() else False 31 | existsDownUpvote = True if user in q.downvotes.all() else False 32 | if existsInUpvote: 33 | if action_type == 'downvote': 34 | q.upvotes.remove(user) 35 | q.downvotes.add(user) 36 | reputation(flag,-20, q) 37 | q.votes = q.votes - 2 38 | elif existsDownUpvote: 39 | if action_type == 'upvote': 40 | q.downvotes.remove(user) 41 | q.upvotes.add(user) 42 | reputation(flag,20, q) 43 | q.votes = q.votes + 2 44 | else: 45 | if action_type == 'downvote': 46 | q.downvotes.add(user) 47 | reputation(flag,-10, q) 48 | q.votes = q.votes - 1 49 | if action_type == 'upvote': 50 | q.upvotes.add(user) 51 | reputation(flag,10, q) 52 | q.votes = q.votes + 1 53 | q.save() 54 | return True -------------------------------------------------------------------------------- /stackoverflow/main/views.py: -------------------------------------------------------------------------------- 1 | from django.shortcuts import render,redirect 2 | from .models import Tags, Questions, Answer 3 | from userauth.models import StackoverflowUser 4 | from django.db import transaction 5 | from django.db.models import Count,Q 6 | from django.contrib.auth.decorators import login_required 7 | from django.contrib import messages 8 | from .utils import reputation, performUpDownVote 9 | from django.core.paginator import Paginator 10 | # Create your views here. 11 | 12 | 13 | def questions(request): 14 | main_query = Questions.objects 15 | if request.GET and ('q' in request.GET) and request.GET['q'] == 'mostviewed': 16 | all_questions = main_query.all().order_by('-views') 17 | marked = 'mostviewed' 18 | elif request.GET and ('q' in request.GET) and request.GET['q'] == 'unanswered': 19 | all_questions = main_query.filter(is_answered = False).order_by('-created_at') 20 | marked = 'unanswered' 21 | else: 22 | marked = 'latest' 23 | all_questions = main_query.all().order_by('-created_at') 24 | 25 | # Pagination 26 | page = request.GET.get('page', 1) 27 | paginator = Paginator(all_questions, 5) 28 | try: 29 | all_questions = paginator.page(page) 30 | # except EmptyPage: 31 | # all_questions = paginator.page(paginator.num_pages) 32 | except Exception as e: 33 | all_questions = paginator.page(1) 34 | 35 | return render(request, 'main/questions.html',{'all_questions':all_questions,'marked' : marked}) 36 | 37 | @login_required 38 | def questionsingle(request, pk): 39 | # user = StackoverflowUser.objects.get(pk=1) 40 | user = request.user 41 | try: 42 | if request.GET and request.GET['isQuestion'] and request.GET['id'] and request.GET['action_type']: 43 | result = performUpDownVote(user,request.GET['isQuestion'],request.GET['id'],request.GET['action_type']) 44 | redirect_to = '/question/'+str(pk) 45 | if 'page' in request.GET: 46 | redirect_to += '?page='+request.GET['page'] 47 | if result == True: 48 | messages.success(request, 'Action successful') 49 | else: 50 | messages.error(request, 'Invalid Action') 51 | return redirect(redirect_to) 52 | except Exception: 53 | pass 54 | 55 | q = Questions.objects.get(pk = pk) 56 | if request.method == 'POST': 57 | questiontaken = request.POST.dict() 58 | answer = questiontaken.get('editor1') # Answer content 59 | a = Answer(ans_content=answer, answered_by=user, question_to_ans = q) 60 | a.save() 61 | q.answers.add(a) 62 | messages.success(request, 'Answer posted successfully') 63 | q.views = q.views + 1 64 | q.save() 65 | 66 | if q.author == user: 67 | showaccept = True 68 | else: 69 | showaccept = False 70 | 71 | # Pagination 72 | all_answers = q.answers.all() 73 | page = request.GET.get('page', 1) 74 | paginator = Paginator(all_answers, 5) 75 | try: 76 | all_answers = paginator.page(page) 77 | except PageNotAnInteger: 78 | all_answers = paginator.page(1) 79 | except EmptyPage: 80 | all_answers = paginator.page(paginator.num_pages) 81 | 82 | 83 | return render(request, 'main/question-single.html',{'q':q,'all_answers':all_answers,'showaccept': showaccept }) 84 | 85 | @login_required 86 | def askquestion(request): 87 | user = request.user 88 | print(user) 89 | if request.method == 'POST': 90 | questiontaken = request.POST.dict() 91 | title = questiontaken.get('title') 92 | content = questiontaken.get('queseditor') 93 | tags = questiontaken.get('tags') 94 | selfanswer = questiontaken.get('selfanswereditor') 95 | 96 | 97 | q = Questions(title=title, ques_content = content, author = user) 98 | if selfanswer != '': 99 | q.is_answered = True 100 | q.save() 101 | all_tags = tags.split(',') 102 | 103 | for a in all_tags: 104 | try: 105 | t = Tags.objects.get(tag_word = a) 106 | q.tags.add(t) 107 | except Exception: 108 | q.tags.create(tag_word = a) 109 | 110 | q.save() 111 | 112 | if selfanswer != '': 113 | a = Answer(ans_content=selfanswer, answered_by=user, question_to_ans = q) 114 | a.is_accepted = True 115 | print(a) 116 | a.save() 117 | q.answers.add(a) 118 | q.has_accepted_answer = True 119 | 120 | q.save() 121 | user.ans_given.add(a) 122 | user.ques_asked.add(q) 123 | user.save() 124 | 125 | messages.success(request, 'Question posted successfully') 126 | 127 | return redirect('name_questionsingle',pk=q.pk) 128 | return render(request, 'main/askquestion.html') 129 | 130 | 131 | def questionByTag(request,tag_word): 132 | main_query = Questions.objects.filter(Q(tags__tag_word__iexact = tag_word)) 133 | 134 | if request.GET and request.GET['q'] == 'mostviewed': 135 | all_questions = main_query.all().order_by('-views') 136 | marked = 'mostviewed' 137 | elif request.GET and request.GET['q'] == 'unanswered': 138 | all_questions = main_query.filter(is_answered = False) 139 | marked = 'unanswered' 140 | else: 141 | marked = 'latest' 142 | all_questions = main_query.all().order_by('-created_at') 143 | 144 | 145 | return render(request, 'main/questions.html',{'all_questions':all_questions,'marked' : marked}) 146 | 147 | @login_required 148 | def profile(request, username): 149 | seeuser = StackoverflowUser.objects.get(username=username) 150 | showeditbutton = True if seeuser == request.user else False 151 | userques = Questions.objects.filter(author = seeuser).order_by('-created_at') 152 | ansgiven = Answer.objects.filter(answered_by = seeuser).order_by('-created_at') 153 | 154 | return render(request, 'main/profile.html',{'seeuser':seeuser, 'showeditbutton': showeditbutton, 'userques': userques, 'ansgiven': ansgiven}) 155 | 156 | 157 | @login_required 158 | def is_accepted(request, pk, pk2): 159 | q = Questions.objects.get(pk = pk) 160 | a = Answer.objects.get(pk = pk2) 161 | 162 | q.has_accepted_answer = True 163 | q.save() 164 | 165 | a.is_accepted = True 166 | a.save() 167 | 168 | if q.author == request.user: 169 | showaccept = True 170 | else: 171 | showaccept = False 172 | 173 | # Pagination 174 | all_answers = q.answers.all() 175 | page = request.GET.get('page', 1) 176 | paginator = Paginator(all_answers, 5) 177 | try: 178 | all_answers = paginator.page(page) 179 | except PageNotAnInteger: 180 | all_answers = paginator.page(1) 181 | except EmptyPage: 182 | all_answers = paginator.page(paginator.num_pages) 183 | 184 | return render(request, 'main/question-single.html',{'q':q,'all_answers':all_answers,'showaccept': showaccept }) -------------------------------------------------------------------------------- /stackoverflow/manage.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Django's command-line utility for administrative tasks.""" 3 | import os 4 | import sys 5 | 6 | 7 | def main(): 8 | """Run administrative tasks.""" 9 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'stackoverflow.settings') 10 | try: 11 | from django.core.management import execute_from_command_line 12 | except ImportError as exc: 13 | raise ImportError( 14 | "Couldn't import Django. Are you sure it's installed and " 15 | "available on your PYTHONPATH environment variable? Did you " 16 | "forget to activate a virtual environment?" 17 | ) from exc 18 | execute_from_command_line(sys.argv) 19 | 20 | 21 | if __name__ == '__main__': 22 | main() 23 | -------------------------------------------------------------------------------- /stackoverflow/media/default_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RugvedB/Stackoverflow-Clone/f2540f8e7812ad55b0e7201d6e669356850d1d0b/stackoverflow/media/default_image.png -------------------------------------------------------------------------------- /stackoverflow/stackoverflow/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RugvedB/Stackoverflow-Clone/f2540f8e7812ad55b0e7201d6e669356850d1d0b/stackoverflow/stackoverflow/__init__.py -------------------------------------------------------------------------------- /stackoverflow/stackoverflow/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RugvedB/Stackoverflow-Clone/f2540f8e7812ad55b0e7201d6e669356850d1d0b/stackoverflow/stackoverflow/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /stackoverflow/stackoverflow/__pycache__/__init__.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RugvedB/Stackoverflow-Clone/f2540f8e7812ad55b0e7201d6e669356850d1d0b/stackoverflow/stackoverflow/__pycache__/__init__.cpython-38.pyc -------------------------------------------------------------------------------- /stackoverflow/stackoverflow/asgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | ASGI config for stackoverflow project. 3 | 4 | It exposes the ASGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.1/howto/deployment/asgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.asgi import get_asgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'stackoverflow.settings') 15 | 16 | application = get_asgi_application() 17 | -------------------------------------------------------------------------------- /stackoverflow/stackoverflow/settings.py: -------------------------------------------------------------------------------- 1 | """ 2 | Django settings for stackoverflow project. 3 | 4 | Generated by 'django-admin startproject' using Django 3.1.3. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.1/topics/settings/ 8 | 9 | For the full list of settings and their values, see 10 | https://docs.djangoproject.com/en/3.1/ref/settings/ 11 | 12 | """ 13 | 14 | from pathlib import Path 15 | import os 16 | from django.contrib.messages import constants as messages 17 | from dotenv import load_dotenv,find_dotenv 18 | 19 | # Build paths inside the project like this: BASE_DIR / 'subdir'. 20 | BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 21 | print(BASE_DIR) 22 | 23 | load_dotenv(find_dotenv()) 24 | 25 | # Quick-start development settings - unsuitable for production 26 | # See https://docs.djangoproject.com/en/3.1/howto/deployment/checklist/ 27 | 28 | # SECURITY WARNING: keep the secret key used in production secret! 29 | SECRET_KEY = os.getenv('SECRET_KEY') 30 | 31 | # SECURITY WARNING: don't run with debug turned on in production! 32 | DEBUG = True 33 | 34 | ALLOWED_HOSTS = [] 35 | 36 | 37 | # Application definition 38 | 39 | INSTALLED_APPS = [ 40 | 'django.contrib.admin', 41 | 'django.contrib.auth', 42 | 'django.contrib.contenttypes', 43 | 'django.contrib.sessions', 44 | 'django.contrib.messages', 45 | 'django.contrib.staticfiles', 46 | 'userauth.apps.UserauthConfig', 47 | 'main.apps.MainConfig', 48 | 'crispy_forms', 49 | ] 50 | 51 | CRISPY_TEMPLATE_PACK = 'bootstrap4' 52 | 53 | LOGIN_REDIRECT_URL = 'name_questions' 54 | LOGIN_URL = 'name_login_req' 55 | 56 | AUTH_USER_MODEL = 'userauth.StackoverflowUser' 57 | 58 | MIDDLEWARE = [ 59 | 'django.middleware.security.SecurityMiddleware', 60 | 'django.contrib.sessions.middleware.SessionMiddleware', 61 | 'django.middleware.common.CommonMiddleware', 62 | 'django.middleware.csrf.CsrfViewMiddleware', 63 | 'django.contrib.auth.middleware.AuthenticationMiddleware', 64 | 'django.contrib.messages.middleware.MessageMiddleware', 65 | 'django.middleware.clickjacking.XFrameOptionsMiddleware', 66 | ] 67 | 68 | ROOT_URLCONF = 'stackoverflow.urls' 69 | 70 | TEMPLATES = [ 71 | { 72 | 'BACKEND': 'django.template.backends.django.DjangoTemplates', 73 | 'DIRS': [], 74 | 'APP_DIRS': True, 75 | 'OPTIONS': { 76 | 'context_processors': [ 77 | 'django.template.context_processors.debug', 78 | 'django.template.context_processors.request', 79 | 'django.contrib.auth.context_processors.auth', 80 | 'django.contrib.messages.context_processors.messages', 81 | ], 82 | }, 83 | }, 84 | ] 85 | 86 | WSGI_APPLICATION = 'stackoverflow.wsgi.application' 87 | 88 | # Database 89 | # https://docs.djangoproject.com/en/3.1/ref/settings/#databases 90 | 91 | DATABASES = { 92 | 'default': { 93 | 'ENGINE': 'django.db.backends.sqlite3', 94 | 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), 95 | } 96 | } 97 | 98 | 99 | # Password validation 100 | # https://docs.djangoproject.com/en/3.1/ref/settings/#auth-password-validators 101 | 102 | AUTH_PASSWORD_VALIDATORS = [ 103 | { 104 | 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', 105 | }, 106 | { 107 | 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', 108 | }, 109 | { 110 | 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', 111 | }, 112 | { 113 | 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', 114 | }, 115 | ] 116 | 117 | 118 | # Internationalization 119 | # https://docs.djangoproject.com/en/3.1/topics/i18n/ 120 | 121 | LANGUAGE_CODE = 'en-us' 122 | 123 | TIME_ZONE = 'UTC' 124 | 125 | USE_I18N = True 126 | 127 | USE_L10N = True 128 | 129 | USE_TZ = True 130 | 131 | 132 | # Static files (CSS, JavaScript, Images) 133 | # https://docs.djangoproject.com/en/3.1/howto/static-files/ 134 | 135 | STATIC_URL = '/static/' 136 | STATICFILES_DIRS = (os.path.join(BASE_DIR,'static'),) 137 | 138 | 139 | MEDIA_URL = '/media/' 140 | MEDIA_ROOT = os.path.join(BASE_DIR, 'media') 141 | 142 | MESSAGE_TAGS = { 143 | messages.ERROR: 'danger' 144 | } 145 | 146 | 147 | EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' 148 | EMAIL_HOST = os.getenv('EMAIL_HOST') 149 | EMAIL_PORT = os.getenv('EMAIL_PORT') 150 | DEFAULT_FROM_EMAIL = os.getenv('DEFAULT_FROM_EMAIL') 151 | EMAIL_HOST_USER = os.getenv('EMAIL_HOST_USER') 152 | EMAIL_HOST_PASSWORD = os.getenv('EMAIL_HOST_PASSWORD') 153 | EMAIL_USE_TLS = True -------------------------------------------------------------------------------- /stackoverflow/stackoverflow/urls.py: -------------------------------------------------------------------------------- 1 | """stackoverflow URL Configuration 2 | 3 | The `urlpatterns` list routes URLs to views. For more information please see: 4 | https://docs.djangoproject.com/en/3.1/topics/http/urls/ 5 | Examples: 6 | Function views 7 | 1. Add an import: from my_app import views 8 | 2. Add a URL to urlpatterns: path('', views.home, name='home') 9 | Class-based views 10 | 1. Add an import: from other_app.views import Home 11 | 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') 12 | Including another URLconf 13 | 1. Import the include() function: from django.urls import include, path 14 | 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) 15 | """ 16 | from django.contrib import admin 17 | from django.urls import path, include 18 | from django.conf import settings 19 | from django.conf.urls.static import static 20 | 21 | urlpatterns = [ 22 | path('', include('main.urls')), 23 | path('', include('userauth.urls')), 24 | path('admin/', admin.site.urls), 25 | ] 26 | 27 | if settings.DEBUG: 28 | urlpatterns+=static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) -------------------------------------------------------------------------------- /stackoverflow/stackoverflow/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for stackoverflow project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/3.1/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'stackoverflow.settings') 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /stackoverflow/static/css/editprofile.css: -------------------------------------------------------------------------------- 1 | body{ 2 | background:#f8f8f8 3 | } -------------------------------------------------------------------------------- /stackoverflow/static/css/home.css: -------------------------------------------------------------------------------- 1 | .single-row{ 2 | padding: 4px 2px; 3 | } 4 | 5 | .border{ 6 | border-style: dashed; 7 | } -------------------------------------------------------------------------------- /stackoverflow/static/css/main.css: -------------------------------------------------------------------------------- 1 | .triangle-up { 2 | width: 0; 3 | height: 0; 4 | border-left: 15px solid transparent; 5 | border-right: 15px solid transparent; 6 | border-bottom: 15px solid #555; 7 | } 8 | 9 | .triangle-down { 10 | width: 0; 11 | height: 0; 12 | border-left: 15px solid transparent; 13 | border-right: 15px solid transparent; 14 | border-top: 15px solid #555; 15 | } -------------------------------------------------------------------------------- /stackoverflow/static/question/home.css: -------------------------------------------------------------------------------- 1 | .single-row{ 2 | padding: 4px 2px; 3 | } 4 | 5 | .border{ 6 | border-style: dashed; 7 | } -------------------------------------------------------------------------------- /stackoverflow/static/question/main.css: -------------------------------------------------------------------------------- 1 | .triangle-up { 2 | width: 0; 3 | height: 0; 4 | border-left: 15px solid transparent; 5 | border-right: 15px solid transparent; 6 | border-bottom: 15px solid #555; 7 | } 8 | 9 | .triangle-down { 10 | width: 0; 11 | height: 0; 12 | border-left: 15px solid transparent; 13 | border-right: 15px solid transparent; 14 | border-top: 15px solid #555; 15 | } -------------------------------------------------------------------------------- /stackoverflow/userauth/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RugvedB/Stackoverflow-Clone/f2540f8e7812ad55b0e7201d6e669356850d1d0b/stackoverflow/userauth/__init__.py -------------------------------------------------------------------------------- /stackoverflow/userauth/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RugvedB/Stackoverflow-Clone/f2540f8e7812ad55b0e7201d6e669356850d1d0b/stackoverflow/userauth/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /stackoverflow/userauth/__pycache__/__init__.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RugvedB/Stackoverflow-Clone/f2540f8e7812ad55b0e7201d6e669356850d1d0b/stackoverflow/userauth/__pycache__/__init__.cpython-38.pyc -------------------------------------------------------------------------------- /stackoverflow/userauth/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from .models import StackoverflowUser 3 | # Register your models here. 4 | 5 | admin.site.register(StackoverflowUser) 6 | -------------------------------------------------------------------------------- /stackoverflow/userauth/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class UserauthConfig(AppConfig): 5 | name = 'userauth' 6 | -------------------------------------------------------------------------------- /stackoverflow/userauth/forms.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | from django.contrib.auth.forms import UserCreationForm, AuthenticationForm 3 | from .models import StackoverflowUser 4 | 5 | 6 | class SignUpForm(UserCreationForm): 7 | name = forms.CharField(max_length=100, required=True) 8 | email = forms.EmailField(max_length=254, help_text='Required. Inform a valid email address.') 9 | 10 | class Meta: 11 | model = StackoverflowUser 12 | fields = ('username', 'name', 'email', 'password1', 'password2', ) 13 | 14 | -------------------------------------------------------------------------------- /stackoverflow/userauth/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RugvedB/Stackoverflow-Clone/f2540f8e7812ad55b0e7201d6e669356850d1d0b/stackoverflow/userauth/migrations/__init__.py -------------------------------------------------------------------------------- /stackoverflow/userauth/migrations/__pycache__/0001_initial.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RugvedB/Stackoverflow-Clone/f2540f8e7812ad55b0e7201d6e669356850d1d0b/stackoverflow/userauth/migrations/__pycache__/0001_initial.cpython-36.pyc -------------------------------------------------------------------------------- /stackoverflow/userauth/migrations/__pycache__/0001_initial.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RugvedB/Stackoverflow-Clone/f2540f8e7812ad55b0e7201d6e669356850d1d0b/stackoverflow/userauth/migrations/__pycache__/0001_initial.cpython-38.pyc -------------------------------------------------------------------------------- /stackoverflow/userauth/migrations/__pycache__/0002_auto_20201116_1153.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RugvedB/Stackoverflow-Clone/f2540f8e7812ad55b0e7201d6e669356850d1d0b/stackoverflow/userauth/migrations/__pycache__/0002_auto_20201116_1153.cpython-36.pyc -------------------------------------------------------------------------------- /stackoverflow/userauth/migrations/__pycache__/0002_auto_20201116_1153.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RugvedB/Stackoverflow-Clone/f2540f8e7812ad55b0e7201d6e669356850d1d0b/stackoverflow/userauth/migrations/__pycache__/0002_auto_20201116_1153.cpython-38.pyc -------------------------------------------------------------------------------- /stackoverflow/userauth/migrations/__pycache__/0002_auto_20201118_1548.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RugvedB/Stackoverflow-Clone/f2540f8e7812ad55b0e7201d6e669356850d1d0b/stackoverflow/userauth/migrations/__pycache__/0002_auto_20201118_1548.cpython-36.pyc -------------------------------------------------------------------------------- /stackoverflow/userauth/migrations/__pycache__/0002_auto_20201118_1548.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RugvedB/Stackoverflow-Clone/f2540f8e7812ad55b0e7201d6e669356850d1d0b/stackoverflow/userauth/migrations/__pycache__/0002_auto_20201118_1548.cpython-38.pyc -------------------------------------------------------------------------------- /stackoverflow/userauth/migrations/__pycache__/0003_auto_20201118_1948.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RugvedB/Stackoverflow-Clone/f2540f8e7812ad55b0e7201d6e669356850d1d0b/stackoverflow/userauth/migrations/__pycache__/0003_auto_20201118_1948.cpython-36.pyc -------------------------------------------------------------------------------- /stackoverflow/userauth/migrations/__pycache__/0003_auto_20201118_1948.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RugvedB/Stackoverflow-Clone/f2540f8e7812ad55b0e7201d6e669356850d1d0b/stackoverflow/userauth/migrations/__pycache__/0003_auto_20201118_1948.cpython-38.pyc -------------------------------------------------------------------------------- /stackoverflow/userauth/migrations/__pycache__/0004_auto_20201118_1808.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RugvedB/Stackoverflow-Clone/f2540f8e7812ad55b0e7201d6e669356850d1d0b/stackoverflow/userauth/migrations/__pycache__/0004_auto_20201118_1808.cpython-36.pyc -------------------------------------------------------------------------------- /stackoverflow/userauth/migrations/__pycache__/0004_auto_20201118_1808.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RugvedB/Stackoverflow-Clone/f2540f8e7812ad55b0e7201d6e669356850d1d0b/stackoverflow/userauth/migrations/__pycache__/0004_auto_20201118_1808.cpython-38.pyc -------------------------------------------------------------------------------- /stackoverflow/userauth/migrations/__pycache__/0005_auto_20201123_1931.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RugvedB/Stackoverflow-Clone/f2540f8e7812ad55b0e7201d6e669356850d1d0b/stackoverflow/userauth/migrations/__pycache__/0005_auto_20201123_1931.cpython-38.pyc -------------------------------------------------------------------------------- /stackoverflow/userauth/migrations/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RugvedB/Stackoverflow-Clone/f2540f8e7812ad55b0e7201d6e669356850d1d0b/stackoverflow/userauth/migrations/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /stackoverflow/userauth/migrations/__pycache__/__init__.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RugvedB/Stackoverflow-Clone/f2540f8e7812ad55b0e7201d6e669356850d1d0b/stackoverflow/userauth/migrations/__pycache__/__init__.cpython-38.pyc -------------------------------------------------------------------------------- /stackoverflow/userauth/models.py: -------------------------------------------------------------------------------- 1 | from django.db import models 2 | from datetime import datetime 3 | from django.utils import timezone 4 | from django.contrib.auth.models import (AbstractUser) 5 | 6 | # Create your models here. 7 | medium_len = 100 8 | long_len = 255 9 | 10 | 11 | class StackoverflowUser(AbstractUser): 12 | email = models.EmailField(verbose_name='email address', max_length=long_len, unique=True) 13 | name = models.CharField(max_length=long_len) 14 | reputation_score = models.IntegerField(default=0) 15 | about_me = models.TextField(default='Apparently, this user prefers to keep an air of mystery about them.') 16 | ques_asked = models.ManyToManyField('main.Questions', blank = True) 17 | ans_given = models.ManyToManyField('main.Answer', blank = True) 18 | profile_pic = models.ImageField(upload_to='user_profile_pic', default='default_image.png',blank=True, null = True) 19 | date_joined = models.DateTimeField(default = timezone.now) 20 | 21 | USERNAME_FIELD = 'username' 22 | REQUIRED_FIELDS = [''] # Email & Password are required by default. -------------------------------------------------------------------------------- /stackoverflow/userauth/templates/userauth/editprofile.html: -------------------------------------------------------------------------------- 1 | {% extends 'main/base.html' %} 2 | 3 | {% block content %} 4 |
5 |
6 | 11 |
12 | {% csrf_token %} 13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | 24 |
25 |
26 |
27 |
28 |
29 |

{{user.name}}

30 |

@{{user.username}}

31 |
Last seen {{user.last_login}}
32 |
33 | 34 |
35 | 36 | 37 |
38 | 42 | 43 |
44 |
45 |
46 |
Joined on {{user.date_joined}}
47 |
48 |
49 |
50 | 53 |
54 |
55 | 56 |
57 |
58 |
59 |
60 |
61 | 62 | 63 |
64 |
65 |
66 |
67 | 68 | 69 |
70 |
71 |
72 |
73 |
74 |
75 | 76 | 77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 | 85 |
86 |
87 | 88 | 89 |
90 |
91 |
92 |
93 |
94 |
95 | 96 |
97 |
98 |
99 |
100 | 104 |
105 |
106 |
107 |
108 |
109 |
Support
110 |

Get fast, free help from our friendly assistants.

111 | 112 |
113 |
114 |
115 |
116 | 117 |
118 | 119 |
120 |
121 | 122 | {% endblock %} -------------------------------------------------------------------------------- /stackoverflow/userauth/templates/userauth/login.html: -------------------------------------------------------------------------------- 1 | {% extends 'main/base.html' %} 2 | {% load crispy_forms_tags %} 3 | 4 | 5 | {% block content %} 6 | 7 | 13 | 14 |
15 | {% load crispy_forms_tags %} 16 |
17 |
18 | {% csrf_token %} 19 |
20 | Log In 21 | {{ form|crispy }} 22 |
23 |
24 | 25 |
26 |
27 |
28 | 29 | Need An Account? Sign Up Now 30 | 31 |
32 |
33 |
34 | 35 | {% endblock %} -------------------------------------------------------------------------------- /stackoverflow/userauth/templates/userauth/logout.html: -------------------------------------------------------------------------------- 1 | {% load crispy_forms_tags %} 2 | 3 | 4 | 5 | 6 | 7 | 8 | hi 9 | 10 | 11 | 12 |
13 |
14 |

You have been logged out.

15 |
16 |

17 | Login again 18 |

19 |
20 |
21 | 22 | 23 | -------------------------------------------------------------------------------- /stackoverflow/userauth/templates/userauth/signup.html: -------------------------------------------------------------------------------- 1 | {% extends 'main/base.html' %} 2 | {% load crispy_forms_tags %} 3 | 4 | 5 | {% block content %} 6 | 7 | 13 |
14 | 15 |
16 |

Sign up

17 |
18 | {% csrf_token %} 19 |
20 | Join Today 21 | {{ form|crispy }} 22 |
23 | 24 | Already Have An Account? Sign In 25 | 26 |
27 | 28 |
29 |
30 | 31 |
32 |
33 | 34 | {% endblock %} -------------------------------------------------------------------------------- /stackoverflow/userauth/templates/userauth/user_active_email.html: -------------------------------------------------------------------------------- 1 | {% autoescape off %} 2 | Hi {{ user.username }}, 3 | Please click on the link to confirm your registration, 4 | 5 | http://{{ domain }}{% url 'activate' uidb64=uid token=token %} 6 | 7 | {% endautoescape %} -------------------------------------------------------------------------------- /stackoverflow/userauth/tests.py: -------------------------------------------------------------------------------- 1 | from django.test import TestCase 2 | 3 | # Create your tests here. 4 | -------------------------------------------------------------------------------- /stackoverflow/userauth/tokens.py: -------------------------------------------------------------------------------- 1 | from django.contrib.auth.tokens import PasswordResetTokenGenerator 2 | import six 3 | 4 | # from django.utils import six 5 | 6 | class TokenGenerator(PasswordResetTokenGenerator): 7 | def _make_hash_value(self, user, timestamp): 8 | return ( 9 | six.text_type(user.pk) + six.text_type(timestamp) + 10 | six.text_type(user.is_active) 11 | ) 12 | 13 | 14 | account_activation_token = TokenGenerator() -------------------------------------------------------------------------------- /stackoverflow/userauth/urls.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | from django.urls import path 3 | from django.contrib.auth import views as auth_views 4 | from . import views 5 | from django.conf import settings 6 | from django.conf.urls.static import static 7 | from django.conf.urls import url 8 | 9 | urlpatterns = [ 10 | path('signup/', views.signup, name = 'name_signup'), 11 | 12 | # This 2 views are for allauth package which doent need any views and has login/logout views already implemented. 13 | # path('login/', auth_views.LoginView.as_view(template_name='userauth/login.html'), name='name_login_req'), 14 | # path('logout/', auth_views.LogoutView.as_view(template_name='userauth/logout.html'), name='name_logout_req'), 15 | 16 | path('login/', views.login_request, name='name_login_req'), 17 | path('logout/', views.logout_request, name='name_logout_req'), 18 | 19 | path('editprofile/', views.editprofile, name = 'name_editprofile'), 20 | 21 | url(r'^activate/(?P[0-9A-Za-z_\-]+)/(?P[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$', 22 | views.activate, name='activate'), 23 | ] 24 | 25 | if settings.DEBUG: 26 | urlpatterns+=static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) -------------------------------------------------------------------------------- /stackoverflow/userauth/views.py: -------------------------------------------------------------------------------- 1 | from django.contrib.auth import login, authenticate, logout 2 | from django.shortcuts import render, redirect 3 | from django.contrib.auth.forms import AuthenticationForm 4 | from .forms import SignUpForm 5 | from django.contrib import messages 6 | from django.contrib.auth.decorators import login_required 7 | from django.contrib.auth import get_user_model 8 | from django.core.mail import EmailMessage 9 | from django.contrib.sites.shortcuts import get_current_site 10 | from django.utils.encoding import force_bytes, force_text, DjangoUnicodeDecodeError 11 | from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode 12 | from django.urls import reverse 13 | from django.http import HttpResponse 14 | from django.template.loader import render_to_string 15 | from .tokens import account_activation_token 16 | User = get_user_model() 17 | 18 | def signup(request): 19 | if request.method == 'POST': 20 | form = SignUpForm(request.POST) 21 | if form.is_valid(): 22 | user = form.save(commit=False) 23 | user.is_active = False 24 | user.save() 25 | 26 | current_site = get_current_site(request) 27 | mail_subject = 'Activate your Stackoberflow account.' 28 | message = render_to_string('userauth/user_active_email.html', { 29 | 'user': user.username, 30 | 'domain': current_site.domain, 31 | 'uid':urlsafe_base64_encode(force_bytes(user.pk)), 32 | 'token':account_activation_token.make_token(user), 33 | }) 34 | to_email = form.cleaned_data.get('email') 35 | email = EmailMessage( 36 | mail_subject, message, to=[to_email] 37 | ) 38 | email.send() 39 | username = form.cleaned_data.get('username') 40 | messages.success(request, f"New account created: {username}, Please confirm your email address to complete the registration") 41 | return redirect("/") 42 | else: 43 | for msg in form.error_messages: 44 | messages.error(request, f"{msg}: {form.error_messages[msg]}") 45 | return render(request = request, template_name = "userauth/signup.html", context={"form":form}) 46 | 47 | form = SignUpForm() 48 | return render(request, 'userauth/signup.html', {'form': form}) 49 | 50 | @login_required 51 | def editprofile(request): 52 | user = request.user 53 | if request.method == 'POST': 54 | data = request.POST.dict() 55 | firstname = data.get('firstname') 56 | lastname = data.get('lastname') 57 | about = data.get('about') 58 | if firstname != '': 59 | user.first_name = firstname 60 | if lastname != '': 61 | user.last_name = lastname 62 | if about != '': 63 | user.about_me = about 64 | if request.FILES and request.FILES['fileInput']: 65 | user.profile_pic = request.FILES['fileInput'] 66 | user.save() 67 | messages.success(request, 'Profile updated successfully') 68 | return render(request, 'userauth/editprofile.html', {'user':user}) 69 | 70 | @login_required 71 | def logout_request(request): 72 | logout(request) 73 | messages.info(request, "Logged out successfully!" ) 74 | return redirect("/") 75 | 76 | 77 | 78 | def login_request(request): 79 | if request.method == "POST": 80 | form = AuthenticationForm(request, data = request.POST) 81 | if form.is_valid(): 82 | username = form.cleaned_data.get('username') 83 | password = form.cleaned_data.get('password') 84 | user = authenticate(username=username, password=password) 85 | if user is not None: 86 | login(request, user) 87 | messages.info(request, f"You are logged in as {username}") 88 | return redirect("/") 89 | else: 90 | messages.error(request, "Invalid username or password") 91 | 92 | else: 93 | messages.error(request, "Invalid username or password") 94 | 95 | form = AuthenticationForm() 96 | return render(request, "userauth/login.html", {"form" : form}) 97 | 98 | def activate(request, uidb64, token): 99 | try: 100 | uid = force_text(urlsafe_base64_decode(uidb64)) 101 | user = User.objects.get(pk=uid) 102 | except(TypeError, ValueError, OverflowError, User.DoesNotExist): 103 | user = None 104 | if user is not None and account_activation_token.check_token(user, token): 105 | user.is_active = True 106 | user.save() 107 | login(request, user) 108 | messages.success(request, 'Account activated successfully. Thank you for your email confirmation. Now you can login your account.') 109 | return redirect('name_login_req') 110 | else: 111 | messages.error(request, 'Activation link is invalid!') 112 | return redirect('name_login_req') --------------------------------------------------------------------------------