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?

1 Like

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: https://edx.readthedocs.io/projects/edx-installing-configuring-and-running/en/latest/configuration/customize_registration_page.html

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

1 Like

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

1 Like