Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit a15ae2a

Browse files
committed
First attempt
0 parents  commit a15ae2a

40 files changed

+551
-0
lines changed

db.sqlite3

140 KB
Binary file not shown.

manage.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#!/usr/bin/env python
2+
"""Django's command-line utility for administrative tasks."""
3+
import os
4+
import sys
5+
6+
7+
def main():
8+
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'streamtutorial.settings')
9+
try:
10+
from django.core.management import execute_from_command_line
11+
except ImportError as exc:
12+
raise ImportError(
13+
"Couldn't import Django. Are you sure it's installed and "
14+
"available on your PYTHONPATH environment variable? Did you "
15+
"forget to activate a virtual environment?"
16+
) from exc
17+
execute_from_command_line(sys.argv)
18+
19+
20+
if __name__ == '__main__':
21+
main()

post/__init__.py

Whitespace-only changes.
143 Bytes
Binary file not shown.

post/__pycache__/admin.cpython-37.pyc

525 Bytes
Binary file not shown.

post/__pycache__/forms.cpython-37.pyc

638 Bytes
Binary file not shown.
876 Bytes
Binary file not shown.

post/__pycache__/urls.cpython-37.pyc

362 Bytes
Binary file not shown.

post/__pycache__/views.cpython-37.pyc

1.99 KB
Binary file not shown.

post/admin.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
from django.contrib import admin
2+
from .models import Post
3+
4+
# Register your models here.
5+
class PostAdmin(admin.ModelAdmin):
6+
list_display = ('id', 'message', 'user', 'date_created')
7+
list_filter = ('id', 'message', 'user', 'date_created')
8+
list_display_links = ('message',)
9+
10+
admin.site.register(Post, PostAdmin)

post/apps.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
from django.apps import AppConfig
2+
3+
4+
class ProductsConfig(AppConfig):
5+
name = 'products'

post/forms.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
from django import forms
2+
from .models import Post
3+
4+
class PostForm(forms.ModelForm):
5+
6+
class Meta:
7+
model = Post
8+
fields = ['message']
9+
widgets = {'message': forms.TextInput(attrs={'class' : 'mdl-textfield__input'}) }
10+
11+

post/migrations/0001_initial.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Generated by Django 3.0.6 on 2020-07-10 09:20
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
initial = True
9+
10+
dependencies = [
11+
]
12+
13+
operations = [
14+
migrations.CreateModel(
15+
name='Product',
16+
fields=[
17+
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
18+
('title', models.CharField(max_length=100, null=True)),
19+
('color', models.CharField(max_length=10, null=True)),
20+
('size', models.CharField(max_length=5, null=True)),
21+
],
22+
),
23+
]
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Generated by Django 3.0.6 on 2020-07-11 09:33
2+
3+
from django.conf import settings
4+
from django.db import migrations, models
5+
import django.db.models.deletion
6+
7+
8+
class Migration(migrations.Migration):
9+
10+
dependencies = [
11+
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
12+
('post', '0001_initial'),
13+
]
14+
15+
operations = [
16+
migrations.CreateModel(
17+
name='Post',
18+
fields=[
19+
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
20+
('message', models.TextField()),
21+
('date_created', models.DateTimeField(auto_now_add=True)),
22+
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
23+
],
24+
),
25+
migrations.DeleteModel(
26+
name='Product',
27+
),
28+
]

post/migrations/__init__.py

Whitespace-only changes.
Binary file not shown.
Binary file not shown.
154 Bytes
Binary file not shown.

post/models.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
from django.db import models
2+
from django.contrib.auth.models import User
3+
from django.utils.timezone import utc
4+
import datetime
5+
6+
# Create your models here.
7+
class Post(models.Model):
8+
user = models.ForeignKey(User, on_delete=models.CASCADE)
9+
message = models.TextField()
10+
date_created= models.DateTimeField(auto_now_add=True)
11+
12+
@property
13+
def get_last_hour(self):
14+
now = datetime.datetime.utcnow().replace(tzinfo=utc)
15+
timediff = now - self.date_created
16+
return round(timediff.total_seconds() / 3600)
17+

post/static/post/base.css

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
2+
*, *:before, *:after {
3+
box-sizing: border-box;
4+
}
5+
6+
html, body {
7+
margin:0;
8+
padding:0;
9+
background-color: #CCC;
10+
}
11+
12+
13+
.page-content {
14+
display: grid;
15+
grid-template-columns: 1fr;
16+
/* grid-template-areas: 'create-post'
17+
'stream-posts'
18+
'stream-content'; */
19+
grid-gap:1rem;
20+
padding: 1rem;
21+
justify-self:center;
22+
}
23+
24+
.create-post {
25+
background-color: white;
26+
width:40vw;
27+
padding:1rem;
28+
justify-self: center;
29+
}
30+
31+
.stream-content {
32+
display: grid;
33+
grid-gap:1rem;
34+
width:100%;
35+
}
36+
37+
.stream-posts {
38+
background-color: white;
39+
width:40vw;
40+
justify-self: center;
41+
padding:1rem;
42+
display:grid;
43+
grid-template-columns: 0.1fr auto;
44+
grid-template-rows: 40px auto;
45+
grid-template-areas: 'stream-post-img stream-post-user'
46+
'stream-post-msg stream-post-msg';
47+
}
48+
49+
.stream-posts-user {
50+
grid-area: stream-post-user;
51+
padding:0.5rem;
52+
53+
}
54+
.stream-posts-msg {
55+
grid-area: stream-post-msg;
56+
padding:0.5rem;
57+
}
58+
59+
60+
.stream-posts-img {
61+
grid-area: stream-post-img;
62+
padding:0.5rem;
63+
}
64+
65+
.mat-elevation-z6 {
66+
box-shadow: 0 3px 5px -1px rgba(0,0,0,.2), 0 6px 10px 0 rgba(0,0,0,.14), 0 1px 18px 0 rgba(0,0,0,.12);
67+
}

post/templates/post/base.html

Whitespace-only changes.

post/templates/post/index.html

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
{% load static %}
2+
<!doctype html>
3+
<html>
4+
<head>
5+
<meta charset="utf-8">
6+
<title>Django Real Time</title>
7+
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
8+
<link rel="stylesheet" href="https://code.getmdl.io/1.3.0/material.light_blue-indigo.min.css" />
9+
<script defer src="https://code.getmdl.io/1.3.0/material.min.js"></script>
10+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
11+
<script src='https://kit.fontawesome.com/a076d05399.js'></script>
12+
<link rel="stylesheet" href="{% static 'post/base.css' %}">
13+
</head>
14+
<body>
15+
<!-- Always shows a header, even in smaller screens. -->
16+
<div class="mdl-layout mdl-js-layout mdl-layout--fixed-header">
17+
<header class="mdl-layout__header">
18+
<div class="mdl-layout__header-row mat-evelation-z6">
19+
<!-- Title -->
20+
<span class="mdl-layout-title">Django Real Time</span>
21+
<!-- Add spacer, to align navigation to the right -->
22+
<div class="mdl-layout-spacer"></div>
23+
<!-- Navigation. We hide it in small screens. -->
24+
<nav class="mdl-navigation mdl-layout--large-screen-only">
25+
<a class="mdl-navigation__link" href="">About</a>
26+
</nav>
27+
</div>
28+
</header>
29+
<div class="mdl-layout__drawer">
30+
<span class="mdl-layout-title">Title</span>
31+
<nav class="mdl-navigation">
32+
<a class="mdl-navigation__link" href="">Link</a>
33+
<a class="mdl-navigation__link" href="">Link</a>
34+
<a class="mdl-navigation__link" href="">Link</a>
35+
<a class="mdl-navigation__link" href="">Link</a>
36+
</nav>
37+
</div>
38+
<main class="mdl-layout__content">
39+
<div class="page-content">
40+
<div class="create-post mat-elevation-z6">
41+
<form action="." method="POST">
42+
{% csrf_token %}
43+
44+
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
45+
{{ form.message }}
46+
<label class="mdl-textfield__label" for="{{ form.message.id_for_label }}">Whats on your mind, {{request.user}}?</label>
47+
</div>
48+
49+
<div>
50+
<!-- Accent-colored raised button -->
51+
<button class="mdl-button mdl-js-button mdl-button--raised mdl-button--accent">Create Post
52+
</button>
53+
</div>
54+
</form>
55+
</div>
56+
<div id="stream-content" class="stream-content"></div>
57+
</div>
58+
</main>
59+
</div>
60+
61+
</body>
62+
</html>
63+
64+
<script defer src="https://code.getmdl.io/1.3.0/material.min.js"></script>
65+
<script>
66+
67+
var eventSource = new EventSource("{% url 'post:stream' %}");
68+
69+
eventSource.onopen = function() {
70+
console.log('Yay! its open?');
71+
}
72+
73+
eventSource.onmessage = function(e) {
74+
console.log(e)
75+
final_data = JSON.parse(e.data)
76+
content = "";
77+
78+
final_data.forEach(function (item){
79+
content += buildPostContent(item['date_created'], item['message'], item['user__username'])
80+
})
81+
document.getElementById('stream-content').innerHTML = content;
82+
console.log(content)
83+
}
84+
85+
eventSource.onerror = function(e) {
86+
console.log(`error ${e}`);
87+
}
88+
89+
function buildPostContent(date_created, message, username) {
90+
last_hour = getLastHour(date_created)
91+
content = `<div class="stream-posts"> <div class="stream-posts-img"><i class="far fa-smile" style="font-size:32px"></i></div>
92+
<div class="stream-posts-user">
93+
<div><strong><a href="#">${username}</a></strong></div>
94+
<div>${last_hour}hr</div>
95+
</div>
96+
<div class="stream-posts-msg">
97+
<h4>${message}</h4>
98+
</div></div>`;
99+
return content
100+
101+
}
102+
103+
104+
function getLastHour(dt) {
105+
let dt1 = new Date(dt);
106+
let now = new Date();
107+
let hours = Math.abs(now - dt1) / 36e5;
108+
109+
return Math.round(hours);
110+
111+
}
112+
113+
</script>
114+

