Skip to content

Commit

Permalink
Merge pull request #1 from lcgeneralprojects/development
Browse files Browse the repository at this point in the history
Development
  • Loading branch information
lcgeneralprojects authored Feb 20, 2024
2 parents e3a1de3 + 9629cad commit 269a290
Show file tree
Hide file tree
Showing 13 changed files with 193 additions and 34 deletions.
3 changes: 3 additions & 0 deletions .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# django-postgresql study
[![en](https://img.shields.io/badge/lang-en-red)](https://github.com/lcgeneralprojects/django-posgresql-study/blob/development/README.md)
[![ru](https://img.shields.io/badge/lang-ru-green)](https://github.com/lcgeneralprojects/django-posgresql-study/blob/development/README.ru.md)

A simple blog project, meant to be proof of basic competence in working with the technologies of Django and PostgreSQL.

There are two intended ways of starting the server.
First, one should navigate tho the `server/` subdirectory of the project, and then executing one of the following commands:
- to start the server directly, use the command `python manage.py runserver`.
- to start the server using Docker, use the command `docker-compose up [--build]`.

Currently, the application allows a user to register, log in, view, post, edit, and delete comments. The access to this functionality is provided by the links in the header of the project's pages.
12 changes: 12 additions & 0 deletions README.ru.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# django-postgresql study
[![en](https://img.shields.io/badge/lang-en-red)](https://github.com/lcgeneralprojects/django-posgresql-study/blob/development/README.md)
[![ru](https://img.shields.io/badge/lang-ru-green)](https://github.com/lcgeneralprojects/django-posgresql-study/blob/development/README.ru.md)

Простой проект-блог, предназначенный для доказательства базовой компетенции в области работы с технологиями Django и PostgreSQL.

На данный момент подразумевается два способа запуска сервера.
Для начала пользователь должен перейти в поддиректорию `server/` и запустить выполнение одной из следующих команд:
- чтобы запустить сервер напрямую, пользователю нужно воспользоваться командой `python manage.py runserver`
- чтобы запустить сервер с помощью Docker, пользователю нужно воспользоваться командой `docker-compose up [--build]`.

На данный момент приложение позволяет пользователю регистрироваться, заходить в свою учетную запись, видеть комментарии, а также оставлять, редактировать и удалять их. Доступ к этим возможностям предоставляется с помощью ссылок в головном элементе страниц проекта.
1 change: 1 addition & 0 deletions server/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.env
3 changes: 2 additions & 1 deletion server/django_postgresql_study/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@
SECRET_KEY = env("SECRET_KEY")

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
# DEBUG = True
DEBUG = env("DEBUG")

ALLOWED_HOSTS = []

Expand Down
26 changes: 25 additions & 1 deletion server/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,29 @@ services:
image: django_postgresql_study_image
command: python manage.py runserver 0.0.0.0:8000
build: .
volumes:
- .:/app
ports:
- "8000:8000"
- "8000:8000"
expose:
- "8000"
env_file:
- ./django_postgresql_study/dev.env
depends_on:
- db

db:
image: postgres:16.1
volumes:
- postgres_data:/var/lib/postgresql/data
ports:
- "5432:5432"
# env_file:
# - ./django_postgresql_study/dev.env
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres_pw
- POSTGRES_DB=postgres

volumes:
postgres_data:
18 changes: 14 additions & 4 deletions server/dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,23 @@ FROM python:3.12.0

WORKDIR /app

COPY ./ .
COPY requirements.txt .

# Set environment variables
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1

# install psycopg2 dependencies
# RUN apt-get update \
# && apt-get add postgresql-dev gcc python3-dev musl-dev
RUN apt-get update && \
apt-get install -y libpq-dev gcc

# Install dependencies
COPY requirements.txt .
RUN pip install -r requirements.txt

# Copy project
COPY ./ .

EXPOSE 8000

CMD ["python", "./manage.py", "runserver"]
# CMD ["python", "./manage.py", "runserver", "0.0.0.0:8000"]
3 changes: 2 additions & 1 deletion server/my_app/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

# URLConf
urlpatterns = [
path(r'hello/', views.say_hello),
# path(r'hello/', views.say_hello),
# path(r'insert/', views.dummy_insert),
path(r'register/', views.sign_up, name='register'),
path(r'login/', views.sign_in, name='login'),
Expand All @@ -12,5 +12,6 @@
path(r'home/create', views.create_post, name='post_create'),
path(r'home/edit/<int:id>/', views.edit_post, name='post_edit'),
path(r'home/delete/<int:id>/', views.delete_post, name='post_delete'),
path(r'home/post_create_norefresh', views.create_post_norefresh, name='post_create_norefresh'),
path(r'', views.default_view, name='default')
]
56 changes: 44 additions & 12 deletions server/my_app/views.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,26 @@
from django.shortcuts import render, redirect, get_object_or_404
from django.http import HttpResponse
from django.http import HttpResponse, JsonResponse
from django.contrib import messages
from django.contrib.auth import login, authenticate, logout
from django.contrib.auth.decorators import login_required
from django.core import serializers
from .models import Post
from .forms import LoginForm, RegisterForm, PostForm
import psycopg2
import environ
import logging
import re

# Environ stuff
env = environ.Env()
environ.Env.read_env()

# Create your views here.
def say_hello(request):
# return HttpResponse('Hello, World!')
x = 1
y = 2
return render(request, 'hello.html', {'name': 'Test'})
# # Create your views here.
# def say_hello(request):
# # return HttpResponse('Hello, World!')
# x = 1
# y = 2
# return render(request, 'hello.html', {'name': 'Test'})

# def dummy_insert(request):
# # return HttpResponse(request.GET.get('input'))
Expand Down Expand Up @@ -102,15 +105,44 @@ def create_post(request):
elif request.method == 'POST':
form = PostForm(request.POST)
if form.is_valid():
user = form.save(commit=False)
user.author = request.user
post = form.save(commit=False)
post.author = request.user
form.save()
messages.success(request, 'The post has been created successfully.')
return redirect('home')
else:
messages.error(request, 'Please correct the following errors:')
return render(request, 'post_form.html', {'form': form})


@login_required
def create_post_norefresh(request):
if request.method == 'POST':
title = request.POST['title']
content = request.POST['content']
author = request.user

new_post = Post(title=title, content=content, author=author)
new_post.save()

# Currently suppressing the messages in the no-refresh view,
# as that leads to the accumulation of messages that are only shown upon refresh.
# TODO: restore the functionality after introducing a header to the HTML pages.
# success = 'New comment created successfully'
# messages.success(request, success)

# Building a response
# TODO: switch the serializer to that of the Django REST framework
post_array = serializers.serialize('json', [new_post])
response = post_array[1:-1]

response = re.sub(r'"author": \d+', f'"author": "{request.user.username}"', response)

logging.warning(response)
logging.warning(request.user.username)

return HttpResponse(response, content_type='application/json')


@login_required
def edit_post(request, id):
Expand Down Expand Up @@ -141,7 +173,7 @@ def delete_post(request, id):

elif request.method == 'POST':
post.delete()
messages.success(request, 'The post has been deleted successfully.')
messages.success(request, 'The comment has been deleted successfully.')
return redirect('home')


Expand All @@ -155,8 +187,8 @@ def home(request):
elif request.method == 'POST':
form = PostForm(request.POST)
if form.is_valid():
user = form.save(commit=False)
user.author = request.user
post = form.save(commit=False)
post.author = request.user
form.save()
messages.success(request, 'The post has been created successfully.')
return render(request, 'home.html', context)
Expand Down
2 changes: 2 additions & 0 deletions server/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ asgiref==3.7.2
Django==4.2.7
django-debug-toolbar==4.2.0
django-environ==0.11.2
djangorestframework==3.14.0
psycopg2==2.9.9
pytz==2024.1
setuptools==57.0.0
sqlparse==0.4.4
typing_extensions==4.8.0
Expand Down
10 changes: 10 additions & 0 deletions server/static/js/script.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
function dummy() {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementsByTagName("main").innerHTML = this.responseText;
}
};
xhttp.open("POST", "home", true);
xhttp.send();
}
6 changes: 6 additions & 0 deletions server/templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
<meta charset="UTF-8">
<title>My site</title>
<link rel="stylesheet" href="{% static 'css/style.css' %}" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.13.2/jquery-ui.min.js" integrity="sha256-lSjKY0/srUM9BE3dPm+c4fBo1dky2v27Gdjm2uoZaL0=" crossorigin="anonymous"></script>"></script>
</head>
<style>
{% comment %} #main_container {
Expand All @@ -18,6 +20,10 @@
{% block style %}
{% endblock style %}
</style>

{% block script %}
{% endblock script %}

<body>
<header>
{% if request.user.is_authenticated %}
Expand Down
75 changes: 60 additions & 15 deletions server/templates/home.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,67 @@
{% block style %}
{% endblock style %}

{% block script %}
<script type="text/javascript">
$(document).on('submit', '#post-form', function (e) {
e.preventDefault();
$.ajax({
type: 'POST',
url: '{% url "post_create_norefresh" %}',
data: {
title: $('#id_title').val(),
content: $('#id_content').val(),
csrfmiddlewaretoken: $('input[name=csrfmiddlewaretoken]').val()
},
dataType: 'json',
success: function (data) {

var date = $.datepicker.formatDate('d M, Y', new Date(data['fields'].published_at),
{
monthNamesShort: ['Jan','Feb','Mar','Apr','Maj','Jun','Jul','Aug','Sep','Okt','Nov','Dec']
});

var author = data['fields'].author.charAt(0).toUpperCase()+data['fields'].author.slice(1)
var post_string = '<h2>'+data['fields'].title+'</h2>'+
'<small>'+'Published on '+date+' by '+author+'</small>'+
'<p>'+data['fields'].content+'</p>'+
'<p><a href="/home/edit/'+data['pk']+'/">Edit</a></p>'+
'<p><a href="/home/delete/'+data['pk']+'/">Delete</a></p>';

console.log('data: '+JSON.stringify(data));
console.log('post_string: '+post_string);
$(".postsDiv").prepend(post_string);
},
error: function (error) {
console.log('We have encountered an error');
console.log(error);
}
})
})
</script>
{% endblock script %}

{% block content %}
<h1>Create Post</h1>
<form method="POST">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Save" />
</form>
{% if request.user.is_authenticated %}
<h1>Create Post</h1>
<form id="post-form" method="POST">
{% csrf_token %}
{{ form.as_p }}
{% comment %} <input type="submit" value="Save" /> {% endcomment %}
<button type="submit">Save</button>
</form>
{% endif %}
<h1>My Posts</h1>
{% for post in posts %}
<h2>{{ post.title }}</h2>
<snall>Published on {{ post.published_at | date:"M d, Y" }} by {{ post.author | title}}</small>
<p>{{ post.content }}</p>
<div class='postsDiv'>
{% for post in posts %}
<h2>{{ post.title }}</h2>
<small>Published on {{ post.published_at | date:"d M, Y" }} by {{ post.author | capfirst}}</small>
<p>{{ post.content }}</p>

{% if request.user.is_authenticated and request.user == post.author %}
<p><a href="{% url 'post_edit' post.id %}">Edit</a></p>
<p><a href="{% url 'post_delete' post.id %}">Delete</a></p>
{% endif %}
{% endfor %}
{% if request.user.is_authenticated and request.user == post.author %}
<p><a href="{% url 'post_edit' post.id %}">Edit</a></p>
<p><a href="{% url 'post_delete' post.id %}">Delete</a></p>
{% endif %}
{% endfor %}
</div>
{% endblock content %}

0 comments on commit 269a290

Please sign in to comment.