Commit cd03ea56 authored by Tang, Alexander's avatar Tang, Alexander
Browse files

Merge remote-tracking branch 'remotes/origin/master' into Alex_2020_06_23

# Conflicts:
#	blog/views.py
parents dd6b2997 21c790de
......@@ -35,6 +35,9 @@ add several states:
* 0 = Normal Article
* 1 = Article is hidden in overview
* 2 = Article can have comments
* 3 = Article is hidden, can have comments
* 4 = Article is User only
* 6 = Article can have comments ans is User only
Setting the state to 3 would hide the article, but allow comments to it.
......
......@@ -11,6 +11,8 @@ from django.utils.text import slugify
BLOG_STATE_HIDE_FROM_LIST = 1
BLOG_STATE_CAN_HAVE_COMMENTS = 2
BLOG_STATE_USER_ONLY = 4
BLOG_STATE_CAN_HAVE_COMMENTS_AND_USER_ONLY = 6
# Create your models here.
......@@ -18,6 +20,15 @@ class Blog(models.Model):
""" Blog class
One blog is a single block of content which can be shown on our page
"""
STATUS_CHOICES = (
(0, 'Sichtbarer Blog'),
(1, 'Versteckter Blog (z.B. Impressum)'),
(2, 'Sichtbarer Blog mit Kommentaren'),
(3, 'Versteckter Blog mit Kommentaren'),
(4, 'Blog nur für User'),
(6, 'Blog mit Kommentaren nur für User'),
)
identifier = models.CharField(max_length=500, unique=True, default=uuid.uuid4())
title = models.CharField(default="Titel", max_length=200)
description = RichTextUploadingField(blank=True)
......@@ -26,7 +37,7 @@ class Blog(models.Model):
image = models.ImageField(upload_to='images/', blank=True)
created = models.DateField(auto_now_add=True)
edited = models.DateField(auto_now=True)
status = models.IntegerField(default=1)
status = models.IntegerField(choices=STATUS_CHOICES,default=1)
slug = models.SlugField(max_length=300, unique=True, null=False)
def __str__(self):
......
......@@ -3,7 +3,7 @@
<!DOCTYPE html>
<html lang="en">
<head>
{% bootstrap_javascript %}
{% bootstrap_javascript jquery="slim" %}
{% bootstrap_css %}
<link rel="stylesheet" href="{% static 'blog/styles.css' %}">
{% block css %}
......@@ -15,16 +15,52 @@
</title>
</head>
<body>
<nav class="navbar fixed-top navbar-expand-lg navbar-light bg-light">
<a class="navbar-brand" href="{% url 'blog:all_blogs' %}">Personal Blog</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavDropdown" aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNavDropdown">
<ul class="navbar-nav">
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdownMenuLink" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Blog Archiv
</a>
<div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
{% for blog in blogs %}
<a class="dropdown-item" href="{{ blog.slug }}">{{ blog.created }}: <strong>{{ blog.title }}</strong></a>
{% endfor %}
</div>
</li>
</ul>
<ul class="navbar-nav ml-auto">
{% if user.is_authenticated %}
<li class="nav-item nav-link disabled">Hallo, {{ user.username }}!</li>
{% if user.is_staff %}
<li class="nav-item"><a class="nav-link" href="/admin">Adminbereich</a></li>
{% endif %}
<li class="nav-item"><a class="nav-link" href="{% url 'blog:user_logout' %}">Logout</a></li>
{% else %}
<li class="nav-item"><a class="nav-link" href="{% url 'blog:user_login' %}">Login</a></li>
{% endif %}
</ul>
</div>
</nav>
<div class="jumbotron jumbotron-fluid">
<div class="container">
{% block heading %}
{% endblock %}
</div>
</div>
{% block content %}
{% endblock %}
<footer class="fixed-bottom bg-light">
<ul class="nav justify-content-end">
<li class="nav-item"><a class="nav-link" href="{% url 'blog:blog-detail' slug='impress' %}">Impressum</a></li>
<li class="nav-item"><a class="nav-link" href="{% url 'blog:blog-detail' slug='contact' %}">Kontakt</a></li>
......
{% extends 'blog/base.html' %}
{% load bootstrap4 %}
{% block page-title %}
Login
{% endblock %}
{% block heading %}
<h1 class="display-2">Login</h1>
{% endblock %}
{% block content %}
<div class="container">
<form class="pt-4 px-3" action="{% url 'blog:user_login' %}" method="post">
{% csrf_token %}
{% if error_message %}
<p class="bg-danger p-d ml-b">{{ error_message }}</p>
{% endif %}
<div class="form-group row clearfix">
<label for="username" class="col-sm-3 col-md-2 col-lg-2 col-xl-1 col-form-label">Username:</label>
<div class="col-3">
<input name="username" value="" type="text" class="form-control" />
</div>
</div>
<div class="form-group row clearfix">
<label for="password" class="col-sm-3 col-md-2 col-lg-2 col-xl-1 col-form-label">Passwort:</label>
<div class="col-3">
<input name="password" type="password" class="form-control" />
</div>
</div>
<div class="form-group row">
<div class="col-sm-2 col-md-5 col-lg-5 col-xl-4">
<input name="login" type="submit" value="Login" class="btn btn-success float-right" /> &nbsp;
</div>
</div>
</div>
</div>
</form>
</div>
{% endblock %}
\ No newline at end of file
......@@ -13,9 +13,9 @@ Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.conf.urls import url
from django.urls import path
from . import views # . because the views are in the same folder
from . import views # . because the views are in the same folder
app_name = 'blog'
......@@ -24,6 +24,8 @@ urlpatterns = [
path('<slug:slug>', views.detail, name='blog-detail'),
path('comment/save', views.save_comment, name='save_comment')
path('comment/save', views.save_comment, name='save_comment'),
url('login/', views.user_login, name='user_login'),
url('logout/', views.user_logout, name='user_logout')
]
\ No newline at end of file
......@@ -2,14 +2,33 @@ from django.http import HttpResponseNotAllowed, Http404
from django.contrib import messages
from django.shortcuts import render, get_object_or_404, redirect
from django.urls import reverse_lazy
from django.db.models import Q
from itertools import chain
from random import shuffle
from django.contrib.auth import authenticate, login, logout
from .forms import CommentForm
from .models import *
from django.views.generic import DetailView
def get_all_blogs(request):
""" Get all blog articles.
Will exclude those which should be hidden in this list (e.g. impress)
Authenticated user get articles with status 4 and 6 extra.
"""
if request.user.is_authenticated:
# Exclude those with status hidden from the overall list, but show everything else
query = f'status & {BLOG_STATE_HIDE_FROM_LIST} <> {BLOG_STATE_HIDE_FROM_LIST}'
else:
# Exclude those with status hidden from the overall list and the user only blogs
query = f'status & {BLOG_STATE_HIDE_FROM_LIST}<>{BLOG_STATE_HIDE_FROM_LIST}' \
f' AND status & {BLOG_STATE_USER_ONLY}<>{BLOG_STATE_USER_ONLY}' \
f' AND status & {BLOG_STATE_CAN_HAVE_COMMENTS_AND_USER_ONLY}' \
f'<>{BLOG_STATE_CAN_HAVE_COMMENTS_AND_USER_ONLY}'
blogs = Blog.objects.extra(where=[query]).order_by('-created')
return blogs
# Create your views here.
......@@ -19,7 +38,7 @@ def all_blogs(request):
"""
# Exclude those with status hidden from the overall list
query = f'status & {BLOG_STATE_HIDE_FROM_LIST} <> {BLOG_STATE_HIDE_FROM_LIST}'
allblogs = Blog.objects.extra(where=[query]).order_by('-created')
allblogs = get_all_blogs(request)
# split into subqueries, turn into lists for shuffling, then being chained
if allblogs.count() > 3:
......@@ -28,16 +47,18 @@ def all_blogs(request):
shuffle(all_blogs_except_last_three_in_random_order)
allblogs = chain(last_three_blogs, all_blogs_except_last_three_in_random_order)
return render(request, 'blog/all_blogs.html', {'blogs': allblogs})
blogs = get_all_blogs(request)
return render(request, 'blog/all_blogs.html', {'blogs': blogs, 'overview_blogs': allblogs})
def detail(request, slug):
""" Shows one complete article, based on the slug (url)
If comments are allowed, they will be shown as well (uses an extended template)
"""
blogs = get_all_blogs(request)
blogResult = Blog.objects.filter(slug=slug)
print(blogResult)
if blogResult.count() == 0:
raise Http404("Url does not exist")
......@@ -49,9 +70,9 @@ def detail(request, slug):
form = CommentForm(initial={'related_blog': blog.id})
# render with comments
return render(request, 'blog/detail_with_comments.html',
{'blog': blog, 'comments': comments, 'comment_form': form})
{'blog': blog, 'comments': comments, 'comment_form': form, 'blogs': blogs})
return render(request, 'blog/detail.html', {'blog': blog})
return render(request, 'blog/detail.html', {'blog': blog, 'blogs': blogs})
def save_comment(request):
......@@ -73,3 +94,33 @@ def save_comment(request):
blog = get_object_or_404(Blog, pk=form.data.get('related_blog'))
# back to the details page
return redirect(reverse_lazy('blog:blog-detail', kwargs={'slug': blog.slug}))
def user_login(request):
"""User login
"""
blogs = get_all_blogs(request)
if request.method == 'POST':
# Process the POST Data
username = request.POST['username']
password = request.POST['password']
# Check username and password
user = authenticate(username=username, password=password)
if user is not None:
login(request, user)
return redirect(reverse_lazy('blog:all_blogs'))
else:
# Throw Error if credentials are wrong
return render(request, 'blog/login.html', {'error_message': 'Falscher Username und / oder Passwort.', 'blogs': blogs})
else:
# No POST data -> then show the page again
return render(request, 'blog/login.html', {'blogs': blogs})
def user_logout(request):
"""User logout
"""
logout(request)
return redirect(reverse_lazy('blog:all_blogs'))
\ No newline at end of file
......@@ -109,7 +109,7 @@ AUTH_PASSWORD_VALIDATORS = [
# Internationalization
# https://docs.djangoproject.com/en/3.0/topics/i18n/
LANGUAGE_CODE = 'en-us'
LANGUAGE_CODE = 'de-de'
TIME_ZONE = 'UTC'
......
......@@ -21,7 +21,7 @@ from startpage import views
from django.conf.urls import url, include
urlpatterns = [
path('admin/', admin.site.urls),
path('admin/', admin.site.urls, name='admin_area'),
path('', views.home, name='home'),
path('blog/', include('blog.urls')),
path('startpage/', include('startpage.urls')),
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment