{"id":23505261,"url":"https://github.com/nezort11/rankrise","last_synced_at":"2026-04-25T21:33:06.334Z","repository":{"id":114260919,"uuid":"416393543","full_name":"nezort11/rankrise","owner":"nezort11","description":"Q/A product recommendation and ranking fullstack website.","archived":false,"fork":false,"pushed_at":"2022-02-16T23:07:43.000Z","size":3270,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-05-08T22:59:53.447Z","etag":null,"topics":["django","questions-and-answers","ranking-algorithm","recommendation-system"],"latest_commit_sha":null,"homepage":"https://murmuring-island-14148.herokuapp.com/api/ui/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nezort11.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-10-12T15:29:42.000Z","updated_at":"2022-02-09T21:16:15.000Z","dependencies_parsed_at":null,"dependency_job_id":"15b2d44f-e535-40a1-951b-6f5176c322e3","html_url":"https://github.com/nezort11/rankrise","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/nezort11/rankrise","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nezort11%2Frankrise","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nezort11%2Frankrise/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nezort11%2Frankrise/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nezort11%2Frankrise/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nezort11","download_url":"https://codeload.github.com/nezort11/rankrise/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nezort11%2Frankrise/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32278249,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-25T18:29:39.964Z","status":"ssl_error","status_checked_at":"2026-04-25T18:29:32.149Z","response_time":59,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["django","questions-and-answers","ranking-algorithm","recommendation-system"],"created_at":"2024-12-25T09:30:32.231Z","updated_at":"2026-04-25T21:33:06.302Z","avatar_url":"https://github.com/nezort11.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# RankRise\n\nThe goal of this website is to help users choose the best product in their case.\n\nThe technology goal is to design best-practice modern RESTful API with Django.\n\n![Swagger UI screenshot](img/swagger_ui.png)\n\n## Setup projects\n\nWhen installing new pip package run the following commands inside `api` folder:\n\n```shell\npipenv install package_name # adds to Pipfile\n\n# Lock dependencies\n# If prerelease error occurs add --pre flag\npipenv lock --pre # generates Pipfile.lock\n\n# Lock dependencies in requirements.txt format (includes both prerelease and development packages)\npipenv lock --pre --dev --requirements \u003e requirements.txt\n\n# Option 1: Enter Django container shell\ndocker-compose -f docker-compose.dev.yml exec api pip install -r requirements.txt\n\n# Option 2: Rebuild containers\ndocker-compose -f docker-compose.dev.yml down\ndocker-compose -f docker-compose.dev.yml up --build -d\n```\n\nInstall a new package:\n\n```sh\n# Stop and remove container + anonymous volume + image\ndocker compose -f docker-compose.dev.yml rm -sv api\ndocker image rm rankrise_api\n\n# Install and lock\npipenv install package\npipenv lock -d -r \u003e requirements.txt\n\n# Rebuild and run\ndocker compose -f docker-compose.dev.yml build api\ndocker compose -f docker-compose.dev.yml up api\n```\n\n## Description\n\n**Idea**:\n\n- Q/A website (question answer/solution/option/recommendation)\n\n- Voting platform\n\n- Recommendation platform\n\n- Ranking platform\n\n- Suggesting platform\n\n- Comparison website\n\n- Alternative searching platform\n\n- Product rating platform\n\n- Community centered\n\n**Features**:\n\n- User has username, email and avatar + social auth?\n\n- Ask questions\n\n- Answers as products (services)\n\n- Product/service search/suggesting\n\n- Question tags/categories (categorization)\n\n- Multilayer categories (MPTT)\n\n- Pros/Cons answer rating\n\n- Pros/Cons commenting\n\n- Answer name, website link, images, videos (links)\n\n- Answer rank (rating) calculation/_algorithm_\n\n- Questing/answer search\n\n- API request throttling\n\n- API testing \u0026 documenting\n\n- Reporting feature (report questions/products/answers/comments)\n\n- Question/product throttling/ban\n\n- Follow question options/last update\n\n- Question comments\n\n- Question sharing/linking\n\n- Option score calculation\n\n- Product community specs (+proc/con comments)\n\n- Product price (free, paid, open-source)\n\n- Recommendation community agreement\n\n- Vote against question, product, option, argument, etc.\n\n**Similar websites**:\n\n- Twitter, Reddit\n\n- Quora, StackOverflow\n\n- Slant, ProductHunt\n\n- Alternative.to\n\n**Plan**:\n\n- Project development setup\n\n- Authentication/Authorization\n\n- Documentation\n\n- Automated testing + test coverage\n\n- CRUD components API\n\n- Model\n\n- Serializer\n\n- API view/view set\n\n- Manual testing\n\n- Automated testing\n\n**Technology stack** (technologies involved in the project):\n\n- Python, Django, Django REST Framework, PostgreSQL\n\n- dj_rest_auth, pytest/coverage, Swagger, django_dotenv\n\n- black, pylint, isort, rope\n\n- AWS/Heroku, Docker, Compose, Github, CI/CD\n\n**Technological features**:\n\n- OpenAPI, Swagger\n\n- JWT authentication\n\n- Test driven development\n\n- Pagination\n\n- Database search\n\nNice to have:\n\n- Throttling\n\n- Caching\n\n- Versioning\n\n- Container debugging\n\n- MPTT structure management\n\n## Roadmap\n\n- [x] Dockerize project + PostgreSQL (setup dev environment)\n\n- [x] Migrate + custom user model\n\n- [x] Move from session to JWT authentication\n\n- [x] Authentication endpoints\n\n- [x] API documentation generation\n\n- [x] Automated testing\n\n- [x] Question\n\n- [x] Test-driven development\n\n- [x] Product\n\n- [x] Filtering\n\n- [x] Option\n\n- [x] Voting\n\n- [x] Ranking\n\n- [x] Throttling\n\n- [x] Import product dataset\n\n- [x] Categorization\n\n- [x] Caching\n\n- [x] Debugging\n\n- [x] S3 storage\n\n- [x] Cloud deployment\n\n- [x] Reporting\n\n- [ ] Try using python/pipenv task runner (vs Make vs Django custom commands)\n\n- [ ] Argument\n\n- [x] Frontend\n\n- [ ] Web design\n\n**Single-page app**:\n\n- [x] create-react-app\n\n- [x] modern development setup (formatter, linter, etc.)\n\n- [x] design complexity-based file/code/project/directory structure and organization\n\n- [x] design API client (resources)\n\n- [x] foundational website design (colors, font, header, footer, etc.)\n\n- [x] basic authentication (signup, login, email) (functional)\n\n- [x] questions list/create (func)\n\n- [x] questions search page, results, list\n\n- [x] question detailed page\n\n- [x] search time results list\n\n- [x] crud/app pages (func + style)\n\n- [ ] JOIN API endpoint multiple dependent resources together on server-side (like filtering/searching)\n\n**Website design**:\n\n- [x] Header\n\n- [x] Hero/Home\n\n- [x] Footer\n\n- [x] Search\n\n- [x] Question page\n\n- [x] Product add\n\n- [x] Modals\n\n## Question\n\nQuestions are the core of API.\n\nAPI:\n\n- Users (authenticated) can only ask questions. There should be some kind of throttling to prevent users from spamming a lot of questions.\n\n- Any one can only list and retrieve questions.\n\n- Only admins can delete or update questions (maybe based on reports).\n\nAPI:\n\n- list, retrieve - unauthenticated users\n\n- create - authenticated users\n\n- update, destroy - authenticated staff users\n\nModels:\n\n- Questions aren't bind to any user (not owned). A question is just a small text around 100 characters which has some (category) and ask_time. Question should be looked up by primary key (integer id or character slug).\n\n## Product\n\nProduct represent some product or service that can be recommended as an option to specific question. Usually it is online/software or Internet service/product.\n\n- id\n\n- name (title, help text: you can not change name after)\n\n- slug (automatically based on name)\n\n- description\n\n- images (links or _filesystem storage_: Django package)\n\n- product website link\n\n- price/cost (_choices_ from: open source, free, paid)\n\nValidation/Model:\n\n- id is a auto incrementing primary key (model)\n\n- name and slug must be unique\n\n- price should contain values only from choices\n\n- website link must be valid URL\n\n- description can be blank\n\n- slug (URI) must not update after name update\n\n- name and slug can not be changed in serializer/API\n\n- name can not be blank\n\n- description, website can be blank\n\n- price default set to free (model)\n\n- name must be \u003c= 50 characters\n\n- images must have image media type\n\nURLs:\n\n- Products should be available under /products/ URL\n\nSerialization:\n\n- Products should include images objects\n\nAPI permissions:\n\n- retrieve, list: unauthenticated\n\n- create: authenticated\n\n- delete: staff\n\n### Product image\n\nImage of the product, has the have API permissions as product.\n\nModel:\n\n- image field\n\n  - 300x200\n\n  - JPEG\n\n  - 80% source quality\n\nPermissions:\n\n- Same as models\n\nURL:\n\n- Image will be available under /products/images/ (validate product slug != images)\n\n## Filtering\n\nAPI should also provide ability to make filtered queries:\n\n- filter by equal, greater, etc.\n\n- search query\n\n- ordering of the result\n\n- pagination of large amount of data\n\n**Question**:\n\n- search by question title (case insensitive partial match)\n\n- order by latest/oldest ask time (default=latest)\n\n- paginate questions by 20\n\n**Product**:\n\n- search word contains in product name\n\n- full-text search by product description\n\n- filter products by price\n\n- paginate by 10\n\n## Options\n\nCommunity can suggests options which are products recommended to specific question.\n\nModel:\n\n- option connects together question and product (answer to question).\n\nPermissions:\n\n- options follow the same community rules, you can only get and create them.\n\n- admins can delete suggested options if they are not appropriate.\n\nRelations:\n\n- If question is deleted, option should be deleted also (options).\n\n- If product is deleted, option FK to product should be set to NULL (recommendations).\n\nRouters (URL design):\n\n- Options will be nested up on question or product (`/questions/\u003cquestion_id\u003e/options/\u003coption_id\u003e/`)\n\nRequirements:\n\n- Pagination by 10. Ordering by rank (descending).\n\n- Question and product foreign keys should be unique together.\n\n## Recommendation\n\nVoting about suggested options is in the core of recommendation system.\n\nDesign:\n\n- recommend or not recommend this option (upvote or downvote)\n\n- write Pro/Con argument about option usage, share opinion\n\n- like (upvote/downvote) top arguments\n\n- comment on argument comments\n\n- options will be ranked based on user votes and arguments\n\n**Vote**:\n\n- Vote should connect option and user (+ vote time)\n\n- Vote option and user data are write-only\n\n- Users can only once vote against specific option (unique together)\n\n- Vote can be either up or down (and can be switched after)\n\n- If option is deleted all votes should be too, if user is deleted all votes should stay (and set user to NULL)\n\n- Votes will be available under `*/options/\u003coption_id\u003e/` route\n\n  - Because `\u003coption_id\u003e` auto increment is absolute, it is not required to pass `\u003cquestion_id\u003e` in the `reverse(url_name)`\n\n  - `\u003cquestion_id\u003e` from URI is required and still used for additional validation.\n\n- Vote displaying should be anonymous (not voter information returned) only vote rate information (up/down) (_write-only_).\n\n- Unauthenticated users can read/list, authenticated can also create votes, update and delete _their_ votes. Admins can do anything.\n\n- Option should have convenient calculate fields (attributes: properties/methods.) or manager to get upvotes or downvotes count.\n\n- Filter option votes based on up or down status (rate). Like `?up=True` or `?up=False`\n\n- No API pagination for votes, ordering by latest vote time, filtering by up/down.\n\n- Vote user should be determined automatically based on request session user.\n\n  - vote user must be set to `request.user`\n\n  - vote create API shouldn't display `user` in OpenAPI documentation (or note that it is get from request session)\n\n- `option` and `user` API arguments will be determined from _URL_ option and _session_ user (arguments in body will be ignored).\n\n## Ranking\n\nRanking system is used to sort options from best scored to less ones.\n\nRanking dependes on votes (upvotes, downvotes), arugments (count, pros, cons), comments.\n\nRanking data math will be based on on:\n\n- JavaScript (client)\n\n- Python (server)\n\n- **SQL/ORM query** (database)\n\n- UPDATE row (database)\n\nFeatures:\n\n- Query upvotes and downvotes of option should be available as option properties.\n\n  - filter and count votes\n\n- Upvotes and downvotes should be included in serializer as read-only fields.\n\n- Upvotes and downvotes should be in rendered JSON data\n\n- Rating is only used to order objects\n\n- Rank is displayed in the data\n\n### Algorithm\n\nRating:\n\n$$\nrating = upvotes - (downvotes * \\frac{3}{4})\n$$\n\nRank point:\n\n$$\npoint = \\frac{max(rating)}{100}\n$$\n\nRank:\n\n$$\nrank = \\frac{rating}{point}-\\frac{downvotes}{upvotes}*10\n$$\n\n1. Calculate rating for each option? To find the MAX(rating) (SQL/ORM).\n2. Calculate score per 1 point (Python).\n3. Annotate each ordered option with the rank, display annotated rank (Python/SQL/ORM).\n\n## Throttling\n\nThis API is not very restrictive and built on top community trust and fairness. It has less restrictive throttling permissions to prevent high request rate (to save database and server from overloading).\n\nCommunity throttling:\n\n- forbid making more than 100 create (POST) requests in a day (authenticated users) and more than 5 POST requests in minute.\n\n  - create views of questions, product (images), options APIs.\n\n  - burst: 5 req/min\n\n  - sustained: 100 req/day\n\n- no throttling for admin users (admins are not restricted to throttling).\n\nTests:\n\n- in order to test sustainable request rate tests should mock burst rate to be the same as sustainable.\n\n## Categories\n\nCategories are content management technique for organizing products. For this API products (and questions) will be categorized hierarchically using MPTT in PostgreSQL.\n\nModel:\n\n- Category (subcategory) has id, name and reference to the parent category (to provide tree categorization).\n\n- slug?\n\n- when parent category is deleted all it's children should also be deleted.\n\nValidation (serializer level):\n\n- Category name can not contain numbers (model level validation, admin interface).\n\n- All model fields are read-only (only accessable from admin interface).\n\n  - **Because everything is read-only - no validation is required** (or validation tests)\n\nProduct:\n\n- Category is referenced from product model, on delete - `set null` product, related name (category products) - `products`.\n\nApplication Interface:\n\n- Categories should be created, updated and deleted from admin interface.\n\n- Categories can only be listed or retrieved (readonly) using API (`/categories/\u003cid:int\u003e/`) - **read-only API**.\n\n- Categories can be search by name (through all categories), filtered by parent (get children) and paginated by 20, ordering by name.\n\n- API should be hierarchical, meaning have multiple levels. _First should be root categories_, then under this category children can be accessed like `/categories/1/children/2/children/3/`. Or get children just by filtering parent like `/categories/?parent=1` to get children of 1 category.\n\n- To get category product filtering product by category should be used like `/products?category=1`.\n\n## Caching\n\nCaching will be used to save _expensive rating/ranking_ queries and calculations when requesting option list.\n\n- level: per-view\n\n- cache backend: Redis (in-memory)\n\n## Debugging\n\nI need to debug Django running (`./manage.py runserver`) inside Docker container from VSCode. I will use `pydebug` PyPA package from Microsoft.\n\n## Storage\n\n\u003e Static files (image) are files that aren't changed/updated/modified (database).\n\nAmazon S3 will be used as a filesystem storage service. The following will be stored:\n\n- Content delivery network - static files (CSS, JS, JPEG, PNG)\n\n- User uploads - static upload files (JPEG, PNG)\n\n## Reports\n\nTo prevent inappropriate/bad questions, production, answers and comments the reporting system\nwill be developed.\n\n- users sent reports about the objects\n- admins review report and decide to do something with that\n\nReport contains:\n\n- title\n- description\n- resource/object type\n- object pk/slug\n- created\n- id\n- reporter (user or admin)\n\n\u003e If object gets destroyed, all reports should be also\n\nUsers can only create reports with following fields:\n\n- title\n- description\n- resource/content type\n- object slug\n\nFor admins all fields will be visible + actions:\n\n- create (admins saw themselfs)\n- list\n- retrieve\n- destroy (inappropriate report)\n\nNo filters, search nor ordering =\u003e enough.\n\nSlug vs id:\n\n- question - id\n- production - slug\n- option - id\n- comment - id\n- report - uuid\n\n## Frontend project structure design\n\n### API client library\n\nBecause of the big number of API CRUD resources the proper design and OOP practices are needed.\n\nThe following resources should be mirrored in API client:\n\n- authentication\n- questions\n- products\n- product images\n- options\n- votes\n- categories\n- reports\n\nWebsite frontend pages:\n\n- home page + recent questions list\n- search results (question/product) page\n- question detail page\n- login page, signup page, user profile page\n\n### HTTP and binary data / REST\n\nHTTP is usually used to transfer HTML document or other textual information inside the body (such a XML, JSON).\n\nThere multiple types of HTTP bodies:\n\n- Text (JSON, HTML, YAML, ...)\n- Structured (form-data - contains multiple other content types, ...)\n- Binary (file, image, video, ...)\n\nBinary files can be only send in serialized (test) form =\u003e use base64 (+33% of data size due to using only 64 of 128 characters).\n\n- `http://someserver.org/images/image.png` will return a resource with media type `image/png` which tells browser to interpreter body as PNG file.\n\n- `http://someapi.org/api/products` will return JSON document with media type (`content-type` header) `application/json`.\n\n### Web design\n\nThe web design of the website will be made in Figma but inspired by Slant.co design.\n\n- Favicon: \"RR\"\n- Color scheme: ?\n- Typography: Outfit (Regular, Bold)\n- Central goal: search for question and find the best option\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnezort11%2Frankrise","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnezort11%2Frankrise","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnezort11%2Frankrise/lists"}