Skip to content

Commit

Permalink
Merge branch 'release/0.0.34'
Browse files Browse the repository at this point in the history
  • Loading branch information
Cristian committed Nov 16, 2016
2 parents 4edeba5 + c3a784e commit 468e914
Show file tree
Hide file tree
Showing 8 changed files with 144 additions and 91 deletions.
73 changes: 0 additions & 73 deletions README.md

This file was deleted.

91 changes: 91 additions & 0 deletions README.rst
@@ -0,0 +1,91 @@
=====================
WELCOME TO DJANGO-QA
=====================
.. image:: https://travis-ci.org/swappsco/django-qa.svg?branch=master
:alt: Build Status
:target: https://travis-ci.org/swappsco/django-qa

.. image:: https://coveralls.io/repos/github/swappsco/django-qa/badge.svg?branch=master
:alt: Coveralls Status
:target: https://coveralls.io/github/swappsco/django-qa?branch=master

A Simple Q&A App using Python Django
====================================
django-qa_ is a fork from Simple-Q-A-App-using-Python-Django_ aimed to create a pluggable package than allows to implement a StackOverflow-like forum site for your Django web project.
The development of this package is kindly supported by SWAPPS_ and constantly developed by it's colaborators. Feel free to use it, add some issues if you find bugs or think of a really cool feature, even clone it and generate a pull requests to incorporate those cool features made by yourself; If you have special requirements, `drop us a few lines <https://www.swapps.io/contact/>`_ and perhaps we can help you out too.

.. _django-qa: http://swappsco.github.io/django-qa/
.. _Simple-Q-A-App-using-Python-Django: http://arjunkomath.github.io/Simple-Q-A-App-using-Python-Django
.. _SWAPPS: https://www.swapps.io/

Please take in considerations than this application is still under active development and we cannot guarantee that nothing will break between versions. Most of the core features are already there, so we expect to release a beta version soon.

Features
========
* Assumes nothing about the rest of your application.
* Create questions and answers.
* Comment on questions and answers.
* Upvote/Downvote questions and answers.
* Users have a reputation and a profile.
* Support for tagging questions with django-taggit.
* Questions are categorized by latest, popular and most voted.

Installation
============
Django-QA aims at keeping things simple. To install it you have to do what you would do with most django apps.

Install with pip::

pip install django-qa

Add to INSTALLED_APPS in your project settings:

.. code-block:: python
INSTALLED_APPS = (
...
qa,
...
)
Add the package urls to the project:

.. code-block:: python
urlpatterns = [
...,
url(r'^', include('qa.urls')),
...
]
Run migrations::

python manage.py migrate

And that's it!


Settings
========
QA_DESCRIPTION_OPTIONAL (False). This flag disables validation for description field, allowing title only questions.


About the functionality
=======================
* The package is integrated with the framework authentication process, right now the package defines an user profile linked to Django's user model, this models was created to contain information related to the user's activities inside the package functionalities.
* It has comments on questions and answers.
* It has no support for anonymous questions nor answers or comments.
* It has tagging support through django-taggit.
* It has a basic implementation for score and reputation records.

Next steps
==========
With this setup you will have a functional questions and answers section inside of your project. Probably you will need to work on changing the default templates to fit the look and feel of your site.

If your project has an user profile already, you may want to merge it with the data provided by this app (questions, answers, comments, reputation, etc). That requires some extra work, but can be done without using ugly hacks.

The template structure serves as a foundation for your project, but you can (and should) override the defaults to better suit your needs. For example we load bootstrap3 from a CDN, but if your application already has bootstrap in a package you can just extend from your main base template.

The package has no moderation options on none of the models yet and still lacks REST support.

If you think that something essential for this kind of application is missing, you can request a feature by adding an issue to our repository.
14 changes: 10 additions & 4 deletions qa/forms.py
@@ -1,8 +1,14 @@
from qa.models import UserQAProfile
from qa.models import UserQAProfile, Question
from django.conf import settings
from django import forms


class UserProfileForm(forms.ModelForm):
class QuestionForm(forms.ModelForm):
class Meta:
model = UserQAProfile
fields = ('website', 'picture')
model = Question
fields = ['title', 'description', 'tags']

def __init__(self, *args, **kwargs):
super(QuestionForm, self).__init__(*args, **kwargs)
if hasattr(settings, 'QA_DESCRIPTION_OPTIONAL'):
self.fields['description'].required = not settings.QA_DESCRIPTION_OPTIONAL
32 changes: 31 additions & 1 deletion qa/tests/test_views.py
@@ -1,4 +1,4 @@
from django.test import TestCase, Client
from django.test import TestCase, Client, override_settings
from django.contrib.auth import get_user_model
from django.core.urlresolvers import reverse
from django.core.exceptions import ValidationError
Expand Down Expand Up @@ -51,6 +51,36 @@ def test_create_question_view_one(self):
self.assertEqual(Question.objects.count(),
current_question_count + 1)

