{"id":46990275,"url":"https://github.com/smark-1/django-easy-faq","last_synced_at":"2026-03-11T13:52:39.597Z","repository":{"id":37008104,"uuid":"341039630","full_name":"smark-1/django-easy-faq","owner":"smark-1","description":"a Django app to easily add FAQ into website with extremely little effort","archived":false,"fork":false,"pushed_at":"2024-08-12T03:04:35.000Z","size":1943,"stargazers_count":17,"open_issues_count":1,"forks_count":8,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-10-02T13:57:28.147Z","etag":null,"topics":["django","faq","frequently-asked-questions"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/smark-1.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-02-22T00:52:32.000Z","updated_at":"2025-06-03T15:11:25.000Z","dependencies_parsed_at":"2024-03-05T01:42:36.295Z","dependency_job_id":"b678abcf-8dc6-4f2a-872b-29e1d93d9578","html_url":"https://github.com/smark-1/django-easy-faq","commit_stats":null,"previous_names":["smark-1/django-easy-faq","dragoncommits/django-easy-faq"],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/smark-1/django-easy-faq","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smark-1%2Fdjango-easy-faq","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smark-1%2Fdjango-easy-faq/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smark-1%2Fdjango-easy-faq/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smark-1%2Fdjango-easy-faq/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/smark-1","download_url":"https://codeload.github.com/smark-1/django-easy-faq/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smark-1%2Fdjango-easy-faq/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30382810,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-11T12:49:11.341Z","status":"ssl_error","status_checked_at":"2026-03-11T12:46:41.342Z","response_time":84,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["django","faq","frequently-asked-questions"],"created_at":"2026-03-11T13:52:39.097Z","updated_at":"2026-03-11T13:52:39.586Z","avatar_url":"https://github.com/smark-1.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# django-easy-faq\n\ndjango-easy-faq is a Django app to allow for a simple yet feature rich faq app. with categories, commenting voting of questions and answers all as an optional part of the app. To see screenshots of what this django-easy-faq could look like with bootstrap 5 styling [click here](demo/demo.md).\n\n\n## Quick start\n\n1. pip install:\n\n    `pip install django-easy-faq`\n\n2. Add \"faq\" to your INSTALLED_APPS setting like this:\n\n    ```python\n    INSTALLED_APPS = [\n        ...\n        'faq',]\n    ```\n\n3. Include the easy-faq URLconf in your project urls.py like this::\n\n    ```python\n    #…\n    path('faq/', include('faq.urls')),\n    #…\n    ```\n\n4. Add `FAQ_SETTINGS = []` to your `settings.py`\n5. Run ``python manage.py makemigrations`` to create the faq models migrations.\n6. Run ``python manage.py migrate`` to create the faq models.\n\n7. Start the development server and visit http://127.0.0.1:8000/admin/\n   to create a category (you'll need the Admin app enabled).(categories part of the app can be disabled)\n\n8. Visit http://127.0.0.1:8000/faq/ to see the categories.\n\n## Settings\n\nyou can change most things in settings below is a list of all settings\nadd any or all to change to desired behavior::\n\n\n    FAQ_SETTINGS = ['your_settings_here',]\n\n\n1. no_category_description                  - add if using categories but don't want descriptions for them\n2. no_category                              - add if don't want to use categories\n3. logged_in_users_can_add_question         - add if you want any logged in user to be able to ask a question\n4. logged_in_users_can_answer_question      - add if you want any logged in user to be able to answer a question\n5. allow_multiple_answers                   - add if you want a question to be able to be answered multiple times\n6. no_comments                              - add if don't want to use comments\n7. anonymous_user_can_comment               - add if you want any user to be able to comment including anonymous users\n8. view_only_comments                       - add if you want users to see posted comments but not be able to add any more\n9. no_votes                                 - add if don't want any voting for useful questions or answers\n10. no_answer_votes                         - add if only want question voting\n11. no_question_votes                       - add if only want answer voting\n12. allow_unicode                           - add if you want to allow unicode slugs\n13. login_required                          - add if you want to only let logged in users see FAQ's\n14. rich_text_answers                       - add if you want to use rich text for answers. This requires the django-tinymce package to be installed\n\n## Templates\n\nall of the templates are meant to be overwritten\nto overwrite them create a faq directory inside of the templates directory and add a html file with the same name to it\n\nif this doesn't work make sure that the templates setting has 'DIRS': ['templates'], in it::\n\n    TEMPLATES = [\n        {\n            ...\n            'DIRS': ['templates'],\n            ...\n        },\n    ]\n\nhere is a list of templates and there default template  you can overwrite\n\n1. categories_list.html - faq main view if using categories::\n\n\n        \u003ch1\u003eselect a FAQ category\u003c/h1\u003e\n        {% for category in categories %}\n            \u003ch3\u003e\u003ca href=\"{% url 'faq:category_detail' category.slug %}\"\u003e{{category.name}}\u003c/a\u003e\u003c/h3\u003e\n            {% if category.description %}\n                \u003cp\u003e{{category.description}}\u003c/p\u003e\n            {% endif %}\n            \u003chr\u003e\n        {% endfor %}\n\n\n2. category_detail.html - faq category detail view if using categories::\n\n\n        \u003ch1\u003echoose a FAQ Question\u003c/h1\u003e\n        \u003ch2\u003e{{category}}\u003c/h2\u003e\n        {% if category.description %}\n        \u003cp\u003e{{category.description}}\u003c/p\u003e\n        {% endif %}\n        \u003chr\u003e\n        {% for question in category.question_set.all %}\n            \u003ch3\u003e\u003ca href=\"{% url 'faq:question_detail' category.slug question.slug %}\"\u003e{{question.question}}\u003c/a\u003e\u003c/h3\u003e\n        {% endfor %}\n        \u003chr\u003e\n        \u003ca href=\"{% url 'faq:index_view' %}\"\u003eback\u003c/a\u003e\n        {% if can_add_question %}\n            \u003ca href=\"{% url 'faq:add_question' category.slug %}\"\u003eadd question\u003c/a\u003e\n        {% endif %}\n\n\n3. questions_list.html - lists all questions if not using categories::\n\n\n        \u003ch1\u003echoose a FAQ Question\u003c/h1\u003e\n        {% for question in questions %}\n            \u003ch3\u003e\u003ca href=\"{% url 'faq:question_detail' question.slug %}\"\u003e{{question.question}}\u003c/a\u003e\u003c/h3\u003e\n        {% endfor %}\n    \n        {% if can_add_question %}\n            \u003chr\u003e\n            \u003ca href=\"{% url 'faq:add_question' %}\"\u003eadd question\u003c/a\u003e\n        {% endif %}\n\n\n4. question_detail.html - the question detail page::\n\n\n        {% extends 'faq/question_base.html' %}\n    \n        {% block question_content %}\n        {% if allow_multiple_answers %}\n        \u003ch3\u003eanswers\u003c/h3\u003e\n        \u003cul\u003e\n            {% for answer in question.answer_set.all %}\n                \u003cli\u003e\u003cb\u003e{{answer.answer}}\u003c/b\u003e\n                    {% if can_vote_answer %}\n                     | found this answer helpful?\n                    \u003cform style=\"display: inline;\" action=\"{% if category_enabled %}{% url 'faq:vote_answer' question.category.slug question.slug answer.slug %}{% else %}{% url 'faq:vote_answer' question.slug answer.slug %}{% endif %}\" method=\"post\"\u003e\n                        {% csrf_token %}\n                        \u003cinput type=\"hidden\" value=True name=\"vote\"\u003e\n                        \u003cbutton type=\"submit\"\u003eyes({{answer.helpful}})\u003c/button\u003e\n                    \u003c/form\u003e\n                    \u003cform style=\"display: inline;\" action=\"{% if category_enabled %}{% url 'faq:vote_answer' question.category.slug question.slug answer.slug %}{% else %}{% url 'faq:vote_answer' question.slug answer.slug %}{% endif %}\" method=\"post\"\u003e\n                        {% csrf_token %}\n                        \u003cinput type=\"hidden\" value=False name=\"vote\"\u003e\n                        \u003cbutton type=\"submit\"\u003eno({{answer.not_helpful}})\u003c/button\u003e\n                    \u003c/form\u003e\n                    {% endif %}\n                \u003c/li\u003e\n            {% endfor %}\n        \u003c/ul\u003e\n    \n        {% else %}\n            {% if question.answer_set.exists %}\n                \u003cp\u003eanswer:\u003c/p\u003e\n                \u003ch3\u003e{{question.answer_set.first.answer}}\u003c/h3\u003e\n                {% if can_vote_answer %}\n                 found this answer helpful?\n                \u003cform style=\"display: inline;\" action=\"{% if category_enabled %}{% url 'faq:vote_answer' question.category.slug question.slug question.answer_set.first.slug %}{% else %}{% url 'faq:vote_answer' question.slug question.answer_set.first.slug %}{% endif %}\" method=\"post\"\u003e\n                    {% csrf_token %}\n                    \u003cinput type=\"hidden\" value=True name=\"vote\"\u003e\n                    \u003cbutton type=\"submit\"\u003eyes({{question.answer_set.first.helpful}})\u003c/button\u003e\n                \u003c/form\u003e\n                \u003cform style=\"display: inline;\" action=\"{% if category_enabled %}{% url 'faq:vote_answer' question.category.slug question.slug question.answer_set.first.slug %}{% else %}{% url 'faq:vote_answer' question.slug question.answer_set.first.slug %}{% endif %}\" method=\"post\"\u003e\n                    {% csrf_token %}\n                    \u003cinput type=\"hidden\" value=False name=\"vote\"\u003e\n                    \u003cbutton type=\"submit\"\u003eno({{question.answer_set.first.not_helpful}})\u003c/button\u003e\n                \u003c/form\u003e\n                {% endif %}\n            {% else %}\n                no answers yet\n            {% endif %}\n        {% endif %}\n    \n    \n        {% if can_answer_question %}\n            {% if category_enabled %}\n                \u003ca href=\"{% url 'faq:answer_question' question.category.slug question.slug %}\"\u003eanswer question\u003c/a\u003e\n            {% else %}\n                \u003ca href=\"{% url 'faq:answer_question' question.slug %}\"\u003eanswer question\u003c/a\u003e\n            {% endif %}\n        {% endif %}\n        \u003chr\u003e\n        {% if comments_allowed %}\n            {% include 'faq/comments.html' %}\n        {% endif %}\n    \n        {% endblock %}\n\n5. answer_form.html - form to add answer to question::\n\n\n        \u003ch1\u003eAnswer Question\u003c/h1\u003e\n        \u003ca href=\"{{question.get_absolute_url}}\"\u003e\u003ch3\u003e{{question.question}}\u003c/h3\u003e\u003c/a\u003e\n        \u003cform method=\"post\"\u003e\n            {% csrf_token %}\n            {{form}}\n            \u003cinput type=\"submit\"\u003e\n        \u003c/form\u003e\n\n6. comment_form.html - form to add comments to question (only shows up when form has error because view only gets posted to)::\n\n\n        \u003ch1\u003ePost A Comment\u003c/h1\u003e\n        \u003ca href=\"{{question.get_absolute_url}}\"\u003e\u003ch3\u003e{{question.question}}\u003c/h3\u003e\u003c/a\u003e\n        \u003cform method=\"post\"\u003e\n            {% csrf_token %}\n            {{form}}\n            \u003cinput type=\"submit\"\u003e\n        \u003c/form\u003e\n\n7. question_form.html - form to add a new question::\n\n\n        \u003ch1\u003eAdd Your Question\u003c/h1\u003e\n        \u003cform method=\"post\"\u003e\n            {% csrf_token %}\n            {{form}}\n            \u003cinput type=\"submit\"\u003e\n        \u003c/form\u003e\n\n8. vote_form.html - form for voting questions and answers (only shows up when form has error because view only gets posted to)::\n\n\n        \u003ch1\u003evote\u003c/h1\u003e\n        \u003cform method=\"post\"\u003e\n            {% csrf_token %}\n            {{form}}\n            \u003cinput type=\"submit\"\u003e\n        \u003c/form\u003e\n\n9. comments.html - if comments are allowed this template is included in the question detail.html::\n\n\n        \u003ch3\u003ecomments\u003c/h3\u003e\n        \u003cul\u003e\n            {% for comment in question.faqcomment_set.all %}\n                \u003cli\u003e\u003ch4\u003e{{comment.comment}}\u003c/h4\u003e\n                    posted by {% if comment.user%}{{comment.user}}{% else %}anonymous{% endif %} {{comment.post_time|timesince}} ago\u003c/li\u003e\n            {% endfor %}\n        \u003c/ul\u003e\n        {% if add_new_comment_allowed %}\n            {% if category_enabled %}\n            \u003cform method=\"post\" action=\"{% url 'faq:add_comment' question.category.slug question.slug %}\"\u003e\n            {% else %}\n            \u003cform method=\"post\" action=\"{% url 'faq:add_comment' question.slug %}\"\u003e\n            {% endif %}\n            \u003cfieldset\u003e\n                \u003clegend\u003ePost Your Comment Here:\u003c/legend\u003e\n                {% csrf_token %}\n                {{comment_form}}\n                \u003cinput type=\"submit\" name=\"post\"\u003e\n            \u003c/fieldset\u003e\n            \u003c/form\u003e\n        {% endif %}\n\n## Template Variables\n\n1. categories_list.html\n    categories - all the categories (category queryset)\n\n2. categories_detail.html\n    category - the category chosen (category object)\n    can_add_question - bool if the user can add a question (depends on the settings)\n3. questions_list.html\n    questions - all the questions (question queryset)\n    can_add_question - bool if the user can add a question (depends on the settings)\n4. question_detail.html\n    question - the question chosen (question object)\n    can_vote_question - bool if the user can vote a question (depends on the settings)\n    category_enabled - bool if category enabled in settings\n    allow_multiple_answers - bool if multiple answers allowed in settings\n    can_vote_answer - bool if the user can vote an answer (depends on the settings)\n    can_answer_question - bool if current user can answer question (depends on the settings)\n    comments_allowed - bool if using comments in settings\n    add_new_comment_allowed - bool if current user can add comment (depends on the settings)\n    comment_form - form to submit a new comment\n5. answer_form.html\n    question - the question to add answer to (question object)\n    form - form to add new answer\n6. comment_form.html\n    question - the question to add comment to (question object)\n    form - form to add new comment\n7. question_form.html\n    form - form to add new question\n8. vote_form.html\n    form - form to vote for a question or answer\n\n## Urls\n\nall of the following urls are by name then additional\nthe app name for the urls is ``'faq'``\n\n* index_view\n    * no arguments\n    * displays all the categories if categories are enabled otherwise shows questions\n* category_detail\n    * needs category slug as slug\n    * displays all the questions given the category when categories are enabled\n* add_question\n    * if categories are enabled needs category slug as slug\n    * if logged_in_users_can_add_question then displays form for logged in users to ask a new question\n* question_detail\n    * needs question slug as question | if categories are enabled needs category slug as slug\n    * displays the main FAQ page with the question all the comments and answers\n* answer_question\n    * needs question slug as question | if categories are enabled needs category slug as category\n    * displays the answer question form\n* add_comment\n    * needs question slug as question | if categories are enabled needs category slug as category\n    * only works if using comments\n    * used to post comment form from question_detail to database\n* vote_answer\n    * needs question slug as question | needs answer slug as answer | if categories are enabled needs category slug as category\n    * only works if using answer voting\n    * used to post hidden input vote = 1 or vote = 0 depending on vote up or down\n* vote_question\n    * needs question slug as question | if categories are enabled needs category slug as category\n    * only works if using question voting\n    * used to post hidden input vote = 1 or vote = 0 depending on vote up or down\n\n## django-tinymce\nIf you want to use rich text answers you will need to [install django-tinymce](https://django-tinymce.readthedocs.io/en/latest/installation.html#id2)\n\nMake sure to include in the template the `{{ form.media }}` to include the tinymce javascript and css files.\n\u003e [!WARNING]  \n\u003e Failing to follow the following steps will result in a xss vulnerability in your site.\n\nTo allow the rich text answers to be rendered properly you will need to use the safe filter in your templates.\nWhile django-tinymce does escape the html the answers that were created when the rich text editor was not enabled **has not been escaped and is not safe**.\nSo these answers cannot be rendered with the safe filter. So a flag was added to the answer model 'is_rich_text' that is set to True when the answer is created with the rich text editor.\nIn the template you can use the following code to render the answer properly::\n\n    {% if answer.is_rich_text %}\n        {{answer.answer|safe}}\n    {% else %}\n        {{answer.answer}}\n    {% endif %}\n\n## Contributing\ndjango-easy-faq aims to be the best faq app for django. It welcomes contributions of all types - issues, bugs, feature requests, documentation updates, tests and pull requests.\n\n## change log\n- 1.9 added view onsite link in admin, added richtext answers in admin\n\n- 1.8 added support for richtext answers with django-tinymce\n\n- 1.7 added support for django 5.0\n\n- 1.6 fixed bug where no_category_description did not do remove the category description in the admin\n\n- 1.5 added login_required setting to allow faq app to be available to only logged in users\n\n- 1.4 added unicode option to add unicode slugs\n\n- 1.3 fixed bug where a slug must be filled out in admin even though slug gets auto generated to save for questions, answers, and categories. Made questions, answers, categories slugs readonly in admin\n\n- 1.2 fixed bug in pypi distro not including faq app\n\n- 1.1 added more templates to override easily\n\n- 1.0 added pypi distribution\n\n- 0.5 fixed migrations\n\n- 0.4 fixed bug that logged out users can vote - which then raises exceptions\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsmark-1%2Fdjango-easy-faq","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsmark-1%2Fdjango-easy-faq","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsmark-1%2Fdjango-easy-faq/lists"}