remotes/origin/PR-39
ArturBaybulatov 10 years ago
parent a06c96b4a2
commit c19cf5b61f
  1. 34
      api/urls.py
  2. 38
      api/views.py
  3. 3
      archilance/settings/base.py
  4. 15
      assets/index.js
  5. 25
      projects/filters.py
  6. 20
      projects/migrations/0005_auto_20160812_1956.py
  7. 2
      projects/models.py
  8. 99
      projects/serializers.py
  9. 263
      projects/templates/project_detail.html
  10. 1
      requirements/base.txt
  11. 86
      users/serializers.py

@ -1,34 +1,42 @@
from rest_framework import routers
from .views import (
AnswerViewSet,
ContractorResumeFilesViewSet,
ContractorResumeViewSet,
DocumentViewSet,
LocationViewSet,
MessageViewSet,
NoteViewSet,
PortfolioPhotoViewSet,
PortfolioViewSet,
ProjectViewSet,
RealtyViewSet,
ReviewViewSet,
SpecializationViewSet,
UserViewSet,
MessageViewSet,
StageViewSet,
NoteViewSet,
DocumentViewSet,
ReviewViewSet,
ContractorResumeViewSet,
ContractorResumeFilesViewSet,
TeamViewSet,
UserViewSet,
)
router = routers.DefaultRouter()
router.register(r'locations', LocationViewSet)
router.register(r'projects', ProjectViewSet)
router.register(r'stages', StageViewSet)
router.register(r'reviews', ReviewViewSet)
router.register(r'answers', AnswerViewSet)
router.register(r'contractorresume', ContractorResumeViewSet)
router.register(r'contractorresumefiles', ContractorResumeFilesViewSet)
router.register(r'documents', DocumentViewSet)
router.register(r'locations', LocationViewSet)
router.register(r'message', MessageViewSet)
router.register(r'note', NoteViewSet)
router.register(r'portfolio-photos', PortfolioPhotoViewSet)
router.register(r'portfolios', PortfolioViewSet)
router.register(r'projects', ProjectViewSet)
router.register(r'realties', RealtyViewSet)
router.register(r'reviews', ReviewViewSet)
router.register(r'specializations', SpecializationViewSet)
router.register(r'stages', StageViewSet)
router.register(r'teams', TeamViewSet)
router.register(r'users', UserViewSet)
router.register(r'message', MessageViewSet)
router.register(r'note', NoteViewSet)
urlpatterns = router.urls

@ -2,16 +2,16 @@ from django.db.models import Q
from rest_framework.viewsets import ModelViewSet
from rest_framework import permissions
from projects.models import Project, Realty, Stage
from projects.serializers import ProjectSerializer, RealtySerializer, StageSerializer
from projects.filters import ProjectFilterSet, RealtyFilterSet, StageFilterSet
from projects.models import Project, Realty, Stage, Portfolio, PortfolioPhoto, Answer, AnswerFile
from projects.serializers import ProjectSerializer, RealtySerializer, StageSerializer, PortfolioSerializer, PortfolioPhotoSerializer, AnswerSerializer, AnswerFileSerializer
from projects.filters import ProjectFilterSet, RealtyFilterSet, StageFilterSet, PortfolioFilterSet, PortfolioPhotoFilterSet
from specializations.models import Specialization
from specializations.serializers import SpecializationSerializer
from specializations.filters import SpecializationFilterSet
from users.models import User, ContractorResumeFiles, ContractorResume
from users.serializers import UserSerializer, ContractorResumeFilesSerializer, ContractorResumeSerializer
from users.models import User, ContractorResumeFiles, ContractorResume, Team
from users.serializers import UserSerializer, ContractorResumeFilesSerializer, ContractorResumeSerializer, TeamSerializer
from users.filters import UserFilterSet, ContractorResumeFilesFilterSet, ContractorResumeFilterSet
from common.models import Location
@ -101,7 +101,7 @@ class SpecializationViewSet(ModelViewSet):
try: # TODO: dirty
queryset = Specialization.objects.root_nodes()[0].get_descendants()
except:
queryset = Specialization.objects
queryset = Specialization.objects.all()
serializer_class = SpecializationSerializer
filter_class = SpecializationFilterSet
@ -116,6 +116,30 @@ class LocationViewSet(ModelViewSet):
try: # TODO: dirty
queryset = Location.objects.root_nodes()[0].get_descendants()
except:
queryset = Location.objects
queryset = Location.objects.all()
serializer_class = LocationSerializer
filter_class = LocationFilterSet
class PortfolioViewSet(ModelViewSet):
queryset = Portfolio.objects.all()
serializer_class = PortfolioSerializer
filter_class = PortfolioFilterSet
class PortfolioPhotoViewSet(ModelViewSet):
queryset = PortfolioPhoto.objects.all()
serializer_class = PortfolioPhotoSerializer
filter_class = PortfolioPhotoFilterSet
class AnswerViewSet(ModelViewSet):
queryset = Answer.objects.all()
serializer_class = AnswerSerializer
# filter_class = AnswerFilterSet
class TeamViewSet(ModelViewSet):
queryset = Team.objects.all()
serializer_class = TeamSerializer
# filter_class = TeamFilterSet

