Adding Marketer and Sales Admin Events Relationship with User on Open Event Server

In this blog, we will talk about how to add API for adding and displaying events in with a user acts as a Marketer and/or Sales Admin on Open Event Server. The focus is on Model Updation and Schema updation of User.

Model Updation

For the Marketer and Sales Admin events, we’ll update User model as follows

Now, let’s try to understand these relationships.

In this feature, we are providing user to act as a marketer and sales admin for a event.

  1. Both the relationships will return the events in which the user is acting as a Marketer and/or Sales Admin.
  2. There are two custom system roles in model CustomSysRole which are Marketer and Sales Admin. A user can act as these custom system roles with respect to an event.
  3. In this relationship, we will return those events from UserSystemRole model in which a user is acting as Marketer Custom System Role and Sales Admin Custom System Role.
  4. We make use of Event and join UserSystemRole and CustomSysRole where we use that user where UserSystemRole.user_id == User.id , CustomSysRole.id == UserSystemRole.role_id, CustomSysRole.name == “Sales Admin” and then we return events in which Event.id == UserSystemRole.event_id
  5. Similarly, for Marketer events we make use of Event and join UserSystemRole and CustomSysRole where we use that user where UserSystemRole.user_id == User.id , CustomSysRole.id == UserSystemRole.role_id, CustomSysRole.name == “Marketer” and then we return events in which Event.id == UserSystemRole.event_id

Schema Updation

For the Marketer and Sales Admin events, we’ll update UserSchema as follows

Now, let’s try to understand this Schema.

In this feature, we are providing user to act as a marketer and sales admin for a event.

  1. For displaying marketer_events relation self_view is displayed by API v1.user_marketer_events and collection of these events is displayed by API v1.event_list
  2. These APIs will return the Events as schema=”EventSchema”. Here, many=True tells us that this is One to many relationship with Events model.

So, we saw how an user can act as a marketer and/or sales admin for many events.

Resources

Adding Custom System Roles in Open Event Server

In this blog, we will talk about how to add different custom system roles concerning a user on Open Event Server. The focus is on its model and Schema updation.

Model Updation

For the User Table, we’ll update our User Model as follows:

Now, let’s try to understand these hybrid properties.

In this feature, we are providing Admin the rights to see whether a user is acting as a Marketer and / or  Sales Admin of any of the event or not. Here, _is__system_role method is used to check whether an user plays a system role like Marketer, Sales Admin or not. This is done by querying the record from UserSystemRole model. If the record is present then the returned value is True otherwise false.

Schema Updation

For the User Model, we’ll update our Schema as follows:

Now, let’s try to understand this Schema.

Since all the properties will return either True or false so these all properties are set to Boolean in Schema.Here dump_only means, we will return this property in the Schema.

So, we saw how User Model and Schema is updated to show custom system roles concerning a user on Open Event Server.

Resources

Loading Default System Image of Event Topic on Open Event Server

In this blog, we will talk about how to add feature of loading system image of event topic from server to display it on Open Event Server. The focus is on adding a helper function to create system image and loading that local image onto server.

Helper function

In this feature, we are providing feature of addition of loading default system image if user doesn’t provides that.

  1. First we get a suitable filename for a image file using get_file_name() function.
  2. After getting filename, we check if the url provided by user is a valid url or not.
  3. If the url is invalid then we use the default system image as the image of that particular event topic.
  4. After getting the local image then we read that image, if the given image file or the default image is not readable or gives IOError then we send a message to the user that Image url is invalid.
  5. After successful reading of image we upload the image to event_topic directory in static directory of the project.
  6. After uploading of this image we get a local URL which shows where is the image is stored. This path is stored into database and finally we can display this image.

Resources

Adding Custom System Roles API on Open Event Server

In this blog, we will talk about how to add API for accessing the Custom System Roles on Open Event Server. The focus is on Schema creation and it’s API creation.

Schema Creation

For the CustomSystemRoleSchema, we’ll make our Schema as follows

