Create a referral management system for a single landing page, and track the visits to that page.
This submission is focused on the Back-end part. I had previous knowledge and experience in Django and in REST api development, but it was my first time using the Django Rest Framework and deploying to heroku.
As indicated, the root level endpoint exposes all the link management information, and the other pages
/link-title
count the visit and show a landing page.
https://ambassador-jordi-nonell.herokuapp.com
This Browsable API has been autogenerated by the framework.
The application exposes the following endpoints.
GET /
: List of all links.POST /
: Create a new link. title is a required field, slug is an optional field.GET /<id>
: Obtain information on a particular link.PUT /<id>
: Update a link.PATCH /<id>
: Partially update a link.DELETE /<id>
: Delete a link and all its visitsGET /<slug>
: View landing page and increment number of visits of that link.
Example:
# Create a new link
response = client.post('/', {"title": "This is an example"})
print(response.data)
# {
# "id": 1,
# "created_at": "2019-04-04T10:01:29.665475Z",
# "title": "This is an example",
# "slug": "this-is-an-example",
# "visits_count": 0,
# "visits": []
# }
# Perform a visit to the landing page
client.get('/this-is-an-example')
# Check the new data on link 1
response = client.get('/1')
print(response.data)
# {
# "id": 2,
# "created_at": "2019-04-04T10:01:29.665475Z",
# "title": "This is an example",
# "slug": "this-is-an-example",
# "visits_count": 1,
# "visits": [
# {
# "id": 1,
# "date_time": "2019-04-04T10:05:18.464486Z",
# "ip": "123.456.789.10",
# "user_agent": "Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0"
# }
# ]
# }
Django (and django rest framework) recommend a way to organize the code structure separating it into
projects (called emissary
in this case) and apps (called main
in this case), that I have found
useful in the past and followed for this challenge. None of the files, except for maybe testing,
has reached a size where I thought about splitting it between two files.
I have followed separation of concerns by using models, views and serializers as apropiated.
All the libraries used (including all the ones that helped deploying to heroku) have been checked for an appropiated license, in this case, MIT, BSD-2 and BSD-3, so the project could be legally monetized.
The submitted code fulfills the expected requirements for the Back-end track, providing some extra features. Most of those features have been implemented so I could become more familiar with the framework:
- It counts the visits by adding up rows in a
visit
table, instead of looking up a field. This is a way to prevent concurrency problems that might happen in paralel requests on a SELECT + UPDATE query. - Each visit saves the following fields:
datetime
,ip
,user agent
. Cookies could have also been used to improve the process to define the uniqueness of the visit. - The link has a datetime field from when it was created.
- The title link is a different field than the url (or slug). If the slug field is not present when creating the link, it is autogenerated from the title. It helps in making the title a field that is not directly related to the url.
This submission has purposedly left some things out, that in a longer project would have gotten the required attention. I have listed a few of those here, and the reasoning for leaving them out:
- Lack of authentication and security There are no users, no CSFR tokens, the django's secret key has been uploaded to github, etc. I used the time in improving documentation and making sure that the code was as maintainable as possible.
- Pragmatic approach to testing and TDD The test suite could be much larger, and cover many other different cases. I have stopped where I have because I see tests as one of the tools to write clear maintainable code, but not the only one. Despite that, as its current state it builds an efficient (although incomplete) safety net.
- Limited documentation and tests regarding Visits I prototyped this model/feature so in a real world scenario it would now be waiting for feedback. Therefore, knowing that it is extremely likely that it would require some changes, I did not want to invest too much time on it.
- Django and Heroku configuration Despite the huge effect that the correct set of settings have in a project, I have figured that I would be able to show my abilities more in this coding challenge if I invested more time actually coding than configuring it. That does not mean that I don't consider it important though.