From a89c5b3d2711912679be8bf270404c7f4e809fd4 Mon Sep 17 00:00:00 2001 From: Mukhtar Date: Mon, 4 Jul 2016 19:55:36 +0300 Subject: [PATCH] #ARC-8 Add models, views and templates, sorl-thumbnails --- archilance/settings/base.py | 1 + archilance/urls.py | 1 + assets/js/chat.js | 143 ++++++++ chat/admin.py | 9 +- chat/migrations/0005_notes.py | 26 ++ chat/migrations/0006_auto_20160704_1811.py | 46 +++ chat/models.py | 9 +- chat/serializers.py | 1 + chat/templates/chat_contractor.html | 107 +----- .../migrations/0037_auto_20160704_1444.py | 22 ++ projects/serializers.py | 15 +- users/filters.py | 14 +- work_sell/admin.py | 3 +- .../migrations/0005_auto_20160704_1449.py | 21 ++ work_sell/migrations/0006_worksellphoto.py | 29 ++ work_sell/models.py | 19 +- work_sell/templates/worksell_detail.html | 219 +++++++++++++ work_sell/templates/worksells_list.html | 310 ++++++++++++++++++ work_sell/urls.py | 13 + work_sell/views.py | 13 +- 20 files changed, 909 insertions(+), 112 deletions(-) create mode 100644 assets/js/chat.js create mode 100644 chat/migrations/0005_notes.py create mode 100644 chat/migrations/0006_auto_20160704_1811.py create mode 100644 projects/migrations/0037_auto_20160704_1444.py create mode 100644 work_sell/migrations/0005_auto_20160704_1449.py create mode 100644 work_sell/migrations/0006_worksellphoto.py create mode 100644 work_sell/templates/worksell_detail.html create mode 100644 work_sell/templates/worksells_list.html create mode 100644 work_sell/urls.py diff --git a/archilance/settings/base.py b/archilance/settings/base.py index c2e290d..5502678 100644 --- a/archilance/settings/base.py +++ b/archilance/settings/base.py @@ -34,6 +34,7 @@ THIRD_PARTY_APPS = [ 'mptt', 'registration', 'rest_framework', + 'sorl.thumbnail', ] LOCAL_APPS = [ diff --git a/archilance/urls.py b/archilance/urls.py index d08281c..1b11ed0 100644 --- a/archilance/urls.py +++ b/archilance/urls.py @@ -10,6 +10,7 @@ from .views import HomeTemplateView, TestChatTemplateView urlpatterns = [ url(r'^$', HomeTemplateView.as_view()), url(r'^chattest$', TestChatTemplateView.as_view()), + url(r'^work_sell/', include('work_sell.urls')), url(r'^test/$', TemplateView.as_view(template_name='test.html'), name='test'), url(r'^projects/', include('projects.urls')), url(r'^chat/', include('chat.urls')), diff --git a/assets/js/chat.js b/assets/js/chat.js new file mode 100644 index 0000000..eca3529 --- /dev/null +++ b/assets/js/chat.js @@ -0,0 +1,143 @@ +/** + * Created by mukhtar on 04.07.16. + */ + +function getCookie(name) { + var cookieValue = null; + if (document.cookie && document.cookie != '') { + var cookies = document.cookie.split(';'); + for (var i = 0; i < cookies.length; i++) { + var cookie = jQuery.trim(cookies[i]); + if (cookie.substring(0, name.length + 1) == (name + '=')) { + cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); + break; + } + } + } + return cookieValue; +} + +var SocketHandler = function () { + var url = 'ws://127.0.0.1:8888/chat'; + var sock = new WebSocket(url); + var intervalId; + sock.onopen = function () { + console.log("Start connect"); + intervalId = setInterval(function () { + sock.send('{"dummy": 1}'); + }, 150000); + }; + sock.onmessage = function (event) { + console.log(event.data); + alert(event.data); + var message = JSON.parse(event.data); + var inbox = document.getElementById('message-chat-space'); + inbox.innerHTML += '
' + + '

Иванов