@ -12,7 +12,7 @@ SECRET_KEY = 'vb6@b9zj7^f!^+x*e8=e!oundyu1!e*&0i(3gu2xwo4%fx4h&n'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
TEMPLATE_DEBUG = True # Show debug info in templates. See `projects/templates/project_filter.html`
# TEMPLATE_DEBUG = True # Show debug info in templates. See `projects/templates/project_filter.html`
ALLOWED_HOSTS = []
@ -39,6 +39,7 @@ THIRD_PARTY_APPS = [
'compressor',
'password_reset',
'mathfilters', # Basic math operations in templates; https://pypi.python.org/pypi/django-mathfilters
'generic_relations', # https://github.com/Ian-Foote/rest-framework-generic-relations
]
LOCAL_APPS = [

@ -315,6 +315,21 @@ $fileUploadContainer.on('click', '.existing-file-remove-btn', function($evt) {
// Project answer portfolio selection ----------------------
//function ...() {
//
//}
// Helpers ---------------------------------------------

@ -1,6 +1,6 @@
from rest_framework_filters import FilterSet, RelatedFilter, AllLookupsFilter
from .models import Project, Stage, Order, Realty, BuildingClassfication, ConstructionType
from .models import Project, Stage, Order, Realty, BuildingClassfication, ConstructionType, Portfolio, PortfolioPhoto
class BuildingClassficationFilterSet(FilterSet):
@ -83,3 +83,26 @@ class RealtyFilterSet(FilterSet):
class Meta:
model = Realty
class PortfolioPhotoFilterSet(FilterSet):
id = AllLookupsFilter()
portfolio = RelatedFilter('projects.filters.PortfolioFilterSet')
# img = ???
class Meta:
model = PortfolioPhoto
class PortfolioFilterSet(FilterSet):
budget = AllLookupsFilter()
currency = AllLookupsFilter()
id = AllLookupsFilter()
name = AllLookupsFilter()
term = AllLookupsFilter()
term_type = AllLookupsFilter()
photos = RelatedFilter('projects.filters.PortfolioPhotoFilterSet')
class Meta:
model = Portfolio

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2016-08-12 16:56
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('projects', '0004_merge'),
]
operations = [
migrations.AlterField(
model_name='answer',
name='portfolios',
field=models.ManyToManyField(blank=True, related_name='answers', to='projects.Portfolio'),
),
]

@ -121,7 +121,7 @@ class Answer(models.Model):
budget = models.DecimalField(max_digits=10, decimal_places=0)
created = models.DateTimeField(default=timezone.now)
currency = models.CharField(max_length=5, choices=CURRENCIES, default='rur')
portfolios = models.ManyToManyField('Portfolio', related_name ='portfolios_answers', blank=True)
portfolios = models.ManyToManyField('Portfolio', related_name ='answers', blank=True)
project = models.ForeignKey(Project, related_name='answers')
secure_deal_only = models.BooleanField(default=False)
term = models.IntegerField(default=0)

@ -1,9 +1,11 @@
from rest_framework.serializers import ModelSerializer
from generic_relations.relations import GenericRelatedField
from rest_framework.serializers import ModelSerializer, ImageField, FileField, SerializerMethodField, PrimaryKeyRelatedField
from .models import Project, Realty, BuildingClassfication, ConstructionType, Order, Stage
from .models import Project, Realty, BuildingClassfication, ConstructionType, Order, Stage, Portfolio, PortfolioPhoto, Answer, AnswerFile
from common.serializers import LocationSerializer
from specializations.serializers import SpecializationSerializer
from users.serializers import UserSerializer
from users.models import User, Team
from users.serializers import UserSerializer, TeamSerializer
class BuildingClassficationSerializer(ModelSerializer):
@ -120,3 +122,94 @@ class ProjectSerializer(ModelSerializer):
'text',
'work_type',
)
class PortfolioPhotoSerializer(ModelSerializer):
img = ImageField()
portfolio_id = PrimaryKeyRelatedField(read_only=True, source='portfolio')
class Meta:
model = PortfolioPhoto
fields = (
'id',
'img',
'portfolio_id',
)
class PortfolioSerializer(ModelSerializer):
# answers = AnswerSerializer(many=True)
building_classification = BuildingClassficationSerializer()
construction_type = ConstructionTypeSerializer()
location = LocationSerializer()
photos = PortfolioPhotoSerializer(many=True)
specialization = SpecializationSerializer()
user = UserSerializer()
class Meta:
model = Portfolio
fields = (
# 'answers',
'budget',
'building_classification',
'construction_type',
'currency',
'description',
'id',
'location',
'name',
'photos',
'specialization',
'term',
'term_type',
'user',
'worksell',
)
class AnswerFileSerializer(ModelSerializer):
file = FileField()
class Meta:
model = AnswerFile
fields = (
'file',
'id',
'name',
# 'answer',
)
class AnswerSerializer(ModelSerializer):
files = AnswerFileSerializer(many=True)
portfolios = PortfolioSerializer(many=True)
project = ProjectSerializer
author = GenericRelatedField({
User: UserSerializer(),
Team: TeamSerializer()
})
class Meta:
model = Answer
fields = (
'budget',
'created',
'currency',
'id',
'secure_deal_only',
'term',
'term_type',
'text',
'files',
'portfolios',
'project',
'author', # Generic related field
# 'candidates',
)

@ -215,20 +215,18 @@
</li>
</ul>
{% if answer.author|class_name == 'User' %}
{% if answer.author.cro %}
<div class="sroUser sroExecutor">
<div class="iconSRO"></div>
<p>Есть допуск СРО</p>
</div>
{% endif %}
{% if answer.author|class_name == 'User' and answer.author.cro %}
<div class="sroUser sroExecutor">
<div class="iconSRO"></div>
<p>Есть допуск СРО</p>
</div>
{% elif answer.author|class_name == 'Team' %}
{# {% if any of these motherfuckers "answer.author.contractors.all" got a cro, then... %}#}
<div class="sroUser sroExecutor">
<div class="iconSRO"></div>
<p>Есть допуск СРО</p>
</div>
{# {% endif %}#}
<!-- TODO -->
<div class="sroUser sroExecutor">
<div class="iconSRO"></div>
<p>Есть допуск СРО</p>
</div>
{% endif %}
</div>
<div class="col-lg-2 listCens">
@ -238,9 +236,9 @@
<i class="fa fa-rub"></i>
</p>
<p>
Срок: <span>{{ answer.term }} {{ answer.get_term_type_display|decap }}</span>
Срок: <span>{{ answer.term }} {{ answer.get_currency_display }} {{ answer.get_term_type_display|decap }}</span>
</p>
<p>Опубликован: {{ answer.created }}</p>
<p>Опубликован: {{ answer.created|date:'M d, Y' }}</p>
</div>
<div class="col-lg-3 retts">
<a href="#" onclick="return false" class="candLink candLink3">
@ -359,6 +357,18 @@
<div class="col-lg-3"></div>
</div>
<div class="polsF1 disTab searchF1">
{% for x in 'abc' %}
<div class="col-lg-3">
<div class="insetCol box-sizing disTab">
<div class="imgGal" s--tyle="background: url('{{ portf.photos.first.img.url }}') no-repeat center">
<div class="imgFigure"></div>
</div>
</div>
</div>
{% endfor %}
</div>
<div class="polsF1 disTab searchF1">
<div class="col-lg-9">
<p>Портфолио <span style="color: red">{{ form.portfolios.errors.as_text }}</span></p>
@ -417,7 +427,7 @@
{% elif request.user.is_customer %}
{% elif request.user.is_customer and project.answers.exists %}
@ -448,9 +458,6 @@
</div>
</div>
<div class="col-lg-12 exNew">
<p>Новые исполнители</p>
</div>
@ -458,127 +465,137 @@
<div class="col-lg-12 exNew">
<p>Новые исполнители</p>
</div>
{% for answer in project.answers.all %}
<div class="candidateBlock disTab">
<div class="candidate">
<div class="col-lg-4">
<a href="#" class="aLinkExe">
<div class="imgExecutor">
{% if answer.author.avatar %}
<img src="{{ answer.author.avatar.url }}" alt="execitor-image">
{% else %}
<img src="{% static 'img/profile.jpg' %}" alt="execitor-image">
{% endif %}
</div>
</a>
{% for answer_p in project.answers.all %}
<div class="candidateBlock disTab">
<div class="candidate">
<div class="col-lg-4">
<a href="#" class="aLinkExe">
<div class="imgExecutor">
{% thumbnail answer_p.author.avatar "126x125" crop="center" as im %}
<img src="{{ im.url }}" alt="execitor-image">
{% endthumbnail %}
</div>
</a>
<p class="nameExecutor">
<a href="#">{{ answer_p.author.get_full_name }} [{{ answer_p.author.username }}]</a>
</p>
<p class="navv2">На сайте 8 лет и 3 месяца</p>
<div class="statusUser">Свободен</div>
</div>
<div class="col-lg-3 retts">
{% ratings_widget answer_p.author.pk 'restList2' %}
{% if answer_p.author.cro %}
<div class="sroUser sroExecutor">
<div class="iconSRO"></div>
<p>Есть допуск СРО</p>
<p class="nameExecutor">
{% if answer.author|class_name == 'User' %}
<a href="#">{{ answer.author.get_full_name }} [{{ answer.author.username }}]</a>
{% elif answer.author|class_name == 'Team' %}
<a href="#">{{ answer.author.name }}</a>
{% endif %}
</p>
<p class="navv2">На сайте {{ answer.author.created }}</p>
{% if answer.author|class_name == 'User' %}
{% if answer.author.contractor_status == 'free' %}
<div class="statusUser">Свободен</div><!-- ............. -->
{% endif %}
{% endif %}
</div>
{% endif %}
</div>
<div class="col-lg-2 listCens">
<p>Цена:
<span> {{ answer_p.budget }}</span>
<i class="fa fa-rub"></i>
</p>
<p>
Срок: <span>{{ answer_p.term }} of {{ answer_p.term_type }}</span>
</p>
<p>Опубликован: {{ answer_p.created | date:"M d, Y" }}</p>
</div>
<div class="col-lg-3 retts">
<a href="javascript:void(0)" class="candLink candLink1">
Кандидат
</a>
<a href="{% url 'chat:chat-user' %}" class="candLink candLink2">
предложить проект
</a>
<a href="javascript:void(0)" class="candLink candLink3">
отказ
</a>
</div>
<div class="gallMini disTab">
<div class="col-lg-3">
<div class="insetCol box-sizing disTab">
<div class="imgGal">
<div class="imgFigure"></div>
<div class="col-lg-3 retts">
{% ratings_widget answer.author.pk 'restList2' %}
{% if answer.author|class_name == 'User' and answer.author.cro %}
<div class="sroUser sroExecutor">
<div class="iconSRO"></div>
<p>Есть допуск СРО</p>
</div>
</div>
</div>
<div class="col-lg-3">
<div class="insetCol box-sizing disTab">
<div class="imgGal">
<div class="imgFigure"></div>
{% elif answer.author|class_name == 'Team' %}
<!-- TODO -->
<div class="sroUser sroExecutor">
<div class="iconSRO"></div>
<p>Есть допуск СРО</p>
</div>
</div>
{% endif %}
</div>
<div class="col-lg-3">
<div class="insetCol box-sizing disTab">
<div class="imgGal">
<div class="imgFigure"></div>
</div>
</div>
<div class="col-lg-2 listCens">
<p>
Цена:
<span>{{ answer.budget|intcomma }}</span>
<i class="fa fa-rub"></i>
</p>
<p>
Срок: <span>{{ answer.term }} {{ answer.get_currency_display }} {{ answer.get_term_type_display|decap }}</span>
</p>
<p>Опубликован: {{ answer.created|date:'M d, Y' }}</p>
</div>
<div class="col-lg-3">
<div class="insetCol box-sizing disTab">
<div class="imgGal">
<div class="imgFigure"></div>
<div class="col-lg-3 retts">
<a href="javascript:void(0)" class="candLink candLink1">
Кандидат
</a>
<a href="{% url 'chat:chat-user' %}" class="candLink candLink2">
предложить проект
</a>
<a href="javascript:void(0)" class="candLink candLink3">
отказ
</a>
</div>
<div class="gallMini disTab">
{% for portf in answer.portfolios.all %}
<div class="col-lg-3">
<div class="insetCol box-sizing disTab">
<div class="imgGal" style="background: url('{{ portf.photos.first.img.url }}') no-repeat center">
<div class="imgFigure"></div>
</div>
</div>
</div>
</div>
{% endfor %}
</div>
</div>
<div class="commBlock44 disTab">
<div class="comm44 disTab">
<div class="col-lg-10 col-lg-offset-1">
<p class="nameComm">
Иванов Петр Иванович
</p>
<span class="dateComm44">
13.01.2016 / 21:05
</span>
<div class="stars box-sizing">
<span class="glyphicon glyphicon-star starAct" aria-hidden="true"></span>
<span class="glyphicon glyphicon-star starAct" aria-hidden="true"></span>
<span class="glyphicon glyphicon-star starAct" aria-hidden="true"></span>
<span class="glyphicon glyphicon-star" aria-hidden="true"></span>
<span class="glyphicon glyphicon-star" aria-hidden="true"></span>
<div class="commBlock44 disTab">
<div class="comm44 disTab">
<div class="col-lg-10 col-lg-offset-1">
<p class="nameComm">
Иванов Петр Иванович
</p>
<span class="dateComm44">
13.01.2016 / 21:05
</span>
<div class="stars box-sizing">
<span class="glyphicon glyphicon-star starAct" aria-hidden="true"></span>
<span class="glyphicon glyphicon-star starAct" aria-hidden="true"></span>
<span class="glyphicon glyphicon-star starAct" aria-hidden="true"></span>
<span class="glyphicon glyphicon-star" aria-hidden="true"></span>
<span class="glyphicon glyphicon-star" aria-hidden="true"></span>
</div>
<p class="textComm44">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean euismod bibendum laoreet. Proin gravida dolor sit amet lacus accumsan et viverra justo commodo. Proin sodales pulvinar tempor. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nam fermentum, nulla luctus pharetra vulputate, felis tellus mollis orci, sed rhoncus sapien nunc eget odio.
</p>
</div>
<p class="textComm44">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean euismod bibendum laoreet. Proin gravida dolor sit amet lacus accumsan et viverra justo commodo. Proin sodales pulvinar tempor. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nam fermentum, nulla luctus pharetra vulputate, felis tellus mollis orci, sed rhoncus sapien nunc eget odio.
</p>
</div>
</div>
<div class="comm44 disTab">
<div class="col-lg-10 col-lg-offset-1">
<p class="nameComm nameCommAct">
Иванов Петр Иванович
</p>
<span class="dateComm44">
13.01.2016 / 21:05
</span>
<p class="textComm44">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean euismod bibendum laoreet. Proin gravida dolor sit amet lacus accumsan et viverra justo commodo. Proin sodales pulvinar tempor. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nam fermentum, nulla luctus pharetra vulputate, felis tellus mollis orci, sed rhoncus sapien nunc eget odio.
</p>
<a href="javascript:void(0)" class="answerComm">
Ответить
</a>
<div class="comm44 disTab">
<div class="col-lg-10 col-lg-offset-1">
<p class="nameComm nameCommAct">
Иванов Петр Иванович
</p>
<span class="dateComm44">
13.01.2016 / 21:05
</span>
<p class="textComm44">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean euismod bibendum laoreet. Proin gravida dolor sit amet lacus accumsan et viverra justo commodo. Proin sodales pulvinar tempor. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Nam fermentum, nulla luctus pharetra vulputate, felis tellus mollis orci, sed rhoncus sapien nunc eget odio.
</p>
<a href="javascript:void(0)" class="answerComm">
Ответить
</a>
</div>
</div>
</div>
</div>
</div>
</div>
{% endfor %}
{% endif %}

@ -39,3 +39,4 @@ tornado==4.3
natsort
django-mathfilters
gunicorn==19.6.0
rest-framework-generic-relations

@ -1,7 +1,9 @@
from rest_framework.serializers import ModelSerializer
from rest_framework.serializers import ModelSerializer, ImageField, FileField, SerializerMethodField
from .models import User, Team, ContractorResumeFiles, ContractorResume
from projects.models import Project
# from projects.serializers import AnswerSerializer
from specializations.serializers import SpecializationSerializer
class ContractorResumeSerializer(ModelSerializer):
@ -30,32 +32,22 @@ class ContractorResumeFilesSerializer(ModelSerializer):
)
class TeamSerializer(ModelSerializer):
class Meta:
model = Team
fields = (
'created',
'name',
'owner',
'specializations',
'users',
)
class UserSerializer(ModelSerializer):
_type = SerializerMethodField() # Distinguish when used with generic serializers
class Meta:
model = User
fields = (
'_type',
'avatar',
'financial_info',
'contractor_specializations',
'contractor_status',
'created',
'cro',
'date_of_birth',
'email',
'financial_info',
'first_name',
'gender',
'id',
@ -63,29 +55,55 @@ class UserSerializer(ModelSerializer):
'last_name',
'last_time_visit',
'location',
'username',
'patronym',
'skype',
'username',
'website',
)
# read_only_fields = (
# 'is_active',
# 'is_admin',
# )
# def create(self, validated_data):
# return User.objects.create(**validated_data)
# def update(self, inst, validated_data):
# inst.email = validated_data.get('email', inst.email)
# inst.first_name = validated_data.get('first_name', inst.first_name)
# inst.is_active = validated_data.get('is_active', inst.is_active)
# inst.last_name = validated_data.get('last_name', inst.last_name)
# # inst.projects = validated_data.get('projects', inst.projects)
#
# inst.save()
#
# return inst
def get__type(self, obj):
return 'User'
# def create(self, validated_data):
# return User.objects.create(**validated_data)
# def update(self, inst, validated_data):
# inst.email = validated_data.get('email', inst.email)
# inst.first_name = validated_data.get('first_name', inst.first_name)
# inst.is_active = validated_data.get('is_active', inst.is_active)
# inst.last_name = validated_data.get('last_name', inst.last_name)
# # inst.projects = validated_data.get('projects', inst.projects)
#
# inst.save()
#
# return inst
class TeamSerializer(ModelSerializer):
_type = SerializerMethodField() # Distinguish when used with generic serializers
avatar = ImageField()
contractors = UserSerializer(many=True)
owner = UserSerializer()
specializations = SpecializationSerializer(many=True)
# answers = AnswerSerializer(many=True)
class Meta:
model = Team
fields = (
'_type',
'answers',
'avatar',
'contractors',
'created',
'id',
'name',
'owner',
'specializations',
)
def get__type(self, obj):
return 'Team'
# import code; code.interact(local=dict(globals(), **locals()))

Loading…
Cancel
Save