Now, let’s try to understand this Schema.

In this feature, we are providing Admin the rights to get and create more system roles.

  1. First of all, we are provide the two fields in this Schema, which are id and name.
  2. The very first attribute id should be of type string as it would have the identity which will auto increment when a new system role is created. Here dump_only means that this value can’t be changed after the record is created.
  3. Next attribute name should be of string type and it will contain the name of new custom system role. This attribute is required in a custom_system_roles table.

API Creation

For the Custom System Roles, we’ll make our API as follows

Now, let’s try to understand this Schema.

In this API, we are providing Admin the rights to set Custom System roles.

  1. CustomSystemRoleList inherits ResourceList which will give us list of all the custom system roles in the whole system.
  2. CustomSystemRoleList has a decorators attribute which gives the permission of POST request to only admins of the system.
  3. CustomSystemRoleDetail inherits ResourceDetail which will give the details of a CustomSystemRole object by id.
  4. CustomSystemRoleDetail has a decorators attribute which gives the permission of PATCH and DELETE requests to only admins of the system.

So, we saw how Custom System Role Schema and API is created to allow users to get it’s values and Admin users to update and delete it’s record.

Resources

Adding Panel Permissions API in Open Event Server

In this blog, we will talk about how to add API for accessing the Panel Permissions on Open Event Server. The focus is on Schema creation and it’s API creation.

Schema Creation

For the PanelPermissionSchema, we’ll make our Schema as follows

Now, let’s try to understand this Schema.

In this feature, we are providing Admin the rights to create and assign panel permission to any of the custom system role.

  1. First of all, we are provide the four fields in this Schema, which are id, panel_name, role_id and can_access.
  2. The very first attribute id should be of type string as it would have the identity which will auto increment when a new system role is created. Here dump_only means that this value can’t be changed after the record is created.
  3. Next attribute panel_name should be of string type and it will contain the name of panel. This attribute is required in a panel_permissions table so set as allow_none=False.
  4. Next attribute role_id should be of integer type as it will tell us that to which role current panel is concerning.
  5. Next attribute can_access should be of boolean type as it will tell us whether a role of id=role_id has access to this panel or not.
  6. There is also a relationship named role which will give us the details of the custom system role with id=role_id.

API Creation

For the Panel Permissions, we’ll make our API as follows

Now, let’s try to understand this Schema.

In this API, we are providing Admin the rights to set panel permissions for a custom system role.

  1. PanelPermissionList inherits ResourceList which will give us list of all the custom system roles in the whole system.
  2. PanelPermissionList has a decorators attribute which gives the permission of both GET and POST requests to only admins of the system.
  3. The POST request of PanelPermissionList API requires the relationship of role.
  4. PanelPermissionDetail inherits ResourceDetail which will give the details of a Panel Permission object by id.
  5. PanelPermissionDetail has a decorators attribute which gives the permission of GET, PATCH and DELETE requests to only admins of the system.

So, we saw how Panel Permissions Schema and API is created to allow Admin users to get, update and delete it’s record.

Resources

 

Adding Event Roles Permission API on Open Event Server

The Open Event Server enables organizers to manage events from concerts to conferences and meetups. It offers features for events with several tracks and venues. Event managers can create invitation forms for speakers and build schedules in a drag and drop interface. The event information is stored in a database. The system provides API endpoints to fetch the data, and to modify and update it.

The Open Event Server is based on JSON 1.0 Specification and hence build on top of Flask Rest Json API (for building Rest APIs) and Marshmallow (for Schema).

In this blog, we will talk about how to add API for accessing and updating the events role permissions on Open Event Server. The focus is on Schema creation and it’s API creation.

Schema Creation

For the Events Role Permission, we’ll make our Schema as follows

 

Now, let’s try to understand this Schema.

