Install Custom Registration Form Plugin on Tutor

Hello!

I made a fork of OpenCraft Project for create a custom extra field on OpenEdx registration Form.

How i can properly install on Tutor as a Plugin?

Can give me directions?

2 Likes

What did you try? Where are you stuck? Did you take a look at https://docs.tutor.overhang.io/configuration.html#installing-extra-xblocks-and-requirements?

So … I have doubts on how to structure it. Would this be possible in just one tutor plugin?
Or do I have to add this extra requirement and make a tutor plugin to add changes on configs?

The Edx documentation says the following:

"In the lms.env.json file, set the REGISTRATION_EXTENSION_FORM setting to the path of the Django form that you just created, as a dot- separated Python string.

For example, if your form is named “ExampleExtensionForm” and is located at “path / to / the_form.py”, the value of the setting is path.to.the_form.ExampleExtensionForm.
"
Documentation link: 4.4. Adding Custom Fields to the Registration Page — Installing, Configuring, and Running the Open edX Platform documentation

How to do it properly?

This is possible in just one plugin. You will need to add the extra requirement and add the config changes to the plugin. In theory you could add the “openedx-dockerfile-pre-assets” patch to your plugin and avoid the extra requirement (with RUN pip install myformplugin), but that would be confusing.

@ejklock Could you make such a plug-in ?
I’m also trying to make custom registration fields, and it would great if you can help.

after follow steps in


and new field appeared on registration form, when i press register button the error message appear as
below:
 lms_1             | 2020-09-30 08:01:26,568 ERROR 11 [root] signals.py:21 - Uncaught exception from None
lms_1             | Traceback (most recent call last):
lms_1             |   File "/openedx/venv/local/lib/python2.7/site-packages/django/core/handlers/exception.py", line 41, in inner
lms_1             |     response = get_response(request)
lms_1             |   File "/openedx/venv/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 249, in _legacy_get_response
lms_1             |     response = self._get_response(request)
lms_1             |   File "/openedx/venv/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 187, in _get_response
lms_1             |     response = self.process_exception_by_middleware(e, request)
lms_1             |   File "/openedx/venv/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 185, in _get_response
lms_1             |     response = wrapped_callback(request, *callback_args, **callback_kwargs)
lms_1             |   File "/openedx/venv/local/lib/python2.7/site-packages/django/views/decorators/csrf.py", line 58, in wrapped_view
lms_1             |     return view_func(*args, **kwargs)
lms_1             |   File "/openedx/venv/local/lib/python2.7/site-packages/django/views/generic/base.py", line 68, in view
lms_1             |     return self.dispatch(request, *args, **kwargs)
lms_1             |   File "/openedx/venv/local/lib/python2.7/site-packages/django/utils/decorators.py", line 67, in _wrapper
lms_1             |     return bound_func(*args, **kwargs)
lms_1             |   File "/openedx/venv/local/lib/python2.7/site-packages/django/utils/decorators.py", line 63, in bound_func
lms_1             |     return func.__get__(self, type(self))(*args2, **kwargs2)
lms_1             |   File "/openedx/venv/local/lib/python2.7/site-packages/django/utils/decorators.py", line 67, in _wrapper
lms_1             |     return bound_func(*args, **kwargs)
lms_1             |   File "/openedx/venv/local/lib/python2.7/site-packages/django/views/decorators/debug.py", line 76, in sensitive_post_parameters_wrapper
lms_1             |     return view(request, *args, **kwargs)
lms_1             |   File "/openedx/venv/local/lib/python2.7/site-packages/django/utils/decorators.py", line 63, in bound_func
lms_1             |     return func.__get__(self, type(self))(*args2, **kwargs2)
lms_1             |   File "/openedx/edx-platform/openedx/core/djangoapps/user_api/views.py", line 179, in dispatch
lms_1             |     return super(RegistrationView, self).dispatch(request, *args, **kwargs)
lms_1             |   File "/openedx/venv/local/lib/python2.7/site-packages/rest_framework/views.py", line 489, in dispatch
lms_1             |     response = self.handle_exception(exc)
lms_1             |   File "/openedx/venv/local/lib/python2.7/site-packages/rest_framework/views.py", line 449, in handle_exception
lms_1             |     self.raise_uncaught_exception(exc)
lms_1             |   File "/openedx/venv/local/lib/python2.7/site-packages/rest_framework/views.py", line 486, in dispatch
lms_1             |     response = handler(request, *args, **kwargs)
lms_1             |   File "/openedx/venv/local/lib/python2.7/site-packages/django/utils/decorators.py", line 67, in _wrapper
lms_1             |     return bound_func(*args, **kwargs)
lms_1             |   File "/openedx/venv/local/lib/python2.7/site-packages/django/views/decorators/csrf.py", line 58, in wrapped_view
lms_1             |     return view_func(*args, **kwargs)
lms_1             |   File "/openedx/venv/local/lib/python2.7/site-packages/django/utils/decorators.py", line 63, in bound_func
lms_1             |     return func.__get__(self, type(self))(*args2, **kwargs2)
lms_1             |   File "/openedx/edx-platform/openedx/core/djangoapps/user_api/views.py", line 154, in post
lms_1             |     user = create_account_with_params(request, data)
lms_1             |   File "/openedx/edx-platform/openedx/core/djangoapps/user_authn/views/register.py", line 162, in create_account_with_params
lms_1             |     (user, profile, registration) = do_create_account(form, custom_form)
lms_1             |   File "/openedx/edx-platform/common/djangoapps/student/helpers.py", line 628, in do_create_account
lms_1             |     custom_model.save()
lms_1             |   File "/openedx/venv/local/lib/python2.7/site-packages/django/db/models/base.py", line 808, in save
lms_1             |     force_update=force_update, update_fields=update_fields)
lms_1             |   File "/openedx/venv/local/lib/python2.7/site-packages/django/db/models/base.py", line 838, in save_base
lms_1             |     updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)
lms_1             |   File "/openedx/venv/local/lib/python2.7/site-packages/django/db/models/base.py", line 924, in _save_table
lms_1             |     result = self._do_insert(cls._base_manager, using, fields, update_pk, raw)
lms_1             |   File "/openedx/venv/local/lib/python2.7/site-packages/django/db/models/base.py", line 963, in _do_insert
lms_1             |     using=using, raw=raw)
lms_1             |   File "/openedx/venv/local/lib/python2.7/site-packages/django/db/models/manager.py", line 85, in manager_method
lms_1             |     return getattr(self.get_queryset(), name)(*args, **kwargs)
lms_1             |   File "/openedx/venv/local/lib/python2.7/site-packages/django/db/models/query.py", line 1079, in _insert
lms_1             |     return query.get_compiler(using=using).execute_sql(return_id)
lms_1             |   File "/openedx/venv/local/lib/python2.7/site-packages/django/db/models/sql/compiler.py", line 1112, in execute_sql
lms_1             |     cursor.execute(sql, params)
lms_1             |   File "/openedx/venv/local/lib/python2.7/site-packages/django/db/backends/utils.py", line 64, in execute
lms_1             |     return self.cursor.execute(sql, params)
lms_1             |   File "/openedx/venv/local/lib/python2.7/site-packages/django/db/utils.py", line 94, in __exit__
lms_1             |     six.reraise(dj_exc_type, dj_exc_value, traceback)
lms_1             |   File "/openedx/venv/local/lib/python2.7/site-packages/django/db/backends/utils.py", line 64, in execute
lms_1             |     return self.cursor.execute(sql, params)
lms_1             |   File "/openedx/venv/local/lib/python2.7/site-packages/django/db/backends/mysql/base.py", line 101, in execute
lms_1             |     return self.cursor.execute(query, args)
lms_1             |   File "/openedx/venv/local/lib/python2.7/site-packages/MySQLdb/cursors.py", line 205, in execute
lms_1             |     self.errorhandler(self, exc, value)
lms_1             |   File "/openedx/venv/local/lib/python2.7/site-packages/MySQLdb/connections.py", line 36, in defaulterrorhandler
lms_1             |     raise errorclass, errorvalue
lms_1             | ProgrammingError: (1146, "Table 'openedx.custom_reg_form_extrainfo' doesn't exist")
lms_1             | 2020-09-30 08:01:26,584 ERROR 11 [django.request] exception.py:135 - Internal Server Error: /user_api/v1/account/registration/
lms_1             | Traceback (most recent call last):
lms_1             |   File "/openedx/venv/local/lib/python2.7/site-packages/django/core/handlers/exception.py", line 41, in inner
lms_1             |     response = get_response(request)
lms_1             |   File "/openedx/venv/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 249, in _legacy_get_response
lms_1             |     response = self._get_response(request)
lms_1             |   File "/openedx/venv/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 187, in _get_response
lms_1             |     response = self.process_exception_by_middleware(e, request)
lms_1             |   File "/openedx/venv/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 185, in _get_response
lms_1             |     response = wrapped_callback(request, *callback_args, **callback_kwargs)
lms_1             |   File "/openedx/venv/local/lib/python2.7/site-packages/django/views/decorators/csrf.py", line 58, in wrapped_view
lms_1             |     return view_func(*args, **kwargs)
lms_1             |   File "/openedx/venv/local/lib/python2.7/site-packages/django/views/generic/base.py", line 68, in view
lms_1             |     return self.dispatch(request, *args, **kwargs)
lms_1             |   File "/openedx/venv/local/lib/python2.7/site-packages/django/utils/decorators.py", line 67, in _wrapper
lms_1             |     return bound_func(*args, **kwargs)
lms_1             |   File "/openedx/venv/local/lib/python2.7/site-packages/django/utils/decorators.py", line 63, in bound_func
lms_1             |     return func.__get__(self, type(self))(*args2, **kwargs2)
lms_1             |   File "/openedx/venv/local/lib/python2.7/site-packages/django/utils/decorators.py", line 67, in _wrapper
lms_1             |     return bound_func(*args, **kwargs)
lms_1             |   File "/openedx/venv/local/lib/python2.7/site-packages/django/views/decorators/debug.py", line 76, in sensitive_post_parameters_wrapper
lms_1             |     return view(request, *args, **kwargs)
lms_1             |   File "/openedx/venv/local/lib/python2.7/site-packages/django/utils/decorators.py", line 63, in bound_func
lms_1             |     return func.__get__(self, type(self))(*args2, **kwargs2)
lms_1             |   File "/openedx/edx-platform/openedx/core/djangoapps/user_api/views.py", line 179, in dispatch
lms_1             |     return super(RegistrationView, self).dispatch(request, *args, **kwargs)
lms_1             |   File "/openedx/venv/local/lib/python2.7/site-packages/rest_framework/views.py", line 489, in dispatch
lms_1             |     response = self.handle_exception(exc)
lms_1             |   File "/openedx/venv/local/lib/python2.7/site-packages/rest_framework/views.py", line 449, in handle_exception
lms_1             |     self.raise_uncaught_exception(exc)
lms_1             |   File "/openedx/venv/local/lib/python2.7/site-packages/rest_framework/views.py", line 486, in dispatch
lms_1             |     response = handler(request, *args, **kwargs)
lms_1             |   File "/openedx/venv/local/lib/python2.7/site-packages/django/utils/decorators.py", line 67, in _wrapper
lms_1             |     return bound_func(*args, **kwargs)
lms_1             |   File "/openedx/venv/local/lib/python2.7/site-packages/django/views/decorators/csrf.py", line 58, in wrapped_view
lms_1             |     return view_func(*args, **kwargs)
lms_1             |   File "/openedx/venv/local/lib/python2.7/site-packages/django/utils/decorators.py", line 63, in bound_func
lms_1             |     return func.__get__(self, type(self))(*args2, **kwargs2)
lms_1             |   File "/openedx/edx-platform/openedx/core/djangoapps/user_api/views.py", line 154, in post
lms_1             |     user = create_account_with_params(request, data)
lms_1             |   File "/openedx/edx-platform/openedx/core/djangoapps/user_authn/views/register.py", line 162, in create_account_with_params
lms_1             |     (user, profile, registration) = do_create_account(form, custom_form)
lms_1             |   File "/openedx/edx-platform/common/djangoapps/student/helpers.py", line 628, in do_create_account
lms_1             |     custom_model.save()
lms_1             |   File "/openedx/venv/local/lib/python2.7/site-packages/django/db/models/base.py", line 808, in save
lms_1             |     force_update=force_update, update_fields=update_fields)
lms_1             |   File "/openedx/venv/local/lib/python2.7/site-packages/django/db/models/base.py", line 838, in save_base
lms_1             |     updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)
lms_1             |   File "/openedx/venv/local/lib/python2.7/site-packages/django/db/models/base.py", line 924, in _save_table
lms_1             |     result = self._do_insert(cls._base_manager, using, fields, update_pk, raw)
lms_1             |   File "/openedx/venv/local/lib/python2.7/site-packages/django/db/models/base.py", line 963, in _do_insert
lms_1             |     using=using, raw=raw)
lms_1             |   File "/openedx/venv/local/lib/python2.7/site-packages/django/db/models/manager.py", line 85, in manager_method
lms_1             |     return getattr(self.get_queryset(), name)(*args, **kwargs)
lms_1             |   File "/openedx/venv/local/lib/python2.7/site-packages/django/db/models/query.py", line 1079, in _insert
lms_1             |     return query.get_compiler(using=using).execute_sql(return_id)
lms_1             |   File "/openedx/venv/local/lib/python2.7/site-packages/django/db/models/sql/compiler.py", line 1112, in execute_sql
lms_1             |     cursor.execute(sql, params)
lms_1             |   File "/openedx/venv/local/lib/python2.7/site-packages/django/db/backends/utils.py", line 64, in execute
lms_1             |     return self.cursor.execute(sql, params)
lms_1             |   File "/openedx/venv/local/lib/python2.7/site-packages/django/db/utils.py", line 94, in __exit__
lms_1             |     six.reraise(dj_exc_type, dj_exc_value, traceback)
lms_1             |   File "/openedx/venv/local/lib/python2.7/site-packages/django/db/backends/utils.py", line 64, in execute
lms_1             |     return self.cursor.execute(sql, params)
lms_1             |   File "/openedx/venv/local/lib/python2.7/site-packages/django/db/backends/mysql/base.py", line 101, in execute
lms_1             |     return self.cursor.execute(query, args)
lms_1             |   File "/openedx/venv/local/lib/python2.7/site-packages/MySQLdb/cursors.py", line 205, in execute
lms_1             |     self.errorhandler(self, exc, value)
lms_1             |   File "/openedx/venv/local/lib/python2.7/site-packages/MySQLdb/connections.py", line 36, in defaulterrorhandler
lms_1             |     raise errorclass, errorvalue
lms_1             | ProgrammingError: (1146, "Table 'openedx.custom_reg_form_extrainfo' doesn't exist")

Hi,
I believe you need a YAML plugin like this, and migrations after that.


name: myplugin
version: 0.1.0
patches:
lms-env: |
“ADDL_INSTALLED_APPS”: [“custom_reg_form”],
“ENABLE_COMBINED_LOGIN_REGISTRATION”: true,
“REGISTRATION_EXTENSION_FORM”: “custom_reg_form.forms.ExtraInfoForm”
cms-env: |
“ENABLE_COMBINED_LOGIN_REGISTRATION”: true

1 Like

when i run :
tutor plugins list
this error raise:
Traceback (most recent call last):
File “main.py”, line 21, in
File “tutor/commands/cli.py”, line 37, in main
File “tutor/commands/plugins.py”, line 121, in add_plugin_commands
File “tutor/plugins.py”, line 236, in iter_installed
File “tutor/plugins.py”, line 203, in iter_installed
File “tutor/plugins.py”, line 150, in iter_installed
File “tutor/serialize.py”, line 7, in load
File “site-packages/yaml/init.py”, line 114, in load
File “site-packages/yaml/constructor.py”, line 49, in get_single_data
File “site-packages/yaml/composer.py”, line 36, in get_single_node
File “site-packages/yaml/composer.py”, line 55, in compose_document
File “site-packages/yaml/composer.py”, line 84, in compose_node
File “site-packages/yaml/composer.py”, line 133, in compose_mapping_node
File “site-packages/yaml/composer.py”, line 84, in compose_node
File “site-packages/yaml/composer.py”, line 127, in compose_mapping_node
File “site-packages/yaml/parser.py”, line 98, in check_event
File “site-packages/yaml/parser.py”, line 439, in parse_block_mapping_key
yaml.parser.ParserError: while parsing a block mapping
in “/root/.local/share/tutor-plugins/myplugin.yml”, line 4, column 3
expected , but found ‘,’
in “/root/.local/share/tutor-plugins/myplugin.yml”, line 5, column 45
[6488] Failed to execute script main

Please check indentations, and ‘,’

and please don’t forget

$ tutor config save

after last error fixed and enabled the new plugin without errors,
the same error again :disappointed_relieved:
ProgrammingError: (1146, “Table ‘openedx.custom_reg_form_extrainfo’ doesn’t exist”)

@qali thank you very much it work :innocent:

1 Like

how can i make migration after adding new field to custom form?? after i run:
1-tutor plugins enable custom_reg_form
2-tutor config save
3-tutor images build openedx
4-tutor local init
no things is changed, and i get this error:

OperationalError: (1054, “Unknown column ‘favorite_morta’ in ‘field list’”)

You getting error, because your changes must override old models and migrations. To do that

$ tutor local run lms bash

To delete old migrations

$ ./manage.py lms migrate custom_reg_form zero

$ tutor images build openedx

$ tutor local quickstart # you should see new migrations, if not ? just run

$ tutor local run lms bash

$ ./manage.py lms makemigrations

$ ./manage.py lms migrate

2 Likes

great its work thank you very much :star_struck : :innocent:

1 Like

can you share source code of this plugin?

Hi @ejklock,
If this question to me ? Some fork of this repository https://github.com/open-craft/custom-form-app. has good examples. And I agree with you about sharing our experiences and codes. If has not some private or organizational information’s.
Thanks,
Murat