13.0.2016
' + + '

' + message.msg + '

'; + + }; + + this.send_contact_message = function (userId) { + var data = { + "format_type": "add_message", + "user_id": userId + } + sock.send(JSON.stringify(data)); + console.log(data); + }; + + this.add_contact_message = function (messageData) { + console.log(messageData); + sock.send(JSON.stringify(messageData)); + }; + + this.send_message = function (form) { + var elements = form.elements; + var data = {}; + var i = 0; + for (var i; i < elements.length; i++) { + if (elements[i].name == 'message') { + data[elements[i].name] = elements[i].value; + } + } + sock.send(JSON.stringify(data)); + var textareaMessage = document.getElementById("message"); + textareaMessage.value = ""; + + } + +} + +$(function () { + var socket = new SocketHandler(); + var form = document.getElementById('message_form'); + var csrftoken = getCookie('csrftoken'); + + // Вытащить сообщения для чата заказа + $('.order-block').on('click', function () { + var orderId = $(this).attr('data-id'); + $("#chat-contractor-order #orderId").val(orderId); + var inbox = document.getElementById('message-chat-order-space'); + inbox.innerHTML = ''; + $.ajax({ + url: '/api/message', + type: 'GET', + data: {csrfmiddlewaretoken: csrftoken, 'order': orderId}, + dataType: 'json', + success: function (json) { + $.each(json.results, function (i, v) { + inbox.innerHTML += '
' + + '

Иванов

13.0.2016
' + + '

' + v.text + '

'; + }); + } + }); + + }); + + // Вытащить сообщения для конактов + $('.user-block').on('click', function () { + var userId = $(this).attr('data-id'); + $("#contact-chat-form #recipentId").val(userId); + var inbox = document.getElementById('message-chat-space'); + inbox.innerHTML = ''; + $.ajax({ + url: '/api/message', + type: 'GET', + data: {csrfmiddlewaretoken: csrftoken, 'recipent__id': userId}, + dataType: 'json', + success: function (json) { + $.each(json.results, function (i, v) { + inbox.innerHTML += '
' + + '

Иванов

13.0.2016
' + + '

' + v.text + '