In this feature, we are providing Admin the rights to get and update the permission given to a role concerning a service.

  1. First of all, we are provide the four fields in this Schema, which are can_create, can_read, can_update and can_delete which are Boolean.
  2. All these fields gives us idea whether a user with a role can create, read, update and delete a service or not respectively in the whole system.
  3. Next there is a relationship with role which is one of organizer, coorganizer, track_organizer, moderator, registrar or attendee.
  4. Next there is a relationship with service which is one of Track, Microlocation, Session, Speaker or Sponsor.

API Creation

For the Events Role Permissions, we’ll make our API as follows

Now, let’s try to understand this API.

In this feature, we are providing Admin the rights to get and update the permission given to a role concerning a service.

  1. First of all, there is the need to know that this API has two method GET and PATCH.
  2. Decorators shows us that only Admin has permissions to access PATCH method for this API i.e. only Admins can modify the events role permissions .
  3. In EventsRolePermissionList, we are inheriting ResourceList from Flask Rest JSONAPI which will allow us to get all the records for the model Permission.
  4. In EventsRolePermissionDetail, we are inheriting ResourceDetail from Flask Rest JSONAPI which will allow us to get and update attributes of a record of model Permission.
  5. In EventsRolePermissionRelationship, we are inheriting ResourceRelationship from Flask Rest JSONAPI which will allow us to get and update relationships of a record of model Permission.

So, we saw how Events Role Permission Schema and API is created to allow users to get it’s values and Admin users to modify it’s attributes and relationships.

Resources

Building the API of Speaker Image Size on Open Event Server

The Open Event Server enables organizers to manage events from concerts to conferences and meetups. It offers features for events with several tracks and venues.It uses the JSON 1.0 Specification and build on top of Flask Rest Json API (for building Rest APIs) and Marshmallow (for Schema). In this blog, we will talk about how to add API for accessing and updating the Speaker Image Size on Open Event Server. The focus is on its API creation.

API Creation

For the SpeakerImageSizeDetail, we’ll make our Schema as follows

Now, let’s try to understand SpeakerImageSizeDetail.

In this feature, we are providing Admin the rights to Get and Update the SpeakerImageSizes

  1. kwargs[‘id’] = 2 states that Image Size model has 2 records and 1st record is used for Event Image Size and 2nd record is used for Speaker Image Size.
  2. decorators = (api.has_permission(‘is_admin’, methods=”PATCH”, id=”2″),) states that for Speaker Image Size, Update API is accessible to Admins only.
  3. methods = [‘GET’, ‘PATCH’] states that this API provides two methods i.e. GET and PATCH.
  4. schema = SpeakerImageSizeSchema states that the schema which is used to return the response is Speaker Image Size Schema.
  5. data_layer = {‘session’: db.session, ‘model’: ImageSizes} states the session and Model used to fetch the records.

Resources

Patching an Attribute Type Across a Flask App

Recently, it was discovered by a contributor that the rating attribute for event feedbacks in Open Event was of type String. The type was incorrect, indeed. After a discussion, developers came concluded that it should be of type Float. In this post, I explain how to perform this simple migration task of changing a data type across a typical Flask app’s stack.

To begin this change, we first, we modify the database model. The model file for feedbacks (feedback.py) looks like the following:

from app.models import db


class Feedback(db.Model):
"""Feedback model class"""
__tablename__ = 'feedback'
id = db.Column(db.Integer, primary_key=True)
rating = db.Column(db.String, nullable=False)  # ←-- should be float
comment = db.Column(db.String, nullable=True)
user_id = db.Column(db.Integer,
db.ForeignKey('users.id', ondelete='CASCADE'))
event_id = db.Column(db.Integer,
db.ForeignKey('events.id', ondelete='CASCADE'))

def __init__(self, rating=None, comment=None, event_id=None,                                        user_id=None):
self.rating = rating  # ←-- cast here for safety
self.comment = comment
self.event_id = event_id
self.user_id = user_id





The change here is quite straightforward, and spans just 2 lines:

rating = db.Column(db.Float, nullable=False)

and

self.rating = float(rating)

We now perform the database migration using a couple of manage.py commands on the terminal. This file is different for different projects, but the migration commands essentially look the same. For Open Event Server, the manage.py file is at the root of the project directory (as is conventional). After cd’ing to the root, we execute the following commands:

$ python manage.py db migrate

and then

$ python manage.py db upgrade

These commands update our Open Event database so that the rating is now stored as a Float. However, if we execute these commands one after the other, we note that an exception is thrown:

sqlalchemy.exc.ProgrammingError: column "rating" cannot be cast automatically to type float
HINT:  Specify a USING expression to perform the conversion.
'ALTER TABLE feedback ALTER COLUMN rating TYPE FLOAT USING rating::double precision'

This happens because the migration code is ambiguous about what precision to use after converting to type float. It hints us to utilize the USING clause of PostgreSQL to do that. We accomplish this manually by using the psql client to connect to our database and command it the type change:

$ psql oevent
psql (10.1)
Type "help" for help.

oevent=# ALTER TABLE feedback ALTER COLUMN rating TYPE FLOAT USING rating::double precision

We now exit the psql shell and run the above migration commands again. We see that the migration commands pass successfully this time, and a migration file is generated. For our migration, the file looks like the following:

from alembic import op
import sqlalchemy as sa


# These values would be different for your migrations.
revision = '194a5a2a44ef'

down_revision = '4cac94c86047'


def upgrade():
op.alter_column('feedback', 'rating',
existing_type=sa.VARCHAR(),
type_=sa.Float(),
existing_nullable=False)


def downgrade():
op.alter_column('feedback', 'rating',
existing_type=sa.Float(),
type_=sa.VARCHAR(),
existing_nullable=False)

This is an auto-generated file (built by the database migration tool Alembic) and we need to specify the extra commands we used while migrating our database. Since we did use an extra command to specify the precision, we need to add it here. PostgreSQL USING clause can be added to alembic migration files via the postgresql_using keyword argument. Thus, the edited version of the upgrade function looks like the following:

def upgrade():
op.alter_column('feedback', 'rating',
existing_type=sa.VARCHAR(),
type_=sa.Float(),
existing_nullable=False,
postgresql_using='rating::double precision')

This completes our work on database migration. Migration files are useful for a variety of purposes – they allow us to easily get to a previous database state, or a new database state as suggested by a project collaborator. Just like git, they allow for easy version control and collaboration.

We didn’t finish this work after database migration. We also decided to impose limits on the rating value. We concluded that 0-5 would be a good range for rating. Furthermore, we also decided to round off the rating value to the “nearest 0.5”, so if the input rating is 2.3, it becomes 2.5. Also, if it is 4.1, it becomes 4.0. This was decided because such values are conventional for ratings across numerous web and mobile apps. So this will hopefully enable easier adoption for new users.

For the validation part, marshmallow came to rescue. It is a simple object serialization and deserialization tool for Python. So it basically allows to convert complex Python objects to JSON data for communicating over HTTP and vice-versa, among other things. It also facilitates pre-processing input data and therefore, allows clean validation of payloads. In our case, marshmallow was specifically used to validate the range of the rating attribute of feedbacks. The original feedbacks schema file looked like the following:

from marshmallow_jsonapi import fields
from marshmallow_jsonapi.flask import Schema, Relationship

from app.api.helpers.utilities import dasherize


class FeedbackSchema(Schema):
"""
Api schema for Feedback Model
"""
class Meta:
"""
Meta class for Feedback Api Schema
"""
type_ = 'feedback'
self_view = 'v1.feedback_detail'
self_view_kwargs = {'id': '<id>'}
inflect = dasherize

id = fields.Str(dump_only=True)
rating = fields.Str(required=True)  # ← need to validate this
comment = fields.Str(required=False)
event = Relationship(attribute='event',
self_view='v1.feedback_event',
self_view_kwargs={'id': '<id>'},
related_view='v1.event_detail',
related_view_kwargs={'feedback_id': '<id>'},
schema='EventSchemaPublic',
type_='event')




To validate the rating attribute, we use marshmallow’s Range class:

from marshmallow.validate import Range

Now we change the line

rating = fields.Str(required=True)

to

rating = fields.Float(required=True, validate=Range(min=0, max=5))

So with marshmallow, just about 2 lines of work implements rating validation for us!

After the validation part, what’s remaining is the rounding-off business logic. This is simple mathematics, and for getting to the “nearest 0.5” number, the formula goes as follows:

rating * 2 --> round off --> divide the result by 2

We will use Python’s built-in function (BIF) to accomplish this. To implement the business logic, we go back to the feedback model class and modify its constructor. Before this type change, the constructor looked like the following:

def __init__(self, rating=None, comment=None, event_id=None, user_id=None):
self.rating = rating
self.comment = comment
self.event_id = event_id
self.user_id = user_id

We change this by first converting the input rating to float, rounding it off and then finally assigning the result to feedback’s rating attribute. The new constructor is shown below:

def __init__(self, rating=None, comment=None, event_id=None, user_id=None):
rating = float(rating)
self.rating = round(rating*2, 0) / 2  # Rounds to nearest 0.5

self.comment = comment
self.event_id = event_id
self.user_id = user_id

This completes the rounding-off part and ultimately concludes rating’s type change from String to Float. We saw how a simple high-level type change requires editing code across multiple files and the use of different tools in between. In doing so, we thus also learned the utility of alembic and marshmallow in database migration and data validation, respectively.


Resources

Populating Database for different Event Types and Event Topics on Open Event Server

The Open Event Server enables organizers to manage events from concerts to conferences and meetups. It offers features for events with several tracks and venues. It uses the JSON 1.0 Specification and build on top of Flask Rest Json API (for building Rest APIs) and Marshmallow (for Schema). In this blog, we will talk about how to add API for accessing and updating the Speaker Image Size on Open Event Server. The focus is on its API creation.

In this blog, we will talk about how to populate database for different event types and event topics in the Open Event Server.

Populating the Database

Using populate_db,py for populating the database.

Now, let’s try to understand this now.

  1. First of all, we will write two functions create_event_topics and create_event_types in populate_db.py .
  2. In these function we will make a list of all the event topics and event types which we want to populate in database.
  3. We will loop through these lists to create their objects if not present.
  4. Last step is to call these functions in populate and populate_without_print functions in populate_db.py itself.

Resources

Adding System Image for Event Categories

The Open Event Server is using the JSON 1.0 Specification and build on top of Flask Rest Json API (for building Rest APIs) and Marshmallow (for Schema). In this blog, we will talk about how to add feature of System Image for Event Categories on Open Event Server. The focus is on Model updation, Schema updation and migrating the Database.

Model Updation

For adding System Image, we’ll update our Model EventTopic.

In this feature, we are providing rights to the Admin to add a system image for each Event Category so that if no image is given by a organizer of event on event creation then it will use the system image of that Event Category as event image by default.

Here we are adding a Column named system_image_url which is of type String. This value cannot be nullable and having a default value.

Migrating the Database

For the migrating the Database we will use simple commands.

This command runs migrations. If it cause problems naming Multiple Migration Head, then you need to run

This problem is caused when two developers push a migration file without merging two heads to achieve one head.

The above command will give us ids of two migration heads.

This command is merging two migration heads.

This command is upgrading the migrations.

Finally, we migrate the Database using above command.

Schema Updation

For the system image, we’ll update the Schema EventTopicSchema as follows

In this feature, to provide system image for each Event Category we’ll add a field named system_image_url in the Schema.

Here we are adding a field named system_image_url which is of marshmallow field type URL. This value cannot be none.

Validating the Event Image and using System Image by default

In this step, we’ll check if a event image is provided by organizer. If that is not provided then we’ll use system image of Event Category as Event Image.

Here, we will first take the event topic of event as added by the organizer. Then we will fetch the the database row in Event Topic model which has id == event_topic_id . Then we will return the system image url of that event topic to the event image.

So we saw how we could provide a default image for any event.

Resources