Post List API
API endpoint that enables a list of posts to be browsed including related models data and auxhiliary properties.
The configured endpoint purposefully does not permit a POST method as I do not want others creating new posts in the database.
GET /api/blog/posts/?format=api&offset=9
{ "count": 17, "next": "https://waynelambert.dev/api/blog/posts/?format=api&limit=3&offset=12", "previous": "https://waynelambert.dev/api/blog/posts/?format=api&limit=3&offset=6", "results": [ { "id": 12, "title": "Implementing Amazon Simple Email Service for a Django Site", "slug": "implementing-amazon-simple-email-service-django-site", "content": "<p>It's a good idea to set up a proper SMTP server that can handle large volumes of transactional emails that your application might need such as registration emails, password resets, etc. Amazon's Simple Email Service (SES) has a number of steps to set it up correctly for your website which we'll run through here.</p>\r\n\r\n<p>You'll need just one additional Python package installing within your project. I use Docker for all of my development and production implementation, so I'll go through the steps using Docker. If you're using a Python virtual environment and a package manager like pipenv, the steps are exactly the same except that you will need to remove the docker component that is prepended to the commands.</p>\r\n\r\n<p>Assuming that your Docker setup uses a service called <strong>'web'</strong> for your Django project, install relevant project packages:</p>\r\n\r\n<div>\r\n<div>\r\n<div>\r\n<div>\r\n<div>\r\n<pre>\r\n<code class=\"language-bash\">$ docker-compose exec web pipenv install django-ses</code></pre>\r\n</div>\r\n</div>\r\n</div>\r\n</div>\r\n</div>\r\n\r\n<p>Next up, you'll need to configure your settings in your Django project. Make the region the one that is where the majority of your website visitors are likely to be located.</p>\r\n\r\n<div>\r\n<div>\r\n<div>\r\n<div>\r\n<div>\r\n<pre>\r\n<code class=\"language-python\"># Settings.py\r\n\r\n# Django SES Email Backend Settings\r\nEMAIL_BACKEND = 'django_ses.SESBackend'\r\nAWS_SES_REGION_NAME = 'eu-west-1'\r\nAWS_SES_REGION_ENDPOINT = 'email.eu-west-1.amazonaws.com'\r\nAWS_ACCESS_KEY_ID = os.environ['AWS_ACCESS_KEY_ID']\r\nAWS_SECRET_ACCESS_KEY = os.environ['AWS_SECRET_ACCESS_KEY']\r\nEMAIL_HOST = os.environ['EMAIL_HOST']\r\nEMAIL_HOST_USER = os.environ['EMAIL_HOST_USER']\r\nEMAIL_HOST_PASSWORD = os.environ['EMAIL_HOST_PASSWORD']\r\nEMAIL_PORT = 587\r\nEMAIL_USE_TLS = True\r\nDEFAULT_FROM_EMAIL = os.environ['DEFAULT_FROM_EMAIL']</code></pre>\r\n</div>\r\n</div>\r\n</div>\r\n</div>\r\n</div>\r\n\r\n<p> </p>\r\n\r\n<p>Log in to your <strong>AWS Management Console</strong> and do a search for <strong>IAM</strong>.</p>\r\n\r\n<p>Although this tutorial is not about setting up the <strong>Identity and Access Management </strong>for your Amazon account, it's recommended that you do so. In short, you'll need to set up a group with some policy permissions to handle whatever aspects of Amazon's Web Services that you wish to use. For now, create a group and then attach the policy called <strong>'AmazonSESFullAccess'</strong> to the group.</p>\r\n\r\n<p>You'll then need to create a user and attach that user to the group. This gives this user (namely you) full access to Amazon's Simple Email Service. If you don't use Identity and Access Management, then you'll be doing everything as the root user which isn't a safe way to manage your account.</p>\r\n\r\n<p>Once you've set up what you need for now in Identity and Access Management, return to your AWS Management Console home page, then do another search for SES.</p>\r\n\r\n<p>From here, you'll need to register your domain and whitelist a couple of emails so that they can be used during testing.</p>\r\n\r\n<p>For domains, go to the domains section and then click <strong>'Verify a New Domain'</strong> button and enter your details in there.</p>\r\n\r\n<p>During this process, one TXT and 3 CNAME records will need to be added to your domain name settings with your domain name's registrar. This <a href=\"https://www.youtube.com/watch?v=IrSP7soIq3A\">YouTube video</a> may help you with this process.</p>\r\n\r\n<p><img alt=\"\" src=\"https://wl-portfolio.s3.amazonaws.com/uploads/2019/08/04/custom_resource_records_8qQH0Ql.png\" style=\"height:100%; width:100%\" /></p>\r\n\r\n<p>The <strong>'Verification Status'</strong> and <strong>'DKIM Status'</strong> should both turn to verified in green text.</p>\r\n\r\n<p><img alt=\"\" src=\"https://wl-portfolio.s3.amazonaws.com/uploads/2019/08/04/ses_domain_verification_status.png\" style=\"height:100%; width:100%\" /></p>\r\n\r\n<p>Similarly, for emails, you may want to add your own email there for testing as well as add another email address that can be used as your <strong>DEFAULT_FROM_EMAIL</strong> setting within your project. This might be an <strong>admin@...</strong> or a <strong>webmaster@...</strong> email address that is used for transactional emails within your application.</p>\r\n\r\n<p><img alt=\"\" src=\"https://wl-portfolio.s3.amazonaws.com/uploads/2019/08/04/ses_email_verification_status.png\" style=\"height:100%; width:100%\" /></p>\r\n\r\n<p>Once you're happy that your Simple Email Service has been set up, you should have been provided with the settings that you can use within your environment variables. There are many ways to use environment variables, however, we will place these in a <strong>.env</strong> file within our project's root directory whilst we're in development and add them within our Heroku console as <strong>'Config Vars'</strong> for production.</p>\r\n\r\n<p>Note there are no spaces either side of the equals signs and there are no quotation marks or apostrophes required to denote strings.</p>\r\n\r\n<div>\r\n<div>\r\n<div>\r\n<div>\r\n<div>\r\n<pre>\r\n<code class=\"language-markdown\"># .env file\r\n\r\n# Django SES Email Backend Settings\r\nAWS_ACCESS_KEY_ID=your-access-key-id-from-amazon\r\nAWS_SECRET_ACCESS_KEY=your-aws-secret-key-from-amazon\r\nEMAIL_HOST=email-smtp.eu-west-1.amazonaws.com\r\nEMAIL_HOST_USER=your-email-host-user-from-amazon\r\nEMAIL_HOST_PASSWORD=your-email-host-password-from-amazon\r\nDEFAULT_FROM_EMAIL={FirstName} {LastName} <admin@{your-domain-name}.com>\r\n</code></pre>\r\n</div>\r\n</div>\r\n</div>\r\n</div>\r\n</div>\r\n\r\n<p>If you've seen my other tutorial on setting up Amazon's S3 storage service, then you can use the same <strong>AWS_SECRET_KEY_ID</strong> and <strong>AWS_SECRET_ACCESS_KEY</strong> for both the S3 storage service and the Simple Email Service. If you would prefer to use a separate setting, then there is one that can be used. You should <a href=\"https://pypi.org/project/django-ses/\">read the docs on PyPI for 'django-ses'</a>.</p>\r\n\r\n<p>You will now need to build your container. So far, you haven't seen the Docker build procedure which I'm using for my development setup, however, this specific docker-compose.yml file can be found in my GitHub repo for this website <a href=\"https://github.com/WayneLambert/portfolio/blob/master/docker-compose.yml\">here</a>.</p>\r\n\r\n<div>\r\n<div>\r\n<div>\r\n<div>\r\n<div>\r\n<pre>\r\n<code class=\"language-bash\">$ docker-compose build</code></pre>\r\n</div>\r\n</div>\r\n</div>\r\n</div>\r\n</div>\r\n\r\n<p>Now, it's time to test whether file uploads such as profile or post images are working as intended, so we will need to make sure that our Docker container is up and running.</p>\r\n\r\n<div>\r\n<div>\r\n<div>\r\n<div>\r\n<div>\r\n<pre>\r\n<code class=\"language-bash\">$ docker-compose up</code></pre>\r\n</div>\r\n</div>\r\n</div>\r\n\r\n<div>You should now be able to access your development version of your website at http://localhost:8001</div>\r\n\r\n<div> </div>\r\n</div>\r\n</div>\r\n\r\n<p><strong><u><span style=\"background-color:#ecf0f1\">Side Note</span></u><span style=\"background-color:#ecf0f1\">:</span></strong><span style=\"background-color:#ecf0f1\"> You may well use port 8000 for your development setup as that is the default Django development server, however, I configure my Docker setup to specifically use port 8001. I only do this so I can visually differentiate between a standard Django development web server and my Dockerized project.</span></p>\r\n\r\n<p>The workflow for setting up a registration and password reset process for your website is a totally separate process and beyond the scope of this tutorial. If you do have this already working locally, then you should request a forgotten password and the email will be generated using Amazon's Simple Email Service and it will come from your chosen email address that you defined in the <strong>DEFAULT_FROM_EMAIL</strong> setting.</p>\r\n\r\n<p>You can use Amazon's <strong>'Send a Test Email'</strong> feature to test whether your email configuration regarding Amazon SES is correctly configured. If this all works from here, then you know that your next challenge is wiring everything up in Django correctly.</p>\r\n\r\n<p><img alt=\"\" src=\"https://wl-portfolio.s3.amazonaws.com/uploads/2019/08/04/ses_send_test_email.png\" style=\"height:100%; width:100%\" /></p>", "reference_url": "", "publish_date": "2019-08-03T19:33:44.568693Z", "updated_date": "2020-07-02T16:29:59.685443Z", "image": "https://wl-portfolio.s3.amazonaws.com/post_images/amazon-ses.png", "status": "Publish", "word_count": 1026, "reading_time": 14, "post_absolute_url": "/blog/post/implementing-amazon-simple-email-service-django-site/", "author_username": "wayne-lambert", "author_first_name": "Wayne", "author_last_name": "Lambert", "author_full_name": "Wayne Lambert", "author_initials": "WL", "author_display_name": "Wayne Lambert", "author_join_year": 2019, "author_view": 1, "author_created_date": "2019-07-21T10:02:09.888000Z", "author_updated_date": "2022-12-14T14:44:36.068604Z", "author_absolute_url": "/blog/users/wayne-lambert/profile/", "author_profile_picture": "https://wl-portfolio.s3.amazonaws.com/profile_pics/gravatar-500.jpg", "categories": [ { "id": 7, "name": "Infrastructure", "slug": "infrastructure", "created_date": "2019-08-02T13:33:45.888597Z" } ] }, { "id": 5, "title": "Designing the Blog Project's Database Models Schema", "slug": "blog-project-database-models-schema", "content": "<p>This post gives a visual representation of the database schema used for this portfolio site.</p>\r\n\r\n<p>The database schema is illustrated by the visualisation tool built into JetBrains' database software called DataGrip. As an aside, I have tried many different database clients to handle PostgreSQL databases and DataGrip is certainly my favourite of them all.</p>\r\n\r\n<p><em>Because the image requires space to view the entire schema, right-click on the image and click 'View Image' to see it more clearly.</em></p>\r\n\r\n<p><img alt=\"\" src=\"https://wl-portfolio.s3.eu-west-2.amazonaws.com/post_images/db-schema.png\" style=\"width:100%\" /></p>\r\n\r\n<p>In addition to all of the default tables that come as part of Django's installation, I have added a blog app which is the main app with most of the main functionality throughout the project.</p>\r\n\r\n<p>The blog app has a <strong>Category</strong> model and a <strong>Post</strong> model. They are linked with a many-to-many relationship so that each post can belong to many categories and each category can have many posts.</p>\r\n\r\n<p>There is also a custom user model which links Django's users to profiles. This is achieved by using Django signals.</p>\r\n\r\n<p>The 'contacts' app contains a database table which captures the contact details for when people contact me through the contact form in the top left-hand corner of the home page of the site.</p>", "reference_url": "", "publish_date": "2019-07-22T15:53:57.817567Z", "updated_date": "2020-07-02T16:00:39.206999Z", "image": "https://wl-portfolio.s3.amazonaws.com/post_images/database.jpg", "status": "Publish", "word_count": 204, "reading_time": 3, "post_absolute_url": "/blog/post/blog-project-database-models-schema/", "author_username": "wayne-lambert", "author_first_name": "Wayne", "author_last_name": "Lambert", "author_full_name": "Wayne Lambert", "author_initials": "WL", "author_display_name": "Wayne Lambert", "author_join_year": 2019, "author_view": 1, "author_created_date": "2019-07-21T10:02:09.888000Z", "author_updated_date": "2022-12-14T14:44:36.068604Z", "author_absolute_url": "/blog/users/wayne-lambert/profile/", "author_profile_picture": "https://wl-portfolio.s3.amazonaws.com/profile_pics/gravatar-500.jpg", "categories": [ { "id": 1, "name": "Django", "slug": "django", "created_date": "2019-07-27T21:39:31.016414Z" }, { "id": 3, "name": "PostgreSQL", "slug": "postgresql", "created_date": "2019-07-27T21:39:41.170546Z" } ] }, { "id": 11, "title": "Implementing Amazon S3 Buckets for your Django Website", "slug": "implementing-amazon-s3-buckets-your-django-website", "content": "<p>It is a good idea and sometimes even necessary to store your media files outside of your server. In the case of an app being implemented on Heroku, then you need to use an alternative media storage such as Amazon S3 if you're providing features where users can uploads images or other types of media.</p>\r\n\r\n<p>Amazon's S3 has a number of steps to set up for your website which we'll run through here.</p>\r\n\r\n<p>You will need a couple of additional packages installing within your project. I personally use Docker for all of my development and production implementation, so I'll go through the steps using Docker. If you're using a Python virtual environment and package manager like pipenv, the steps are exactly the same except that you will need to remove the docker component that is prepended to the commands.</p>\r\n\r\n<p>Assuming that your Docker setup uses a service called <strong>'web'</strong> for your Django project, install relevant project packages:</p>\r\n\r\n<div>\r\n<pre>\r\n<code class=\"language-bash\">$ docker-compose exec web pipenv install boto3\r\n$ docker-compose exec web pipenv install django-storages</code></pre>\r\n</div>\r\n\r\n<p>Next up, you will need to configure your settings in your Django project. Make the region the one that is where the majority of your website visitors are likely to be located.</p>\r\n\r\n<div>\r\n<pre>\r\n<code class=\"language-python\"># Settings.py\r\n\r\n...\r\n\r\nINSTALLED_APPS = [\r\n ... # List of pre-installed Django apps\r\n\r\n # Third Party\r\n ... # List of 3rd party packages you installed for your Django project\r\n 'storages', # New\r\n\r\n # Project Apps\r\n ... # List of project apps you built for your Django project\r\n]\r\n\r\n...\r\n\r\n# Django Storages Settings\r\nDEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'\r\nAWS_STORAGE_BUCKET_NAME = os.environ['AWS_STORAGE_BUCKET_NAME']\r\nAWS_ACCESS_KEY_ID = os.environ['AWS_ACCESS_KEY_ID']\r\nAWS_SECRET_ACCESS_KEY = os.environ['AWS_SECRET_ACCESS_KEY']\r\nAWS_S3_FILE_OVERWRITE = False\r\nAWS_S3_REGION_NAME = 'eu-west-2'\r\nAWS_DEFAULT_ACL = None</code></pre>\r\n</div>\r\n\r\n<p> </p>\r\n\r\n<p>Log in to your <strong>AWS Management Console</strong> and do a search for <strong>IAM</strong>.</p>\r\n\r\n<p>Although this tutorial is not about setting up the <strong>Identity and Access Management </strong>for your Amazon account, it is recommended that you do so. In short, you will need to set up a group with some policy permissions to handle whatever aspects of Amazon's Web Services that you wish to use. For now, create a group and then attach the policy called <strong>'AmazonS3FullAccess'</strong> to the group.</p>\r\n\r\n<p>You will then need to create a user and attach that user to the group. This gives this user (namely you) full access to Amazon's S3 file storage web service. If you do not use Identity and Access Management, then you will be doing everything as the root user which is not a safe way to manage your account.</p>\r\n\r\n<p>Once you have set up what you need for now in Identity and Access Management, return to your AWS Management Console home page, then do another search for S3.</p>\r\n\r\n<p>From here, you can create buckets using the provided wizard. You will need to make sure that the user that you have just set up has full access to the bucket so that they can read and write from/to it.</p>\r\n\r\n<p>Once you're happy that your bucket has been set up, you should have been provided with the settings that you can use within your environment variables. There are many ways to use environment variables, however we will place these in a <strong>.env</strong> file within our project's root directory whilst we're in development and add them within our Heroku console as <strong>'Config Vars'</strong> for production.</p>\r\n\r\n<p>Note there are no spaces either side of the equals signs and there are no quotation marks or apostrophes required to denote strings.</p>\r\n\r\n<div>\r\n<pre>\r\n<code class=\"language-markdown\"># .env file\r\n\r\n# Django Storages Settings\r\nAWS_STORAGE_BUCKET_NAME=your-s3-bucket-name\r\nAWS_ACCESS_KEY_ID=your-access-key-id-from-amazon\r\nAWS_SECRET_ACCESS_KEY=your-aws-secret-key-from-amazon</code></pre>\r\n</div>\r\n\r\n<p>There is one more important step to ensure that all of this works. In your settings file, you may have a setting like below in your <strong>settings.py</strong> file, especially if you have been doing all of your development locally up until now.</p>\r\n\r\n<div>\r\n<pre>\r\n<code class=\"language-python\"># Settings.py\r\n\r\nMEDIA_ROOT = os.path.join(BASE_DIR, 'media')</code></pre>\r\n</div>\r\n\r\n<p>You will need to delete (or at least temporarily comment out) the setting so that it is not being used by Django. You are now intending for S3 to be used as the default file storage for any of your media requirements as specified in the <strong>'DEFAULT_FILE_STORAGE'</strong> setting you set earlier. This counts for both development and production.</p>\r\n\r\n<p>You will now need to build your container. So far, you haven't seen the Docker build procedure which I am using for my development setup, however this specific <strong>docker-compose.yml</strong> file can be found in my GitHub repo for this website <a href=\"https://github.com/WayneLambert/portfolio/blob/master/docker-compose.yml\">here</a>.</p>\r\n\r\n<div>\r\n<pre>\r\n<code class=\"language-bash\">$ docker-compose build</code></pre>\r\n</div>\r\n\r\n<p>Now, it's time to test whether file uploads such as profile or post images are working as intended, so we will need to make sure that our Docker container is up and running.</p>\r\n\r\n<div>\r\n<pre>\r\n<code class=\"language-bash\">$ docker-compose up</code></pre>\r\n</div>\r\n\r\n<p>You should now be able to access your development version of your website at http://localhost:8001</p>\r\n\r\n<p><strong><u><span style=\"background-color:#ecf0f1\">Side Note</span></u><span style=\"background-color:#ecf0f1\">:</span></strong><span style=\"background-color:#ecf0f1\"> You may well use port 8000 for your development setup as that is the default Django development server, however I configure my Docker setup to specifically use port 8001. I only do this so I can visually differentiate between a standard Django development web server and my Dockerized project.</span></p>\r\n\r\n<p>Now simply log in to your website and attempt to upload some media to your website. This is anywhere within your project's models that you have used an image field or a file field. Check the url of the media resource that has just been uploaded. If it has an Amazon S3 url, it will have worked. You can also confirm this by inspecting your S3 bucket within your Amazon AWS Management Console.</p>\r\n\r\n<p>I don't know about you but I think I am going to set up any of my project's that I intend to deploy from the get-go using S3. I think it is so easy to set these things up from the start once you have a repeatable system that it can save you the headaches when it comes to deploying your application down the line. I also have a preference for installing any packages that I know I will need for my project at the start of the project and can easily add them to a Bash script that I maintain for this very reason.</p>", "reference_url": "", "publish_date": "2019-08-03T12:40:16.760364Z", "updated_date": "2020-01-29T14:14:31.764191Z", "image": "https://wl-portfolio.s3.amazonaws.com/post_images/amazon-s3.jpg", "status": "Publish", "word_count": 1040, "reading_time": 14, "post_absolute_url": "/blog/post/implementing-amazon-s3-buckets-your-django-website/", "author_username": "wayne-lambert", "author_first_name": "Wayne", "author_last_name": "Lambert", "author_full_name": "Wayne Lambert", "author_initials": "WL", "author_display_name": "Wayne Lambert", "author_join_year": 2019, "author_view": 1, "author_created_date": "2019-07-21T10:02:09.888000Z", "author_updated_date": "2022-12-14T14:44:36.068604Z", "author_absolute_url": "/blog/users/wayne-lambert/profile/", "author_profile_picture": "https://wl-portfolio.s3.amazonaws.com/profile_pics/gravatar-500.jpg", "categories": [ { "id": 1, "name": "Django", "slug": "django", "created_date": "2019-07-27T21:39:31.016414Z" }, { "id": 7, "name": "Infrastructure", "slug": "infrastructure", "created_date": "2019-08-02T13:33:45.888597Z" } ] } ] }