'; + }); + } + }); + + }); + + // Добавить сообщение для контакта + $('#contact-chat-add-message').on('click', function () { + var chatMessage = $("#chat").val(); + var recipentId = $("#recipentId").val(); + var senderId = $("#senderId").val(); + + socket.add_contact_message({ + "format_type": "add_message_contact", + "data": { + "sender_id": senderId, + "recipent_id": recipentId, + "chat_message": chatMessage, + } + }); + + $("#chat").val(""); + }); + + +}); + + + diff --git a/chat/admin.py b/chat/admin.py index e064b6c..127440a 100644 --- a/chat/admin.py +++ b/chat/admin.py @@ -1,7 +1,14 @@ from django.contrib import admin -from .models import Message +from .models import Message, Notes + class MessageAdmin(admin.ModelAdmin): list_display = ('text', 'sender', 'recipent',) + +class NotesAdmin(admin.ModelAdmin): + list_display = ('text', 'sender', 'recipent', 'order',) + + admin.site.register(Message, MessageAdmin) +admin.site.register(Notes, NotesAdmin) diff --git a/chat/migrations/0005_notes.py b/chat/migrations/0005_notes.py new file mode 100644 index 0000000..fea1d07 --- /dev/null +++ b/chat/migrations/0005_notes.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.6 on 2016-07-04 11:44 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('chat', '0004_auto_20160630_1204'), + ] + + operations = [ + migrations.CreateModel( + name='Notes', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('text', models.TextField()), + ], + options={ + 'verbose_name_plural': 'Сообщения', + 'verbose_name': 'Сообщение', + }, + ), + ] diff --git a/chat/migrations/0006_auto_20160704_1811.py b/chat/migrations/0006_auto_20160704_1811.py new file mode 100644 index 0000000..6df4f18 --- /dev/null +++ b/chat/migrations/0006_auto_20160704_1811.py @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.6 on 2016-07-04 15:11 +from __future__ import unicode_literals + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone + + +class Migration(migrations.Migration): + + dependencies = [ + ('projects', '0037_auto_20160704_1444'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('chat', '0005_notes'), + ] + + operations = [ + migrations.AlterModelOptions( + name='notes', + options={'verbose_name': 'Заметка', 'verbose_name_plural': 'Заметки'}, + ), + migrations.AddField( + model_name='notes', + name='created', + field=models.DateTimeField(default=django.utils.timezone.now), + ), + migrations.AddField( + model_name='notes', + name='order', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='order_notes', to='projects.Order'), + ), + migrations.AddField( + model_name='notes', + name='recipent', + field=models.ForeignKey(default=None, on_delete=django.db.models.deletion.CASCADE, related_name='recipent_notes', to=settings.AUTH_USER_MODEL), + preserve_default=False, + ), + migrations.AddField( + model_name='notes', + name='sender', + field=models.ForeignKey(default=None, on_delete=django.db.models.deletion.CASCADE, related_name='sender_notes', to=settings.AUTH_USER_MODEL), + preserve_default=False, + ), + ] diff --git a/chat/models.py b/chat/models.py index 2b5d506..ec3c08f 100644 --- a/chat/models.py +++ b/chat/models.py @@ -22,11 +22,14 @@ class Message(models.Model): class Notes(models.Model): text = models.TextField() - + created = models.DateTimeField(default=timezone.now) + sender = models.ForeignKey(User, related_name='sender_notes') + recipent = models.ForeignKey(User, related_name='recipent_notes') + order = models.ForeignKey(Order, related_name='order_notes', null=True, blank=True) def __str__(self): return self.text class Meta: - verbose_name = 'Сообщение' - verbose_name_plural = 'Сообщения' + verbose_name = 'Заметка' + verbose_name_plural = 'Заметки' diff --git a/chat/serializers.py b/chat/serializers.py index 9cdf3c0..3d12789 100644 --- a/chat/serializers.py +++ b/chat/serializers.py @@ -13,6 +13,7 @@ class MessageSerializer(ModelSerializer): fields = ( 'text', 'created', + 'order', 'sender', 'recipent', 'private_type', diff --git a/chat/templates/chat_contractor.html b/chat/templates/chat_contractor.html index 9a1d1d7..f5aa956 100644 --- a/chat/templates/chat_contractor.html +++ b/chat/templates/chat_contractor.html @@ -124,16 +124,7 @@ 7мб
-
  • - Архитерурное 2.jpg - 7мб -
    -
  • -
  • - Архитерурное 2.jpg - 7мб -
    -
  • + Распечатать с помощью ресурса @@ -185,6 +176,7 @@
    +
    @@ -361,91 +360,5 @@ {% endblock %} {% block js_block %} - - + {% endblock %} diff --git a/projects/migrations/0037_auto_20160704_1444.py b/projects/migrations/0037_auto_20160704_1444.py new file mode 100644 index 0000000..32fefbe --- /dev/null +++ b/projects/migrations/0037_auto_20160704_1444.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.6 on 2016-07-04 11:44 +from __future__ import unicode_literals + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('projects', '0036_auto_20160630_1846'), + ] + + operations = [ + migrations.AlterField( + model_name='order', + name='contractor', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='orders', to=settings.AUTH_USER_MODEL), + ), + ] diff --git a/projects/serializers.py b/projects/serializers.py index 3c40c7c..f8fa4b8 100755 --- a/projects/serializers.py +++ b/projects/serializers.py @@ -1,6 +1,6 @@ from rest_framework.serializers import ModelSerializer -from .models import Project, Realty, BuildingClassfication, ConstructionType +from .models import Project, Realty, BuildingClassfication, ConstructionType, Order from common.serializers import LocationSerializer from specializations.serializers import SpecializationSerializer from users.serializers import UserSerializer @@ -45,6 +45,19 @@ class RealtySerializer(ModelSerializer): ) +class OrderSerializer(ModelSerializer): + class Meta: + model = Order + + fields = ( + 'contractor', + 'created', + 'project', + 'secure', + 'status', + ) + + class ProjectSerializer(ModelSerializer): customer = UserSerializer() specialization = SpecializationSerializer() diff --git a/users/filters.py b/users/filters.py index 12af244..82a0753 100755 --- a/users/filters.py +++ b/users/filters.py @@ -2,13 +2,13 @@ from rest_framework_filters import FilterSet, RelatedFilter, AllLookupsFilter from .models import User class UserFilterSet(FilterSet): - # id = AllLookupsFilter() - # email = AllLookupsFilter() - # first_name = AllLookupsFilter() - # is_active = AllLookupsFilter() - # is_admin = AllLookupsFilter() - # last_name = AllLookupsFilter() - # projects = RelatedFilter('projects.filters.ProjectFilterSet') + id = AllLookupsFilter() + email = AllLookupsFilter() + first_name = AllLookupsFilter() + is_active = AllLookupsFilter() + is_admin = AllLookupsFilter() + last_name = AllLookupsFilter() + projects = RelatedFilter('projects.filters.ProjectFilterSet') class Meta: model = User diff --git a/work_sell/admin.py b/work_sell/admin.py index 6eb2c2c..beb929c 100644 --- a/work_sell/admin.py +++ b/work_sell/admin.py @@ -1,4 +1,5 @@ from django.contrib import admin -from .models import WorkSell +from .models import WorkSell, WorkSellPhoto admin.site.register(WorkSell) +admin.site.register(WorkSellPhoto) diff --git a/work_sell/migrations/0005_auto_20160704_1449.py b/work_sell/migrations/0005_auto_20160704_1449.py new file mode 100644 index 0000000..7826eec --- /dev/null +++ b/work_sell/migrations/0005_auto_20160704_1449.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.6 on 2016-07-04 11:49 +from __future__ import unicode_literals + +from django.db import migrations +import sorl.thumbnail.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('work_sell', '0004_worksell_price'), + ] + + operations = [ + migrations.AlterField( + model_name='worksell', + name='img', + field=sorl.thumbnail.fields.ImageField(upload_to='worksell/worksell'), + ), + ] diff --git a/work_sell/migrations/0006_worksellphoto.py b/work_sell/migrations/0006_worksellphoto.py new file mode 100644 index 0000000..08d2f2c --- /dev/null +++ b/work_sell/migrations/0006_worksellphoto.py @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.6 on 2016-07-04 15:54 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion +import sorl.thumbnail.fields + + +class Migration(migrations.Migration): + + dependencies = [ + ('work_sell', '0005_auto_20160704_1449'), + ] + + operations = [ + migrations.CreateModel( + name='WorkSellPhoto', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('img', sorl.thumbnail.fields.ImageField(upload_to='worksell/worksell')), + ('worksell', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='photos', to='work_sell.WorkSell')), + ], + options={ + 'verbose_name': 'Изображение Готовая работа', + 'verbose_name_plural': 'Изображения Готовые работы', + }, + ), + ] diff --git a/work_sell/models.py b/work_sell/models.py index 77128ce..e614d3b 100644 --- a/work_sell/models.py +++ b/work_sell/models.py @@ -1,16 +1,33 @@ from django.db import models +from sorl.thumbnail import ImageField from users.models import User + class WorkSell(models.Model): name = models.CharField(max_length=255) description = models.TextField(blank=True) - img = models.ImageField(upload_to='worksell/worksell') + img = ImageField(upload_to='worksell/worksell') price = models.DecimalField(max_digits=10, decimal_places=0, default=0) contractor = models.ForeignKey(User, related_name='work_sell') def __str__(self): return self.name + def is_author_for_work(self): + pass + class Meta: verbose_name = 'Готовая работа' verbose_name_plural = 'Готовые работы' + + +class WorkSellPhoto(models.Model): + img = ImageField(upload_to='worksell/worksell') + worksell = models.ForeignKey(WorkSell, related_name='photos') + + def __str__(self): + return self.worksell.name + + class Meta: + verbose_name = 'Изображение Готовая работа' + verbose_name_plural = 'Изображения Готовые работы' diff --git a/work_sell/templates/worksell_detail.html b/work_sell/templates/worksell_detail.html new file mode 100644 index 0000000..a1e8818 --- /dev/null +++ b/work_sell/templates/worksell_detail.html @@ -0,0 +1,219 @@ +{% extends 'partials/base.html' %} +{% load staticfiles %} +{% load thumbnail %} +{% block content %} + + +
    +
    +
    +

    {{ object }}

    +
    +

    предыдущий

    +
    +
    +

    следующий

    +
    +
    + +
    +
    +

    Описание:

    +
    +
    +

    + {{ object.text }} +

    +
    +
    +
    +
    + + +
    +
    +
    +
    +
    +
    +
    +
    +

    Похожие работы

    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    + {% include 'partials/footer.html' %} + +
    +
    + +{% endblock %} +{% block js_block %} + + + {% endblock %} diff --git a/work_sell/templates/worksells_list.html b/work_sell/templates/worksells_list.html new file mode 100644 index 0000000..13db17a --- /dev/null +++ b/work_sell/templates/worksells_list.html @@ -0,0 +1,310 @@ +{% extends 'partials/base.html' %} +{% load staticfiles %} +{% load thumbnail %} +{% block content %} + + +
    +
    +
    +

    Работы на продажу

    +
    +
    +
    +
    +
    +
    Тип работ:
    +
    Специализации:
    +
    +
    +
    +
    +
    + +
    +
    + +
    +
    + +
    +
    + +
    +
    +
    +
    Тип работ:
    +
    Специализации:
    +
    +
    +
    + + + +
    +
    + +
    + + +
    +
    +
    +

    Расширенный поиск

    + +
    +
    +
    +
    +
    +
    +
    +
    Тип работ:
    +
    Специализации:
    +
    +
    Специализации:
    +
    +
    +
    + +
    +
    + +
    +
    + +
    +
    + +
    +
    +
    +
    +
    +
    + {% for work in object_list %} +
    + +
    +

    {{ work }}

    + + +
    +
    + +
    +
    + +
    +
    +
    +
    +
    +
    + {% thumbnail work.img "265x265" crop="center" as im %} +
    +
    +
    + {% endthumbnail %} +
    +
    + {{ work.price }} +
    +
    +
    +
    +

    {{ work }}

    + + +
    +
    + +
    +
    + +
    +
    +
    +
    +
    +
    + {% thumbnail work.img "265x265" crop="center" as im %} +
    +
    +
    + {% endthumbnail %} +
    +
    + {{ work.price }} +
    +
    +
    +
    +

    {{ work }}

    + + +
    +
    + +
    +
    + +
    +
    +
    +
    + {% endfor %} +
    +
    + +
    + {% include 'partials/footer.html' %} +
    +
    +{% endblock %} diff --git a/work_sell/urls.py b/work_sell/urls.py new file mode 100644 index 0000000..6db4aaf --- /dev/null +++ b/work_sell/urls.py @@ -0,0 +1,13 @@ +from django.conf import urls + +from .views import ( + WorkSellsView, + WorkSellDetail, +) + +app_name = 'work_sell' + +urlpatterns = [ + urls.url(r'^$', WorkSellsView.as_view(), name='list'), + urls.url(r'^(?P\d+)/$', WorkSellDetail.as_view(), name='detail'), +] diff --git a/work_sell/views.py b/work_sell/views.py index 91ea44a..4f33be4 100644 --- a/work_sell/views.py +++ b/work_sell/views.py @@ -1,3 +1,14 @@ from django.shortcuts import render +from django.views.generic import ListView, DetailView -# Create your views here. +from .models import WorkSell + + +class WorkSellsView(ListView): + model = WorkSell + template_name = 'worksells_list.html' + + +class WorkSellDetail(DetailView): + model = WorkSell + template_name = 'worksell_detail.html'