A recipe blog for autistic and other neurospicy folx. Utilitarian, customizable and to the point. No rambling, no unrelated stories, no word count fillers, no distracting design kitsch or vertigo-inducing moving backgrounds. Instead, the focus is on precise and searchable information to easily find recipes for specific needs.
Developer: Dr. Sylvia Blaho
See the development progress and further plans on GitHub Projects.
- UX/UI
- Project Management | Agile Methodologies
- Features
- Technologies used
- Deployment
- Testing
- Credits
Table of contents generated with readme-toc
In a world designed for neurotypical people, the needs of neurodivergent people are often disregarded. When it comes to recipe blogs, the 3 main culprits I aim to tackle in this project are
Each issue and its implemented mitigation is described below.
An oft-parodied trend of many food blogs is their inflated word count by paraphrasing and unrelated personal stories, presumably in an effort to improve their SEO ranking.
While this is a mild annoyance to neurotypical people, it can be a serious accessibility issue for those who are neurodivergent and have executive functioning issues, such as problems focusing or front-end perfectionism.
Many autistic people are very particular about food (termed food selectivity in scientific literature; some examples). However, most recipe blogs do not offer easy ways to search for particular textures, tastes or temperatures.
Analogous to dopamine dressing, being able to surround themselves with colors that match or complement their mood and energy levels is a useful coping strategy for neurodivergent people.
To combat the problem of superfluous information, this recipe site is designed to clearly separate the different components of a recipe to provide a better overview for visitors, and a helpful template for recipe writers.
To address the problem of lack of specificity, this recipe blog has an emphasis on tagging, searching and filtering recipes, enabling visitors to find recipes matching their specific needs.
To facilitate users being able to customize the look of the site, the blog offers a selection of color themes that users can choose from.
Along with usual blog features like access management, post management and collaboration, the following Themes, Epics and User Stories were defined at the beginning of the project (click here for the original Sheet):
However, as the development time available for the project was only 1 month, and this was my first Django project, these User Stories were vetted based on whether they were to be part of the Minimum Viable Product (MVP) or not.
Based on the considerations specific to a neurodivergent audience (described above), clarity of presentation and customizability was rated more important than collaboration.
Accordingly, the User Stories in the MVP were determined as follows (click here for the original Sheet):
Naturally, this list was modified somewhat during development (see the Prioritization section for details). The final list can be seen in GitHub Issues.
The initial design of data models was as follows:
Notable aspects of the models are described below.
Partially based on the Post model of the I Think Therefore I Blog walkthrough, but changed several aspects:
- Published is Boolean
- Separated content into
- Instructions
- PrepTime
- CookTime
- Ingredients (separate model)
Ingredients are available across the project, while IngredientQuantities are specific to individual recipes.
The reasoning behind this setup was threefold:
- To allow for more fine-grained access permissions
- To lay the foundations for a future implementation of a shopping list making functionality, along the lines of the Dinner Party app I made.
- The intermediary IngredientQuantity model also has unit and quantity attributes.
Decimal instead of float used for quantity.
Recipes can be saved without any ingredients (to allow better management of drafts).
Instances of Ingredient where ingr_name
& preparation
are the same cannot be duplicated.
- "cheese, sliced" and "cheese, grated" are both possible
- 2 instances of "cheese, grated" are not allowed
This is true when adding new ingredients as well as when editing existing ones would result in a duplicated.
Each instance of IngredientQuantity is unique, that is, even if there are 2 recipes that call for 2 apples each, these are treated as separate entities.
This model is based entirely on the Comment model of the I Think Therefore I Blog walkthrough project.
These models were added to the initial design in order to enable more filtering and more precise tagging of recipes. Their implementation parallels IngredientQuantity and Ingredient: RecipeAttribute acts as an intermediary between the Recipe and Attribute models.
Using this design as opposed to a ManyToManyField relation between Recipe and Attribute enables setting up a better control of the scope of permissions for staff users.
When implementing the community
app of the project, this model was added to store public information about the users, with the intention that logged-in users will be able to create and manage profiles for themselves.
Crucially, the Profile model is distinct from the built-in User model, connected by a OnetoOne field.
There are 2 advantages to this setup:
- Allow for user information to be accessible in the admin panel but not on the website UI
- Avoid accidentally overwriting crucial user information needed for signin and permissions.
Accordingly, the current Entity Relationship Diagram is as follows:
The project implemented signup, signin and signout functionalities by using Allauth.
CRUD functionalities are only available to logged-in users.
Visitors who are not logged in can still access the search, filter and color theme functionalities.
Logged-in users can Create, Read, Update and Delete their own comments. This functionality is implemented following the walkthrough project.
In addition, Staff users can access the Admin Panel and Create, Read, Update and Delete their own recipes, ingredient quantities, recipe attributes and profiles. Only their own objects are available to Staff users in the Admin Panel, while the Superuser can manage all objects.
This is present on every page, thus it contains elements that are used throughout the site.
The most prominent position has the navigation links letting the user switch between the collection
app containing the recipes, and the community
app containing the user profiles.
The center position of the nav bar has the blog name, logo and tagline.
On the right, we find the color theme selector toggle and the recipe search bar, but of these being important targeted features of the project.
As the primary purpose of the project is to show recipes, the home page of the site displays the list of published recipes.
The recipe filters are prominently placed at the top, since it is anticipated that this feature will be widely used by the target audience.
Clicking on any recipe takes the visitor to the recipe detail page.
To ease navigation, this app is laid out similarly to the collection
app: the main page shows a list of profiles, and clicking on them leads to the profile detail page.
The footer is also present on every page, but the information contained here is predicted to be used less frequently: the developer name and social media profile links.
Since this recipe blog is modeled after the I Think Therefore I Blog walkthrough project, and one of the project's aims is to keep layouts simple and intuitive, the basic layout of the home page and footer was not modified significantly (see the UX improvements section for changes that might not be obvious at first glance).
However, I decided to make several alterations and additions to the navigation bar.
First, I visually separated page navigation from access management functions (signing up/in/out): the page navigation stayed in the top left corner in the navigation, but access management links and information were moved to the so-called "user bar" immediately below.
Within the user bar, (semi-)permanent information was moved to the right side, while the left portion of the user bar was reserved for ephemeral dismissable messages having to do with signing in/out.
I also moved the blog name to the middle of the navigation bar.
The right side of the navigation bar has the color theme toggle and the search field.
The mobile version of the recipe list (with the nav bar open) was mocked up as follows:
I have made some more significant changes to the recipe detail page, since the way the data are stored is also more detailed than in the walkthrough project.
I separated the space under the masthead into 2 columns: the smaller one on the left has concrete, bite-sized and easily parsable information like preparation time, cooking time and ingredients. The larger column on the right contained the instructions.
Not shown on the wireframes is the Comments section – since this is very much the same as the walkthrough project, I did not make a separate mockup of this. One change I implemented was to show messages to do with comment creation/editing/deletion in the comment section rather than at the top of the page (see the section UX improvements).
A further addition to the masthead on the recipe detail page is the inclusion of attribute tags.
The mockup of the mobile version of the recipe detail page is shown below (with the nav bar closed):
I did not make separate wireframes for the profile list and profile detail templates, as these are analogous to their corresponding recipe counterparts.
The logo I chose for this project is the Rainbow Infinity symbol representing autism. This symbol is most widely used by autistic self-advocacy groups, and is in stark contrasts with the puzzle piece symbol that has been used to spread many harmful stereotypes about autistic people.
The rainbow infinity logo represents the many different facets of autism, the wide potential of autistic people, and the fact that autism is a circular spectrum without a "mild" end and "severe" end – mirroring the recognition that labels such as "low functioning" or "high functioning" are harmful and irrelevant.
The logo is also a not-so-subtle nod to Pride month, when this project was developed, as there is a striking correlation between the neurodivergent and queer communities: autistic people are 8 times more likely to identify as queer as neurodivergent people.
I have consciously stayed away from any unnecessary visual clutter, such as excessive borders and shadows, elements of very different shapes, background images, and auto-moving elements of all kinds.
These elements tend to cause problems for a variety of users (e.g. those with visual impairment, executive functioning impairment, vertigo, etc.). Neurodivergent people are highly likely to experience some of these issues due to their heightened sensory processing, so steering clear of these chimes in perfectly with accessibility goals and particularly suited to the target audience.
As detailed in above, I wanted to offer users to customize the color theme of the site to match their particular needs.
For the MVP I designed 3 monochrome color themes: orange, blue and green. I plan to expand the available themes for future versions of this project.
The names of the navigation links were changed to Collection and Community, to better reflect the names of the apps.
On the recipe list and the profile list, the whole card was made clickable instead of just the title, to accommodate those with below average motor coordination (another frequent occurrence within neurodivergent individuals).
I also separated messages based on their function, and had them display in separate locations:
- messages related to comments pop up right inside the Comment block
- other messages, which at this point are all related to Account Management, pop up in the left hand side of the user bar (where the Account Management links and information are located).
This puts all messages physically close to where the relevant actions have been performed, preventing distractions and confusion, and aiding processing.
For the content of the recipes, I used photos and text from my own recipe collection.
For mocking up the profile cards, I used characters from Terry Pratchett's Discworld (see also the Credits section), as many neurodivergent people see themselves represented by them (see these examples).
Neurospicy is a popular self-identification of neurodivergent people, reclaiming their self definition and reframing neurodiversity as something additional or different to neurotypical identities, rather than lacking.
Given that spicy is also a salient feature of recipes, it seemed natural to combine both meanings in the blog's title.
The work to be done was divided into the following Themes:
- Access management
- Collaboration
- Commenting
- Produce content
- View content
Each theme was then divided into Epics, and Epics into User Stories, as seen here (click here for the original Sheet):
Each epic was assigned a distinctive color, which was also used for its label in GitHub Issues. Epics belonging to the same Theme were assigned colors of similar hues. This facilitated getting an overview of the work items.
Finally User Stories were broken down into tasks. These can be seen for each User Story individually in GitHub Issues and on the Project Board.
As this was my first project using Django, some User Stories have a very detailed task list, both as learning and as documentation/reference. Issues that have tasks that were already familiar only have high-level bullet points.
Some work items that have initially been classified as Epics have later been reclassified as User Stories – typically these were "meta" items to do with testing and documentation.
Estimating the time it would take to complete each User Story is notoriously difficult, doubly so with the first project in a new framework. This is why I did not assign sizes to the individual User Stories, instead, I treated them as one unit.
This proved to be the right strategy in retrospect, as inexperince caused me to take disproportionately long on tasks that would be much faster the second time around. On the other side, some other tasks could be completed much faster than estimated. All in all, the lack of relative sizing of individual User Stories did not have an adverse effect on the project.
The Issues were added to the Project Board in GitHub projects. This has a table view and a Kanban board view – this was the one I used most during development.
I have customized the Kanban columns to fit the project needs, and also added swimlanes representing milestones.
I have used several categories of labels during the project:
- Priority labels (those starting with
p:
) - An
epic
label to enable filtering between Epics and User Stories on the Project Board - A label for each epic (those starting with
e:
), to be assigned to the Epic and all its corresponding User Stories(since GitHub Issues does not provide any other way to link these). The individual epic labels are color-coded to match the Google Sheet containing User Stories - Other miscellaneous labels such as
bug
,enhancement
,mentor
, etc.
These have provided an excellent way to both filter Issues and to maintain an easier visual overview of them.
As the available time for development was only 3 weeks (setting the 4th week aside for testing and documentation), sorting User Stories into must have
, should have
, could have
and won't have
was done on the whole group of User Stories rather than on a sprint-by-sprint basis.
I have modified the MoSCoW method slightly in that I split the won't have
label into two:
- Issues with the label
wont have
are duplicates or mistaken issues - Issues not completed for the first release of the project but still to be done in further development work are assigned the label
v2
.
The links below show the User Stories excluding "meta" issues such as testing & documentation.
- User Stories with priority
must have
: 39 - User Stories with priority
should have
: 11 - User Stories with priority
could have
: 28
The statistics on planned vs. implemented User Stories can be seen on the Statistics tab of the User Stories Google Sheet.
Epics that had User Stories of various levels of prioritization received all applicable labels. As the User Stories in the Epic were completed, the labels of completed User Stories were removed from the Epic.
For example, EPIC: View author info has one User Story with priority should have
completed, and another User Story with priority could have
remaining to be done in version 2. Thus the label p: should have
was removed from the Epic, and label the remaining p: could have
.
The available development time for the project was 4 weeks. Accordingly, work items were divided into 4 milestones:
The first 3 milestones were assigned the User Stories discussed so far, while the last milestone was planned for "meta" tasks like testing and documentation.
Each milestone was assigned to a week-long sprint.
Initially, roughly the same percentage of must have
, should have
and could have
Stories were assigned to all 3 sprints.
However, as tends to happen in real life, different sprints had different velocities, which is reflected in the uneven number of User Stories completed in each sprint.
At the beginning of every sprint, I reviewed the Issues assigned to the current milestone and decided the order in which they are to be implemented, in a more fine-grained way than the existing prioritization labels.
I also defined tasks for the highest priority items, with tasks definitions for lower-priority items following as soon as it became plausible that I can finish them that sprint.
Whenever I have received updated information about prioritization or implementation from my mentor or the Code Institute community, I would also make appropriate changes in prioritization during sprints.
At the end of every sprint, I reviewed the items that were not completed, and either reassigned them to the next sprint, or to version 2 of the project.
This section briefly introduces the features implemented in the current version of the project. For videos demonstrating how each feature works, see the Manual feature testing section of TESTING.md
.
The navigation bar is present on all pages, and contains the most frequently used functionalities:
- navigation links
- brand name and logo
- color theme selector
- search field
On small viewports parts of the navigation bar are hidden by default and revealed by tapping the hamburger icon.
On desktop views, all nav bar items are visible by default.
This dropdown lets users choose between pre-defined color themes. Currently, these are orange, blue and green, but more options are planned for future versions.
The selected color theme is persistent, that is, it remains in effect even if the user navigates to another page within the site, or opens it in another tab.
The user bar is situated immediately below the admin bar and is present on all pages. It contains dynamically updated information on the user's login status, and links to the Signup & Signin or the Signout pages, as appropriate.
The left side of the user bar displays ephemeral messages relating to login status (seen dynamically in the videos in Authentication manual testing).
The user bar is also fully responsive.
The footer shows the site developer information and social media links. These open in a new window. The footer is present on all pages and is fully responsive.
The home page shows published recipes in a responsive grid, with pagination links displaying at the bottom when needed.
Each recipe card is clickable as a whole, to see the details of the selected recipe.
The top of the home page has 4 filters:
- temperature
- diet
- taste
- texture
These show recipes with the selected recipe attributes in the same grid structure as the home page.
In the current version of the app, only one filter can be active at a time. I hope to extend this functionality for future versions.
The search page displays recipes where the word entered into the Search field (in the navigation bar) is found in any of the following fields:
- title
- excerpt
- instructions
- comments
- attributes
- ingredients
The results are displayed in a responsive grid used on the home page.
This page shows the different pieces of information relating to the selected recipe in visually distinct, minimally styled blocks.
These include:
- title
- updated on
- attributes
- image (or placeholder)
- total time
- preparation time
- cooking time
- ingredient count
- ingredient list
- instructions
Visual separation and simplicity aids processing, which can accommodate users with attention or executive functioning issues.
Signed-in users can comment on recipes using the form at the bottom of each recipe detail page. All comments need approval before becoming visible to other users.
Once a superadmin approved a comment, it becomes visible regardless of login status.
Comments can be edited by their author. Edited comments change back to unapproved.
Users can also delete their own comments regardless of approval status.
This is the starting page of the community
app, and shows all user profiles in a responsive grid.
Similarly to the recipe list, the whole surface of a profile card is clickable to view individual profile pages.
Each profile page shows the information users chose to share publicly (if any):
- username or first name (last name optional)
- staff status
- pronouns
- neurodiversity status
- about text
The profile detail page is also fully responsive.
Access management has been implemented using Allauth. All functionalities work as intended, and the Allauth templates have been adjusted to fit the styling of the site.
See the the writeups and videos in Authentication manual testing for more details.
The Admin Panel enables the superuser to manage all objects in all models in the app.
They can add any objects associated to any user, for example, add a recipe with any user in the database as the author.
They can also manage all instances of related models from the Recipe Admin view.
The current version of the app does not contain the functionality to manage recipes from the website's UI. Following the suggestion of my mentor, I have deprioritized this and focused my time on creating automated tests instead.
As an interim workaround, I have set up the Admin Panel to provide restricted access to Staff users (Gytha and Tiffany), so that they can manage their own items, but not others'.
Below, we can see the options of the Admin Panel for staff user Tiffany. The available models on the left hand side are considerably restricted, as is the list of recipes, as only those recipes are shown where Tiffany is the author.
Inline foreign keys are also restricted, as shown below: the Staff user can only select themselves as the author of the recipe.
Finally, we see that related models are also limited: the Comment model does not appear in the Recipe view for the Staff user, and Attributes can be added to the recipe, but cannot be modified (as opposed to the superadmin view).
For future versions of the project, I would like to implement those User Stories that could not be done for this version for lack of time. They are listed under the label v2
.
In addition, I would like to extend customization options for the color theme selector, with a wide range of monochromatic palettes, thematic multicolored palettes and dark mode(s).
Similarly, I would like to extend filtering capabilities to combine several filter vectors and also filter for negative attributes (e.g., "not bitter").
Code was manually tested and validated throughout development. At the end of the development process, a final, comprehensive round of testing and validating was completed. The results are detailed in TESTING.md.
Apart from making sure that the app functions as intended, I have also taken special care to make sure the code is well organized and appropriately commented. Since I am just becoming familiar with Django (and dealing with executive functioning issues), I have erred on the side of "more is more" for code comments and docstrings for methods that were new to me.
I have also done my best to adhere to the principle of Don't Repeat Yourself (DRY).
The Javascript files written for this project have been through several iterations of refactoring.
I have also restructured the templates of the collection
app so that the home page, filter results page and search page all use the same code snippets for displaying the recipes and pagination links.
- Django & Python for the app framework
- HTML & CSS for the UI
- JavaScript for forms
- Allauth for access management
- Cloudinary for storing images
- Crispyforms for forms
- Gunicorn for deployment
- Summernote for rich text in the Admin Panel
- Whitenoise for static file storage
- CI Python Linter – validate Python code
- Coolors.co - color palettes
- Favicon.io – create the favicon
- Freeconvert: convert manual testing videos from
.mov
to.mp4
- Git – version control
- GitHub – store the source files
- GitHub Desktop – GitHub UI
- GitHub Issues – feature management, bug tracking
- GitHub Projects – project management
- GitHub TOC generator – automatically generate a Markdown TOC
- GitHub web editor
- GitPod – Integrated Development Environment
- Google Sheets – planning user stories
- Heroku – host the production version of the app
- Jigsaw – validate CSS code
- JSHint – validate JavaScript code
- Lighthouse – accessibility audits
- Lucidchart – make the ERD
- Preview – cropping and annotating images
- Shields.io – add badges to README
- Slack – mentor communication
- W3C HTML validator – validate HTML code
- WebAIM – color contrast checking
The following instructions describe the deployment process with the tools used for this project. Of course, you can choose other tools/providers for the individual functions described below, e. g., a different Postgres database instead of Neon, or a different development environment instead of GitPod. Naturally, detailed instructions are only provided for the tools used in this project.
- GitPod (or another IDE)
- Python 3
- pip
- git
- Neon (or another Postgres database)
- Cloudinary (or another media hosting provider)
- Google Mail with an app password (or another email server)
- Heroku (or another could platform)
You can fork the repository by following these steps:
- Log in to GitHub (if you don't have a GitHub account yet, you can create one for free).
- Navigate to the project website https://github.com/blahosyl/spicy.
- Click on Fork in the upper right part of the screen.
- On the next page you have the possibility to change the repository name. To do this, simply write your desired name in the text field in the center part of the screen. You can also leave the name as it is.
- Click Fork in the bottom right part of the screen.
Tip
If you do rename the repository, make sure to keep the GitHub naming conventions in mind.
- Open the repository in a new workspace in GitPod. GitPod will automatically run the Python virtual environment for you. If you're using a different development environment, see this documentation.
- Install the required dependencies:
pip3 -r requirements.txt.
- To store access credentials and other secrets, create a file called
env.py
in your top-level project directory. Before adding any content to it, addenv.py
to.gitignore
and commit your changes. This will prevent the contents ofenv.py
from being pushed to the Git repository. - Add the following information to your
env.py
file:CLOUDINARY_URL
-you can find this in your Cloudinary console under API KeysDATABASE_URL
DEFAULT_FROM_EMAIL
SECRET_KEY
- In
settings.py
, add your GitPod workspace URL toALLOWED_HOSTS
- Run a migration to create your database tables:
python manage.py migrate
- Create a superuser (make sure you save the username and password you use here):
python manage.py createsuperuser
- Run the development server
python manage.py runserver
Make sure to complete the following pre-deployment steps in your development environment, especially if you made changes to the project:
- (Re-)create a list of requirements by going to the terminal and typing
pip3 freeze > requirements.txt
. This popuplates yourrequirements.txt
file with the list of required files. - Collect static files (these are hosted with whitenoise):
python manage.py collectstatic
- In
settings.py
, make sureDEBUG=False
- Commit and push your changes to GitHub.
- Log in to your Heroku account (or create a new one if you have not done so yet).
- Create a new Heroku app by selecting your region and app name.
- Under Settings > Config Vars in Heroku, add the following variables:
CLOUDINARY_URL
-you can find this in your Cloudinary console under API KeysDATABASE_URL
DEFAULT_FROM_EMAIL
: this can be the same asEMAIL_APP_USER
EMAIL_APP_PASSWORD
: instructions for obtaining oneEMAIL_APP_USER
: the email used with your email serverSECRET_KEY
- Under Deploy > Deployment method in Heroku, select GitHub and connect Heroku to your GitHub account.
- Type in your repository name, then click Search.
- When your repository appears, click Connect next to it.
- Under Deploy > Manual deploy in Heroku, select Deploy branch to deploy manually.
- Once the process is finished, the following message will appear:
Your app was successfully deployed - Click View under the message, and a new tab will appear with your deployed app.
- Once the process is finished, the following message will appear:
- (optional) Under Deploy > Automatic deploy in Heroku, select Enable Automatic Deploys if you want your app to be rebuilt each time you push to the
main
branch of your GitHub repository (but make sure yoursettings.py
file always hasDEBUG=False
when you do).
See the document TESTING.md
for details.
- The architecture of the project was based on the I Think Therefore I Blog walkthrough project by Code Institute
- Leon Potgieter suggested I use Neon DB when I discovered ElephantSQL's EOL, helped with testing on local DB issue, and gave me a handy tip for line breaking
- search tutorial
- querying of related models implemented with the help of Roman Rakic
- Tech Corner Website
- Successful comment editing test rewritten with the help of tutor Roo
- Daisy McGirr on the Allauth social plugin
- Rachel O'Donnell and Joanna Gorska on how to allow creating mockups with amiresponsive by installing the Ignore X-Frame Headers Chrome plugin
The following resources were used to learn/double check general, atomic functionalities/syntax/errors:
- Show labels and Milestones in GitHub Projects Kanban board
- Creating and editing milestones for issues and pull requests
- making a model for ingredients
- sort model entries by field
- connector types in Entity Relationship Diagrams
- float vs. decimal in Python
durationfield
in Django- 1:N relationship where N must be at least one entry
- database design one to many where many is at least one
- Django model reference
verbose_name
: change model display name in admin panel- inline model in admin panel | Django documentation
- inline model in admin panel | Stackoverflow
- exclude duplicates of the same two fields together
- pluralize words depending on database value
- Bootstrap spacing
- Bootstrap position
- Bootstrap cards
- Bootstrap grid system
- change CSS color variables with JS
- Bootstrap nav bar
- Keep form elements on one line with Bootstrap
- Bootstrap forms | select
- HTML symbols
- trailing slashes in URIs
- Bootstrap: make whole card clickable
- Allauth documentation
- Allauth guide
- email verification: email must be required
- email verification in the Dev environment
- email verification example
- managing static files in Django
- change app name (used by Allauth emails)
- Git merge vs rebase
- recover deleted GitHub branch
- direct link to Google app passwords
Attribute error (missing)
caused by indentation error inviews.py
- Mozilla JS
sessionStorage
docs - Mozilla Web Storage API docs
- JS local storage intro
- Mozilla JS
querySelector
documentation - Javascript docstrings
- many-to-many relationships in Django
- intermediary table vs. ManyToManyField
- Django documentation on many-to-many relationships
- accessing foreign key values in ListView
- querying backwards related objects
- "
ReverseManyToOneDescriptor
object has no attribute" error - Django search documentation
- display search term on search result page
- how to reuse the same bit of code in Django
- Django
include
documentation - relative paths for templates
- fix pagination for search results
- dropdown form in Django
- dropdown form without a button
- conditional: string in URL
elif
vselse
error: "Exception Value: Unexpected end of expression in if tag"- set Cloudinary to use https
import cloudinary
insettings.py
- get the URL with Javascript
- Bootstrap gutters
- Bootstrap text utilities
- restrict objects available to staff users in the admin panel
- Django documentation:
ModelAdmin.get_queryset(request)
- Bootstrap: make all cards the same height
- Bootstrap borders
- Bootstrap columns
- restrict ForeignKey Field dropdown options in Django admin
- Django
formfield_for_foreignkey
documentation - Bootstrap sizing
- preferred way of breaking lines in Python
- built-in error views
- displaying messages based on tags
- Django messages documentation
floatformat
template tag
Profile texts for the mockup users based on Terry Pratchett's Discworld series were taken from Wikipedia. The description of Geoffrey Swivel was adjusted to use the correct pronouns.
All other text was written by me.
Lemon bar recipe based on Chili&Vanilia's post.
Red velvet cake recipe based on Pamela Moxley's post.
Logo/favicon by janeb13 on Pixabay, converted to ico
format with Favicon.io
.
All other pictures taken by me.
- Creating your first README with Kera Cudmore by Code Institute
- Creating your first README by Kera Cudmore
- Bully Book Club by Kera Cudmore
- Bodelschwingher Hof by Ana Runje
- Travel World by Pedro Cristo
- Sourdough Bakes by Siobhan Gorman
- Horizon Photo by Rory Patrick Sheridan
- BackeStock by Amy Richardson
- American Pizza Order System by Iasmina Pal
- Neverlost by Rory Patrick Sheridan
- EastStr by Nathan Surgenor
- The README of my first Code Institute project
- The README of my second Code Institute project
- The README of my third Code Institute project
A person unknown to me has forked the project repository and submitted a pull request with some code comments added. I had not communicated with this person before this nor asked for their contribution to the repository. The pull request was closed without merging.
I would like to express my deepest gratitude to my mentor, Rory Patrick Sheridan for his incredibly useful and understanding support throughout the project. Issues raised by him or discussed with him can be found here (see the individual ticket descriptions for the details of his contribution).
I am also grateful to the Code Institute tutoring team, in particular, to John and Roo for their help. The details of their contributions can be found here.
I would also like to thank Peter Litauszki for photo and video editing help.