2 Likes

With the help of @ak00001 I could make a few new fields to display on registration page, but on clicking register it freezes and Create Account button greys out.
(Running on Koa)
log tail-100


@regis @qali @ak00001 Can you please help me to resolve this ?

Hi @nadheemabdulla,
It looks like migrations problem, you must rebuild container(production env) after your changes on models, forms and migrations file.

$ tutor images build openedx

$ tutor local quickstart # you should see new migrations, if not ? just run

$ tutor local run lms bash

$ ./manage.py lms makemigrations

$ ./manage.py lms migrate

Thank you so much for the response.
I tried this again-

New registration field is shown but freezes while clicking on Create account
So I tried

which lists

migrations for 'shoppingcart':
  lms/djangoapps/shoppingcart/migrations/0005_auto_20201224_0102.py
    - Remove field course_enrollment from certificateitem
    - Remove field orderitem_ptr from certificateitem
    - Remove field created_by from coupon
    - Remove field coupon from couponredemption
    - Remove field order from couponredemption
    - Remove field user from couponredemption
    - Remove field orderitem_ptr from courseregcodeitem
    - Delete model CourseRegCodeItemAnnotation
    - Remove field created_by from courseregistrationcode
    - Remove field invoice from courseregistrationcode
    - Remove field invoice_item from courseregistrationcode
    - Remove field order from courseregistrationcode
    - Remove field invoiceitem_ptr from courseregistrationcodeinvoiceitem
    - Remove field orderitem_ptr from donation
    - Remove field changed_by from donationconfiguration
    - Remove field invoice from invoicehistory
    - Remove field invoice from invoiceitem
    - Remove field created_by from invoicetransaction
    - Remove field invoice from invoicetransaction
    - Remove field last_modified_by from invoicetransaction
    - Remove field user from order
    - Remove field order from orderitem
    - Remove field user from orderitem
    - Remove field course_enrollment from paidcourseregistration
    - Remove field orderitem_ptr from paidcourseregistration
    - Delete model PaidCourseRegistrationAnnotation
    - Remove field course_enrollment from registrationcoderedemption
    - Remove field order from registrationcoderedemption
    - Remove field redeemed_by from registrationcoderedemption
    - Remove field registration_code from registrationcoderedemption
    - Delete model CertificateItem
    - Delete model Coupon
    - Delete model CouponRedemption
    - Delete model CourseRegCodeItem
    - Delete model CourseRegistrationCode
    - Delete model CourseRegistrationCodeInvoiceItem
    - Delete model Donation
    - Delete model DonationConfiguration
    - Delete model Invoice
    - Delete model InvoiceHistory
    - Delete model InvoiceItem
    - Delete model InvoiceTransaction
    - Delete model Order
    - Delete model OrderItem
    - Delete model PaidCourseRegistration
    - Delete model RegistrationCodeRedemption

on running

I get

MySQLdb._exceptions.ProgrammingError: (1146, "Table 'openedx.shoppingcart_certificateitem' doesn't exist")
django.db.utils.ProgrammingError: (1146, "Table 'openedx.shoppingcart_certificateitem' doesn't exist")

Here is the log

Thank you again for your time.

Hi,
Actually like this error below was my expectation about custom register form.

django.db.utils.OperationalError: (1054, “Unknown column ‘org_inst’ in ‘field list’”)

But there are many different error which is mostly ecommerce related ? Such as this error below

(1146, “Table ‘openedx.shoppingcart_certificateitem’ doesn’t exist”)

But any way, what kind of custom fields do you want to in your registrations form ? So we can try to make a demo for that.

Thanks

1 Like