post/templatetags/__init__.py

Whitespace-only changes.
Binary file not shown.
Binary file not shown.
Binary file not shown.

post/templatetags/mdl_form_tags.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
2+
from django import template
3+
4+
register = template.Library()
5+
6+
@register.filter(is_safe=True)
7+
def textfield_with_floating_label(value):
8+
"""Removes all values of arg from the given string"""
9+
mdl_textfield = '<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">{}</div>'.format(value)
10+
mdl_textfield = mdl_textfield.replace('for="id_message"', 'for="mdl-textfield__label"')
11+
mdl_textfield = mdl_textfield.replace('<p>', '').replace('</p>', '')
12+
return mdl_textfield

post/tests.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from django.test import TestCase
2+
3+
# Create your tests here.

post/urls.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
from django.urls import path
2+
3+
from .views import IndexView, PostStreamView
4+
5+
app_name = 'post'
6+
7+
urlpatterns = [
8+
path('', IndexView.as_view(), name='index'),
9+
path('stream/', PostStreamView.as_view(), name='stream'),
10+
]

post/views.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
from django.shortcuts import render, get_object_or_404
2+
from django.views import View
3+
from .models import Post
4+
import time
5+
from django.http import StreamingHttpResponse, HttpResponseRedirect
6+
from django.urls import reverse
7+
import json
8+
from django.core.serializers.json import DjangoJSONEncoder
9+
10+
# Create your views here.
11+
from .forms import PostForm
12+
13+
class IndexView(View):
14+
form_class = PostForm
15+
initial = {}
16+
template_name = 'post/index.html'
17+
18+
def get(self, request, *args, **kwargs):
19+
form = self.form_class(initial=self.initial)
20+
posts = Post.objects.all().order_by('-id')
21+
return render(request, self.template_name, {'form': form, 'posts': posts})
22+
23+
def post(self, request, *args, **kwargs):
24+
form = self.form_class(request.POST)
25+
if form.is_valid():
26+
frm = form.save(commit=False)
27+
frm.user_id = request.user.id
28+
frm.save()
29+
return HttpResponseRedirect(reverse('post:index'))
30+
31+
return render(request, self.template_name, {'form': form})
32+
33+
34+
def event_stream():
35+
36+
initial_data = ""
37+
while True:
38+
data = json.dumps(list(Post.objects.order_by("-id").values("message",
39+
"date_created", "user__username")),
40+
cls=DjangoJSONEncoder
41+
)
42+
43+
if not initial_data == data:
44+
yield "\ndata: {}\n\n".format(data)
45+
initial_data = data
46+
time.sleep(1)
47+
48+
49+
50+
class PostStreamView(View):
51+
52+
def get(self, request):
53+
response = StreamingHttpResponse(event_stream())
54+
response['Content-Type'] = 'text/event-stream'
55+
return response

streamtutorial/__init__.py

Whitespace-only changes.
149 Bytes
Binary file not shown.

streamtutorial/__pycache__/abc-2020-07-11.pdf

Whitespace-only changes.
Binary file not shown.
1004 Bytes
Binary file not shown.
566 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)