Code Monkey home page Code Monkey logo

djaodjin-saas's Introduction

DjaoDjin-SaaS

Documentation Status PyPI version

djaodjin-saas is a Django application that implements the logic to support subscription-based Software-as-a-Service businesses.

Major Features:

  • Separate billing profiles and authenticated users
  • Double entry book keeping ledger
  • Flexible security framework

This project contains bare bone templates which are compatible with Django and Jinja2 template engines. To see djaodjin-saas in action as part of a full-fledged subscription-based session proxy, take a look at djaoapp.

Full documentation for the project is available at Read-the-Docs

Development

After cloning the repository, create a virtualenv environment and install the prerequisites:


    $ python -m venv .venv
    $ source .venv/bin/activate
    $ pip install -r testsite/requirements.txt

    # Installs Javascript prerequisites to run in the browser
    $ make vendor-assets-prerequisites

To use the testsite, you will need to add the payment processor keys (see Processor Backends) and Django secret key into a credentials file. Example with Stripe:


    $ cat ./credentials

    SECRET_KEY = "enough_random_data"
    STRIPE_PUB_KEY = "your_stripe_public_api_key"
    STRIPE_PRIV_KEY = "your_stripe_private_api_key"

It remains to create and populate the database with required objects.

$ python ./manage.py migrate --run-syncdb --noinput
$ python ./manage.py loaddata testsite/fixtures/initial_data.json
$ python ./manage.py createsuperuser

You can further generate a set of dummy data data to populate the site.

$ python ./manage.py load_test_transactions

Side note: If create your own fixtures file (ex: testsite/fixtures/test_data.json) and attempt to load them with a Django version before 2 while the Python executable was linked with a SQLite version after 3.25, you might stumble upon the well-known SQLite 3.26 breaks database migration ForeignKey constraint, leaving <table_name>__old in db schema bug. Your best bet is to use Django2+ or delete the migrations/ directory.

If all is well then, you are ready to run the server and browse the testsite.

$ python manage.py runserver

# Browse http://localhost:8000/

Implementation Notes

The latest versions of django-restframework (>=3.0) implement paginators disconnected from parameters in views (i.e. no more paginate_by). You will thus need to define PAGE_SIZE in your settings.py

$ diff testsite/settings.py
+REST_FRAMEWORK = {
+    'PAGE_SIZE': 25,
+    'DEFAULT_PAGINATION_CLASS':
+        'rest_framework.pagination.PageNumberPagination',
+}

This Django App does not send notification e-mails itself. All major updates that would result in a e-mail sent trigger signals though. It is straightforward to send e-mails on a signal trigger in the main Django project. We provide sample e-mail templates here in the saas/templates/notification/ directory.

Release Notes

Tested with

  • Python: 3.7, Django: 3.2 (LTS)
  • Python: 3.10, Django: 4.2 (latest)
  • Python: 2.7, Django: 1.11 (legacy) - use testsite/requirements-legacy.txt

0.20.4

  • accounts for upper/lower case email during group buy
  • enables filter by provider in /api/pricing
  • removes b'' marker in downloads while being py27-compatible

previous release notes

djaodjin-saas's People

Contributors

amirraouf avatar amizya avatar deep-chill avatar dependabot[bot] avatar dnohales avatar gealmeida avatar knivets avatar rene-armida avatar smirolo avatar stephanerob avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

djaodjin-saas's Issues

Enable a manager to cancel a balance due

If a subscriber places an order and the charge is denied, there is a balance due on the account. There should be an API to cancel balance dues that is known impossible to be recovered. The API will create the appropriate Transaction.

The project needs some additional clarifications

I was interested in exploring more of this project but some of the terms and relationships used are not clear -- even after reading the documentation.

  1. What is provider and why are they needed ? If someone wants to launch their own saas site, how does provider even come into play ? I am not sure what was the thought process in adding a organization -- provider relationship

  2. In an organization only manager/admin can make POST requests ? Contributors/users only can make GET requests ? What if the saas business needs to be able to provide write access to organization users, but only for the non admin section -- all the payment/billing/admin sections of the organization are not accessible to a regular user.

Javascript error on the subscriber retention screen

The following errors are reported when loading the subscriber retention screen:

ReferenceError: params is not defined
    at g.$scope.refresh (djaodjin-saas-angular.js:499)
    at Object.fn (djaodjin-saas-angular.js:480)
    at g.$get.g.$digest (angular.js:12636)
    at g.scopePrototype.$digest (hint.js:1468)
    at g.$get.g.$apply (angular.js:12901)
    at g.scopePrototype.$apply (hint.js:1478)
    at angular.js:1496
    at Object.e [as invoke] (angular.js:4059)
    at d (angular.js:1494)
    at Object.Oa.resumeBootstrap (angular.js:1516)
ReferenceError: params is not defined
    at g.$scope.refresh (djaodjin-saas-angular.js:499)
    at Object.fn (djaodjin-saas-angular.js:487)
    at g.$get.g.$digest (angular.js:12636)
    at g.scopePrototype.$digest (hint.js:1468)
    at g.$get.g.$apply (angular.js:12901)
    at g.scopePrototype.$apply (hint.js:1478)
    at angular.js:1496
    at Object.e [as invoke] (angular.js:4059)
    at d (angular.js:1494)
    at Object.Oa.resumeBootstrap (angular.js:1516)

Processor Dependency issue

While adding Organisation via Admin Panel I found a Processor dependency issue.

  • Processor field is mandatory but not every Organisation is Processor
  • If I try to add Processor Organisation then again It will ask for a Processor
  • Its never ending process. Please Make Processor as optional

Frontend issues

  1. "Roles" link in the header navigation is broken
  2. "Unsubscribe Now" button is broken here
  3. Here "Registered" table seems to be broken (no data)
  4. Here "Churned" and "Registered" table filters are filtering the "Active" table, instead of the respective ones

Order confirmation or payment successful instead of and

Currently, a order_executed signal is executed when a user clicks on subscribe from the /cart/ page, then a charge_updated is triggered when the charge is successful. The resulting email notification lead to confusion for some subscribers. order_executed should only be triggered when the charge is not successful.

Today's sale in local time

In the dasboard page, ReceivablesListAPIView is used to show Today's sale. The template should be updated to pass an ends_at to the API such that the result is "Today" in local time, not utc.

AttributeError raised during payment

When attempting to submit a payment while registering a test account, I received this error (snipped from the Django log output):

[03/Apr/2015 10:46:29] "GET /cowork/billing/cowork_user6/cart/ HTTP/1.1" 200 41804
127.0.0.1 cowork_user6 INFO [03/Apr/2015:10:47:41 +0000] [checkout] save subscription of cowork_user6 to open-space
127.0.0.1 cowork_user6 INFO [03/Apr/2015:10:47:43 +0000] Updated card information for cowork_user6 on processor (cus_5zXzZ56hXkd7gT)
127.0.0.1 cowork_user6 ERROR [03/Apr/2015:10:47:44 +0000] InvalidRequestError for charge of 17999 cents to cowork_user6
- - ERROR [03/Apr/2015:10:47:44 +0000] Internal Server Error: /cowork/billing/cowork_user6/cart/
Traceback (most recent call last):
  File "/home/marmida/develop/djaodjin/lib/python2.7/site-packages/django/core/handlers/base.py", line 111, in get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/home/marmida/develop/djaodjin/lib/python2.7/site-packages/django/contrib/auth/decorators.py", line 21, in _wrapped_view
    return view_func(request, *args, **kwargs)
  File "/home/marmida/develop/djaodjin/lib/python2.7/site-packages/signup/decorators.py", line 116, in _wrapped_view
    return view_func(request, *args, **kwargs)
  File "/home/marmida/develop/djaodjin/lib/python2.7/site-packages/saas/decorators.py", line 389, in _wrapped_view
    return view_func(request, *args, **kwargs)
  File "/home/marmida/develop/djaodjin/reps/djaodjin/djaodjin/decorators.py", line 33, in _wrapped_view
    return view_func(request, *args, **kwargs)
  File "/home/marmida/develop/djaodjin/lib/python2.7/site-packages/django/views/generic/base.py", line 69, in view
    return self.dispatch(request, *args, **kwargs)
  File "/home/marmida/develop/djaodjin/lib/python2.7/site-packages/saas/views/billing.py", line 389, in dispatch
    return super(CartBaseView, self).dispatch(*args, **kwargs)
  File "/home/marmida/develop/djaodjin/lib/python2.7/site-packages/django/views/generic/base.py", line 87, in dispatch
    return handler(request, *args, **kwargs)
  File "/home/marmida/develop/djaodjin/lib/python2.7/site-packages/django/views/generic/edit.py", line 173, in post
    return self.form_valid(form)
  File "/home/marmida/develop/djaodjin/lib/python2.7/site-packages/saas/views/billing.py", line 255, in form_valid
    return self.form_invalid(form)
  File "/home/marmida/develop/djaodjin/lib/python2.7/site-packages/django/views/generic/edit.py", line 86, in form_invalid
    return self.render_to_response(self.get_context_data(form=form))
  File "/home/marmida/develop/djaodjin/lib/python2.7/site-packages/saas/views/billing.py", line 614, in get_context_data
    context = super(CartView, self).get_context_data(**kwargs)
  File "/home/marmida/develop/djaodjin/lib/python2.7/site-packages/saas/views/billing.py", line 116, in get_context_data
    context.update(PROCESSOR_BACKEND.retrieve_card(self.customer))
  File "/home/marmida/develop/djaodjin/lib/python2.7/site-packages/saas/backends/stripe_processor.py", line 204, in retrieve_card
    if p_customer.default_card:
  File "/home/marmida/develop/djaodjin/lib/python2.7/site-packages/stripe/resource.py", line 70, in __getattr__
    raise AttributeError(*err.args)
AttributeError: default_card
[03/Apr/2015 10:47:45] "POST /cowork/billing/cowork_user6/cart/ HTTP/1.1" 500 217777

This occurs both with Stripe 1.21.0 and 1.22.1, the latest.

Export coupon applications as a CSV

Allow the user to download a CSV showing the instances of coupons being redeemed. This should include one row per coupon invocation. This should include:

  • coupon code
  • coupon discount percentage
  • user's name
  • user's email?
  • plan
  • amount paid

Error response received from Stripe during test payments

Using a test card and submitting a payment leads to this warning banner being displayed across the top of the reloaded credit card form page:

Received unknown parameter: statement_description

The development server console shows the following:

127.0.0.1 cowork_user9 ERROR [03/Apr/2015:11:04:21 +0000] InvalidRequestError for charge of 17999 cents to cowork_user9

This message originates from the Stripe API, which is responding to our API submission of the payment with the following:

error:
type: "invalid_request_error"
message: "Received unknown parameter: statement_description"
param: "statement_description"

See:

LOGGER.error('InvalidRequestError for charge of %d cents to %s',

Refactor download views

We have added a number of CSV download views recently. These integrate with the django_rest_framework via SmartListMixin, which provides filtering. All of our download views should be refactored as follows:

  1. extract the CSV generation code into an abstract parent class, e.g. CSVDownloadView. This would inherit from View.
  2. extract the queryset fetching into a mixin with a get_queryset method.
  3. each concrete download view inherits from the above mixin and the download view.

out-of-system transactions

  1. Currently it is possible to export all transactions in [ledger](out-of-system transactions) format. It should also be possible to export transactions in a format supported by QuickBooks.

  2. Currently the ledger import manage.py command will create all transactions in the text file into the database. What it should do is reconcile the transactions between the text file and the database and only insert new transactions. As a result, importing the same ledger file a second time should not change the database.

  3. Import should also support a format outputted by QuickBooks.

Invalid routing number triggers cryptic validation complaint: "Routing Number field(s) cannot be empty."

Trying to start a withdrawal with an invalid bank account number causes the following error message to be displayed to the user: Routing Number field(s) cannot be empty.

routing_validation

This is counter-intuitive, because the user did provide a routing number (it's just invalid, and Stripes' JS library has rejected it -- unfortunately, that function does nothing more than indicate validation success, without any explanantion. See: https://stripe.com/docs/stripe.js?#bank-account-validateRoutingNumber)

Enable adding transactions done out of app

It often happens that for group payments, the provider will receive a check in the mail. To keep metrics accurate, it must be possible to add transactions that were not executed online.

Cannot register with non-ASCII content in form

Validation rules fire that prevent the entry of non-ASCII content into the registration form. See the attached image.

unicode_reg

This may be specific to the wrapping site, or may be part of the djaodjin-saas core. I'm not certain. It should be the case that the registration form instead allows non-ASCII input.

Coupon admin's filter feature usability problems

The filter's auto-refresh on the coupon admin page fires off too eagerly. I made a short video of this behavior:
https://www.dropbox.com/sc/1hs0fpfp36agnuq/AAAlY-schXOxmYx0CLe5u9UQa

This has some negative effects:

  1. it interrupts the user's typing, forcing them to type only one character per refresh
  2. it loses focus, causing the user to re-focus on the text box after each refresh

In addition, it's confusing because:

  1. the filter matches unexpected rows. I tried some number input that I figured should not match, and yet, it still found some rows with nothing obviously matched.
  2. it's on the same line as the data-entry form for adding a new coupon. It's not immediately clear that one of these adds a row, while one filters the current results.
  3. if no results are found, the display loses the input control for the filter expression, forcing the user to reload or hit back.

Add "delete" for plans

Add a "delete" button to plans that have no subscribers.

This applies to plans that have never had any subscribers. Plans that have had at least one subscriber cannot be deleted; they can only be deactivated. Peleted plans are physically removed from the database.

"&dash;" appears on front-end of the test site

This is apparently because of our use of proxies, which causes the content on pages to go through a pass-through, and that causes a second round of HTML entity encoding that isn't being handled correctly. Investigate.

Investigate to merge Charge.payment_successful on checkout request in RazorPay setup

The flow to subscribe and pay for a plan is as follow:

  1. POST to /api/cart/
  2. GET /api/billing/:organization/checkout/
  3. compute the total amount to charge from the list of invoicables.
  4. POST to RazorPay
  5. POST /api/billing/:organization/checkout/ with {“processor_token”: token-returned-by-razorpay}
    This will call RazorpayBackend.create_charge_on_card to capture the total amount of invoicables.
  6. GET /api/billing/charges/:charge (:charge being return by the previous call as "processor_key")
    This will call Charge.payment_successful and create the Transaction in the database as well as switch Charge.state from "created" to “done".

RazorPay works somewhat differently from Stripe. The processor_token passed back by RazorPay is an actual charge id. The processor_token passed back by Stripe is a card id. It is quite possible that payment_successful could be called after razorpay.capture and make step #6 optional in RazorPay setup.

python 2/3 issues

  1. While trying to run python ./manage.py load_test_transactions with python3 the following error is thrown:
    TypeError: Population must be a sequence or set. For dicts, use list(d).
    https://github.com/djaodjin/djaodjin-saas/blob/master/testsite/management/commands/load_test_transactions.py#L206
  2. There is a print x statement without braces at the same file as the previous isse
  3. While visiting http://localhost:8000/billing/cowork-master/cart/ page in a browser with python2 the following error is thrown:
    'module' object has no attribute 'zip_longest'
    https://github.com/djaodjin/djaodjin-saas/blob/master/saas/views/billing.py#L718

Show refunds in revenue graph

Right now the total revenue is displayed, not the actual profit. A new line
in the chart (and in the table should show the refunds).

Export financial transactions as CSV

Two admin views show financial transactions: "funds" and "billing." In both cases, we want to add both (1) the same style of date picker as on the "Retention" screen, allowing for filtering the transactions by date, and (2) a CSV download of the transaction data.

TODO: specify the CSV fields in each case.

Add coupon code to receipt email

Currently, the email receipt sent to the provider / admin includes the coupon percentage, but not the code, for each registration. Add the code to this email.

Move revenue / financials view backwards and forwards in time

Allow the user viewing the financial revenue graph in the provider admin the ability to move that view forward or back in time. Because the number of months determines the width of the page, it may be best to only allow them to slide the start and end dates, together, forward by N months, instead of allowing them to choose an arbitrary start and end date (and thus, require more horizontal space on the page).

Help on http/404 Forbidden Error

First, thank you for th initiative of adding value to this nice project.

We are not sure where to post, but do you have any clue why we we are experiencing 404-Forbidden error trying to access http://127.0.0.1:8000/saas/root as per the setup steps described in the readme ?

We would appreciate your feedback.

weekly revenue e-mails

Create a manage.py command that can be run on a weekly basis to send an e-mail report of the revenue for the past week (Same numbers as shown on the Revenue table, i.e. "Total Sales", "New Sales", "Churned Sales", "Payments", "Refunds").
Furthermore, show the percentage increase/decrease vs. the past week and the same week a year ago.

global name 'managed_organization' is not defined

I am getting this error after logging in and signing the terms and condition. Traceback

Environment:

Request Method: GET
Request URL: http://127.0.0.1:8000/saas/

Django Version: 1.5
Python Version: 2.7.5
Installed Applications:
('gunicorn',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.admin',
'django.contrib.markup',
'app_metrics',
'saas',
'testsite')
Installed Middleware:
('django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware')

Traceback:
File "/home/skbohra/code/saass/vc/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response

  1.                     response = callback(request, _callback_args, *_callback_kwargs)
    
    File "/home/skbohra/code/saass/vc/lib/python2.7/site-packages/django/views/generic/base.py" in view
  2.         return self.dispatch(request, _args, *_kwargs)
    
    File "/home/skbohra/code/saass/vc/lib/python2.7/site-packages/django/utils/decorators.py" in _wrapper
  3.         return bound_func(_args, *_kwargs)
    
    File "/home/skbohra/code/saass/saas/decorators.py" in _wrapped_view
  4.                     return view_func(request, _args, *_kwargs)
    
    File "/home/skbohra/code/saass/vc/lib/python2.7/site-packages/django/utils/decorators.py" in bound_func
  5.             return func(self, _args2, *_kwargs2)
    
    File "/home/skbohra/code/saass/saas/views/profile.py" in dispatch
  6.     return super(OrganizationListView, self).dispatch(_args, *_kwargs)
    
    File "/home/skbohra/code/saass/vc/lib/python2.7/site-packages/django/views/generic/base.py" in dispatch
  7.     return handler(request, _args, *_kwargs)
    
    File "/home/skbohra/code/saass/vc/lib/python2.7/site-packages/django/views/generic/list.py" in get
  8.     self.object_list = self.get_queryset()
    
    File "/home/skbohra/code/saass/saas/views/profile.py" in get_queryset
  9.     return managed_organization(self.request.user)
    

Exception Type: NameError at /saas/
Exception Value: global name 'managed_organization' is not defined

Cannot create database schema

Getting the follwing error using the migrate command.

python ./manage.py migrate --run-syncdb --noinput
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying admin.0002_logentry_remove_auto_add... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying auth.0007_alter_validators_add_error_messages... OK
Applying auth.0008_alter_user_username_max_length... OK
Applying saas.0001_initial...Traceback (most recent call last):
File "./manage.py", line 22, in
execute_from_command_line(sys.argv)
File "C:\Python35\lib\site-packages\django\core\management_init_.py", line 363, in execute_from_command_line
utility.execute()
File "C:\Python35\lib\site-packages\django\core\management_init_.py", line 355, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "C:\Python35\lib\site-packages\django\core\management\base.py", line 283, in run_from_argv
self.execute(*args, **cmd_options)
File "C:\Python35\lib\site-packages\django\core\management\base.py", line 330, in execute
output = self.handle(*args, **options)
File "C:\Python35\lib\site-packages\django\core\management\commands\migrate.py", line 204, in handle
fake_initial=fake_initial,
File "C:\Python35\lib\site-packages\django\db\migrations\executor.py", line 115, in migrate
state = self._migrate_all_forwards(state, plan, full_plan, fake=fake, fake_initial=fake_initial)
File "C:\Python35\lib\site-packages\django\db\migrations\executor.py", line 145, in _migrate_all_forwards
state = self.apply_migration(state, migration, fake=fake, fake_initial=fake_initial)
File "C:\Python35\lib\site-packages\django\db\migrations\executor.py", line 244, in apply_migration
state = migration.apply(state, schema_editor)
File "C:\Python35\lib\site-packages\django\db\migrations\migration.py", line 129, in apply
operation.database_forwards(self.app_label, schema_editor, old_state, project_state)
File "C:\Python35\lib\site-packages\django\db\migrations\operations\models.py", line 97, in database_forwards
schema_editor.create_model(model)
File "C:\Python35\lib\site-packages\django\db\backends\base\schema.py", line 271, in create_model
self.deferred_sql.append(self.create_fk_sql(model, field, "fk%(to_table)s%(to_column)s"))
File "C:\Python35\lib\site-packages\django\db\backends\base\schema.py", line 957, in create_fk_sql
"name": self.quote_name(self.create_index_name(model, [from_column], suffix=suffix)),
File "C:\Python35\lib\site-packages\django\db\backends\base\schema.py", line 860, in create_index_name
index_name = '%s
%s
%s' % (table_name, '
'.join(column_names), hash_suffix_part)
TypeError: sequence item 0: expected str instance, bytes found

Cleaning up (amount, unit) tuples

The class Price (models.py) was introduced recently. Lots of places and interfaces still rely on passing an amount and unit instead of a Price object. To be updated.

Second there are 'usd' defaults at too many places in the code. These should be factored. A DEFAULT_UNIT should also be introduced into settings.py

settle pending charges before asking to pay a balance due

In case the API call to the charge status in the /receipt/ page is interrupted or the webhook is not triggered, a Charge might be stuck in a pending state. Before showing a balance due, in-flight pending charges should get a chance to be settled and their status updated.

download printable quote/invoice

Currently it is possible to print a charge receipt. It should also be possible to print an invoice, i.e. same information but before the charge is made. This most likely require to rethink the checkout process.

Not ready for Django 2.x! TypeError: __init__() missing 1 required positional argument: 'on_delete'

I followed the installation instructions, installed djaodjin-saas with pip in my virtual environment (Python 3.6).

So as a result this is my pip freeze:

$ pip freeze
certifi==2018.1.18
chardet==3.0.4
Django==2.0.3
django-countries==5.2
django-extra-views==0.10.0
django-localflavor==2.0
djangorestframework==3.7.7
djaodjin-saas==0.3.1
idna==2.6
Markdown==2.6.11
python-dateutil==2.7.0
pytz==2018.3
razorpay==1.1.1
requests==2.18.4
six==1.11.0
stripe==1.79.1
urllib3==1.22

I typed in all the settings and url modification as in the docs, set up my stripe test credentials, and run the server.

$ python manage.py runserver
Unhandled exception in thread started by <function check_errors.<locals>.wrapper at 0x10305ee18>
Traceback (most recent call last):
  File "/me/tmp/stripe-django/env/lib/python3.6/site-packages/django/utils/autoreload.py", line 225, in wrapper
    fn(*args, **kwargs)
  File "/me/tmp/stripe-django/env/lib/python3.6/site-packages/django/core/management/commands/runserver.py", line 112, in inner_run
    autoreload.raise_last_exception()
  File "/me/tmp/stripe-django/env/lib/python3.6/site-packages/django/utils/autoreload.py", line 248, in raise_last_exception
    raise _exception[1]
  File "/me/tmp/stripe-django/env/lib/python3.6/site-packages/django/core/management/__init__.py", line 327, in execute
    autoreload.check_errors(django.setup)()
  File "/me/tmp/stripe-django/env/lib/python3.6/site-packages/django/utils/autoreload.py", line 225, in wrapper
    fn(*args, **kwargs)
  File "/me/tmp/stripe-django/env/lib/python3.6/site-packages/django/__init__.py", line 24, in setup
    apps.populate(settings.INSTALLED_APPS)
  File "/me/tmp/stripe-django/env/lib/python3.6/site-packages/django/apps/registry.py", line 112, in populate
    app_config.import_models()
  File "/me/tmp/stripe-django/env/lib/python3.6/site-packages/django/apps/config.py", line 198, in import_models
    self.models_module = import_module(models_module_name)
  File "/me/tmp/stripe-django/env/lib/python3.6/importlib/__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 994, in _gcd_import
  File "<frozen importlib._bootstrap>", line 971, in _find_and_load
  File "<frozen importlib._bootstrap>", line 955, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 665, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 678, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "/me/tmp/stripe-django/env/lib/python3.6/site-packages/saas/models.py", line 211, in <module>
    class Organization(models.Model):
  File "/me/tmp/stripe-django/env/lib/python3.6/site-packages/saas/models.py", line 266, in Organization
    'Organization', null=True, blank=True, related_name='processes')
TypeError: __init__() missing 1 required positional argument: 'on_delete'

Please advise if I need to downgrade the Django version or what to do.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.