@override_settings(QA_DESCRIPTION_OPTIONAL=True)
def test_create_question_optional_description(self):
"""
When QA_DESCRIPTION_OPTIONAL is True, the validation for description
should be disabled on the form, allowing the object to be created without specifying it.
"""
title = 'This is my question'
current_question_count = Question.objects.count()
response = self.client.post(
reverse('qa_create_question'),
{'title': title, 'tags': 'test tag'})
self.assertEqual(response.status_code, 302)
new_question = Question.objects.last()
self.assertEqual(new_question.title, title)
self.assertEqual(Question.objects.count(), current_question_count + 1)

@override_settings(QA_DESCRIPTION_OPTIONAL=False)
def test_create_question_optional_description_false(self):
"""
When QA_DESCRIPTION_OPTIONAL is False (default), the validation for description
will be on place, and a question cannot be created without setting some content for it.
"""
title = 'This is my question'
current_question_count = Question.objects.count()
response = self.client.post(
reverse('qa_create_question'),
{'title': title, 'tags': 'test tag'})
self.assertEqual(response.status_code, 200)
self.assertEqual(Question.objects.count(), current_question_count)

def test_create_question_view_two(self):
"""
CreateAnswerView should create a new question object bound to the
Expand Down
5 changes: 3 additions & 2 deletions qa/views.py
Expand Up @@ -19,6 +19,8 @@
QuestionVote, AnswerComment, QuestionComment)
from .mixins import LoginRequired, AuthorRequiredMixin
from .utils import question_score
from .forms import QuestionForm

try:
qa_messages = 'django.contrib.messages' in settings.INSTALLED_APPS and\
settings.QA_MESSAGES
Expand Down Expand Up @@ -214,9 +216,8 @@ class CreateQuestionView(LoginRequired, CreateView):
View to handle the creation of a new question
"""
template_name = 'qa/create_question.html'
model = Question
fields = ['title', 'description', 'tags']
message = _('Thank you! your question has been created.')
form_class = QuestionForm

def form_valid(self, form):
"""
Expand Down
4 changes: 2 additions & 2 deletions setup.py
Expand Up @@ -2,12 +2,12 @@
# -*- coding: utf-8 -*-
from setuptools import find_packages, setup

with open('README.md') as file:
with open('README.rst') as file:
long_description = file.read()

setup(
name='django-qa',
version='0.0.33',
version='0.0.34',
description='Pluggable django app for Q&A',
long_description=long_description,
author='arjunkomath, cdvv7788, sebastian-code, jlariza, swappsco',
Expand Down
15 changes: 6 additions & 9 deletions test_project/core/views.py
Expand Up @@ -2,7 +2,7 @@
from django.shortcuts import render
from django.http import HttpResponseRedirect, HttpResponse
from django.template import RequestContext
from django.shortcuts import render, render_to_response
from django.shortcuts import render
from django.contrib.auth import authenticate, login
from .forms import UserForm

Expand All @@ -20,7 +20,6 @@ def register(request):
# If it's a HTTP POST, we're interested in processing form data.
if request.method == 'POST':
# Attempt to grab information from the raw form information.
# Note that we make use of both UserForm and UserProfileForm.
user_form = UserForm(data=request.POST)

# If the two forms are valid...
Expand All @@ -41,21 +40,19 @@ def register(request):
# Print problems to the terminal.
# They'll also be shown to the user.
else:
return render_to_response(
return render(request,
'register.html',
{'user_form': user_form, 'registered': registered},
context)
{'user_form': user_form, 'registered': registered})

# Not a HTTP POST, so we render our form using two ModelForm instances.
# These forms will be blank, ready for user input.
else:
user_form = UserForm()

# Render the template depending on the context.
return render_to_response(
return render(request,
'register.html',
{'user_form': user_form, 'registered': registered},
context)
{'user_form': user_form, 'registered': registered})


def user_login(request):
Expand Down Expand Up @@ -97,7 +94,7 @@ def user_login(request):
else:
# No context variables to pass to the template system, hence the
# blank dictionary object...
return render_to_response('login.html', {}, context)
return render(request, 'login.html', {})


# Use the login_required() decorator to ensure only
Expand Down
1 change: 1 addition & 0 deletions test_project/simpleqa/settings.py
Expand Up @@ -99,6 +99,7 @@
'debug': True,
},
},

]
# Internationalization
# https://docs.djangoproject.com/en/1.7/topics/i18n/
Expand Down

0 comments on commit 468e914

Please sign in to comment.