#ARC-11 Fixes: section 1

remotes/origin/PR-39
ArturBaybulatov 10 years ago
parent d912bfcb8f
commit 5cd05de357
  1. 4
      api/urls.py
  2. 55
      api/views.py
  3. 51
      archilance/management/commands/generate_work_sells.py
  4. 7
      archilance/settings/base.py
  5. 6
      archilance/util.py
  6. 1
      projects/filters.py
  7. 2
      projects/models.py
  8. 6
      projects/serializers.py
  9. 7
      users/serializers.py
  10. 106
      users/templates/contractor_office.html
  11. 33
      work_sell/filters.py
  12. 8
      work_sell/models.py
  13. 52
      work_sell/serializers.py

@ -18,6 +18,8 @@ from .views import (
StageViewSet,
TeamViewSet,
UserViewSet,
WorkSellPhotoViewSet,
WorkSellViewSet,
)
@ -40,5 +42,7 @@ router.register(r'specializations', SpecializationViewSet)
router.register(r'stages', StageViewSet)
router.register(r'teams', TeamViewSet)
router.register(r'users', UserViewSet)
router.register(r'work-sell-photos', WorkSellPhotoViewSet)
router.register(r'work-sells', WorkSellViewSet)
urlpatterns = router.urls

@ -1,13 +1,20 @@
from django.conf import settings
from django.db.models import Q
from rest_framework.viewsets import ModelViewSet
from rest_framework import permissions
from rest_framework.pagination import PageNumberPagination
from rest_framework.viewsets import ModelViewSet
from projects.models import Project, Realty, Stage, Portfolio, PortfolioPhoto, Answer, AnswerFile, Order
from projects.serializers import (ProjectSerializer, RealtySerializer, StageSerializer,
PortfolioSerializer, PortfolioPhotoSerializer, AnswerSerializer,
OrderSerializer, AnswerFileSerializer,)
from projects.filters import (ProjectFilterSet, RealtyFilterSet, StageFilterSet, PortfolioFilterSet,
OrderFilterSet, PortfolioPhotoFilterSet,)
from projects.serializers import (
ProjectSerializer, RealtySerializer, StageSerializer, PortfolioSerializer,
PortfolioPhotoSerializer, AnswerSerializer, OrderSerializer, AnswerFileSerializer,
)
from projects.filters import (
ProjectFilterSet, RealtyFilterSet, StageFilterSet, PortfolioFilterSet, OrderFilterSet,
PortfolioPhotoFilterSet,
)
from specializations.models import Specialization
from specializations.serializers import SpecializationSerializer
@ -29,6 +36,10 @@ from reviews.models import Review
from reviews.serializers import ReviewSerializer
from reviews.filters import ReviewFilterSet
from work_sell.models import WorkSell, WorkSellPhoto
from work_sell.serializers import WorkSellSerializer, WorkSellPhotoSerializer
from work_sell.filters import WorkSellFilterSet, WorkSellPhotoFilterSet
class ContractorResumeFilesViewSet(ModelViewSet):
queryset = ContractorResumeFiles.objects.all()
@ -142,10 +153,19 @@ class LocationViewSet(ModelViewSet):
filter_class = LocationFilterSet
class PortfolioPagination(PageNumberPagination):
page_size = settings.API_PAGE_SIZE # Default page size
page_size_query_param = 'page_size' # Provide custom page size through a query param
max_page_size = 1000
class PortfolioViewSet(ModelViewSet):
queryset = Portfolio.objects.all()
serializer_class = PortfolioSerializer
filter_class = PortfolioFilterSet
pagination_class = PortfolioPagination
class PortfolioPhotoViewSet(ModelViewSet):
@ -154,6 +174,29 @@ class PortfolioPhotoViewSet(ModelViewSet):
filter_class = PortfolioPhotoFilterSet
class WorkSellPagination(PageNumberPagination):
page_size = settings.API_PAGE_SIZE # Default page size
page_size_query_param = 'page_size' # Provide custom page size through a query param
max_page_size = 1000
class WorkSellViewSet(ModelViewSet):
queryset = WorkSell.objects.all()
serializer_class = WorkSellSerializer
filter_class = WorkSellFilterSet
pagination_class = WorkSellPagination
class WorkSellPhotoViewSet(ModelViewSet):
queryset = WorkSellPhoto.objects.all()
serializer_class = WorkSellPhotoSerializer
filter_class = WorkSellPhotoFilterSet
class AnswerViewSet(ModelViewSet):
queryset = Answer.objects.all()
serializer_class = AnswerSerializer

@ -0,0 +1,51 @@
from django.contrib.auth.models import Group, Permission
from django.contrib.contenttypes.models import ContentType
from django.core.management import BaseCommand
from django.utils import timezone
import pydash as _; _.map = _.map_; _.filter = _.filter_
import random
from archilance import util
from common.models import Location
from projects.models import TERMS, CURRENCIES, BuildingClassfication, ConstructionType
from specializations.models import Specialization
from users.models import User
from work_sell.models import WorkSell, WorkSellPhoto
class Command(BaseCommand):
def handle(self, *args, **options):
print('---------------------------------------')
print('Generating work sells...')
print('---------------------------------------')
def create_work_sell(i):
ws = WorkSell(
budget=util.random_amount(),
created=util.random_date(),
currency=_.sample(CURRENCIES)[0],
description=util.lorem(),
name=util.lorem(words=_.random(2, 20), sentences=1),
term=_.random(0, 20),
term_type=_.sample(TERMS)[0],
)
ws.save()
ws.user = User.contractor_objects.order_by('?').first()
ws.building_classification = BuildingClassfication.objects.order_by('?').first()
ws.construction_type = ConstructionType.objects.order_by('?').first()
ws.location = Location.objects.root_nodes()[0].get_descendants().order_by('?').first()
ws.specialization = Specialization.objects.root_nodes()[0].get_descendants().order_by('?').first()
pic_names = _.split('a.png b.png c.jpg d.png e.jpg f.png g.png h.jpg i.png j.png k.jpg l.png m.png n.png o.png p.png q.jpg', ' ')
_.times(
lambda i_: ws.photos.create(img='_sample_files/%s' % util.take_one_random(pic_names)),
_.random(1, 15),
)
ws.save()
return ws
_.times(create_work_sell, 1000)

@ -256,6 +256,9 @@ LOGIN_URL = '/users/login/'
if DEBUG:
EMAIL_BACKEND = 'django.core.mail.backends.dummy.EmailBackend'
PAGE_SIZE = 10 # Non-api page size (regular views)
API_PAGE_SIZE = 100 # Django REST framework
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.BasicAuthentication',
@ -267,7 +270,7 @@ REST_FRAMEWORK = {
# 'rest_framework.permissions.DjangoModelPermissions',
],
'PAGE_SIZE': 100,
'PAGE_SIZE': API_PAGE_SIZE,
'DEFAULT_FILTER_BACKENDS': ('rest_framework_filters.backends.DjangoFilterBackend',), # djangorestframework-filters
}
@ -293,8 +296,6 @@ SHELL_PLUS_POST_IMPORTS = ( # Extra auto imports
('pprint', ('pprint', 'pformat')),
)
PAGE_SIZE = 10 # Pagination
YANDEX_MONEY = {'shop_password': 'x1uvmS9Iq8WBE3Oo'}

@ -82,8 +82,8 @@ def model_fields(model, width=200):
) for f in fields], width=width)
def lorem(sentences=5):
words = _.split((
def lorem(words=None, sentences=5):
vocab = _.split((
'a ac adipiscing amet ante arcu at auctor augue bibendum commodo condimentum consectetur consequat convallis curabitur'
'cursus diam dictum dignissim dolor donec duis efficitur eget eleifend elit enim erat et eu ex facilisis faucibus feugiat'
'finibus gravida iaculis id imperdiet in integer ipsum lacinia lacus laoreet lectus leo libero ligula lobortis lorem'
@ -93,7 +93,7 @@ def lorem(sentences=5):
'vitae viverra volutpat vulputate'
), ' ')
return _.join(_.times(lambda i_: _.capitalize(_.join(_.sample(words, _.random(5, 30)), ' ')), sentences), '. ')
return _.join(_.times(lambda i_: _.capitalize(_.join(_.sample(vocab, words or _.random(5, 30)), ' ')), sentences), '. ')
def decap(s):

@ -103,6 +103,7 @@ class PortfolioFilterSet(FilterSet):
term_type = AllLookupsFilter()
photos = RelatedFilter('projects.filters.PortfolioPhotoFilterSet')
user = RelatedFilter('users.filters.UserFilterSet')
class Meta:
model = Portfolio

@ -288,7 +288,7 @@ class Portfolio(models.Model):
budget = models.DecimalField(max_digits=10, decimal_places=0, default=0, null=True, blank=True)
building_classification = models.ForeignKey(BuildingClassfication, related_name='portfolios', null=True, blank=True)
construction_type = models.ForeignKey(ConstructionType, related_name='portfolios', null=True, blank=True)
created = models.DateTimeField(default=timezone.now, auto_now_add=True, auto_created=True)
created = models.DateTimeField(auto_now_add=True, auto_created=True)
currency = models.CharField(max_length=20, default='rur', choices=CURRENCIES, null=True, blank=True)
description = models.TextField()
location = TreeForeignKey('common.Location', related_name='portfolios', null=True, blank=True)

@ -1,5 +1,5 @@
from generic_relations.relations import GenericRelatedField
from rest_framework.serializers import ModelSerializer, ImageField, FileField, SerializerMethodField, PrimaryKeyRelatedField
from rest_framework.serializers import ModelSerializer, ImageField, FileField, SerializerMethodField, PrimaryKeyRelatedField, ReadOnlyField
from .models import Project, Realty, BuildingClassfication, ConstructionType, Order, Stage, Portfolio, PortfolioPhoto, Answer, AnswerFile
from common.serializers import LocationSerializer
@ -7,7 +7,6 @@ from specializations.serializers import SpecializationSerializer
from users.models import User, Team
from users.serializers import UserSerializer, TeamSerializer
class BuildingClassficationSerializer(ModelSerializer):
class Meta:
model = BuildingClassfication
@ -47,7 +46,6 @@ class RealtySerializer(ModelSerializer):
)
class StageSerializer(ModelSerializer):
# order = OrderSerializer()
@ -101,7 +99,6 @@ class OrderSerializer(ModelSerializer):
)
class ProjectSerializer(ModelSerializer):
customer = UserSerializer()
specialization = SpecializationSerializer()
@ -149,6 +146,7 @@ class PortfolioSerializer(ModelSerializer):
# answers = AnswerSerializer(many=True)
building_classification = BuildingClassficationSerializer()
construction_type = ConstructionTypeSerializer()
id = ReadOnlyField()
location = LocationSerializer()
photos = PortfolioPhotoSerializer(many=True)
specialization = SpecializationSerializer()

@ -1,4 +1,4 @@
from rest_framework.serializers import ModelSerializer, ImageField, FileField, SerializerMethodField
from rest_framework.serializers import ModelSerializer, ImageField, FileField, SerializerMethodField, ReadOnlyField
from .models import User, Team, ContractorResumeFiles, ContractorResume
from projects.models import Project
@ -34,6 +34,7 @@ class ContractorResumeFilesSerializer(ModelSerializer):
class UserSerializer(ModelSerializer):
_type = SerializerMethodField() # Distinguish when used with generic serializers
id = ReadOnlyField()
class Meta:
model = User
@ -81,18 +82,18 @@ class UserSerializer(ModelSerializer):
class TeamSerializer(ModelSerializer):
_type = SerializerMethodField() # Distinguish when used with generic serializers
# answers = AnswerSerializer(many=True)
avatar = ImageField()
contractors = UserSerializer(many=True)
owner = UserSerializer()
specializations = SpecializationSerializer(many=True)
# answers = AnswerSerializer(many=True)
class Meta:
model = Team
fields = (
'_type',
'answers',
# 'answers',
'avatar',
'contractors',
'created',

@ -159,61 +159,55 @@
<div class="tab-content">
<div id="tab11" class="tab-pane fade in active">
<div class="galleryWork2 disTab col-lg-9">
{% for p in portfolios %}
<div class="galleryWork2 disTab col-lg-9 -portfolios-container">
<script type="text/template" class="-portfolio-item-templ">
<div class="col-lg-4">
<div class="insetCol box-sizing disTab">
<div class="imgGal" style="background:rgba(0, 0, 0, 0) url('{{ p.photos.first.img.url }}') no-repeat scroll center center / cover ;">
<div class="imgGal" style="background:rgba(0, 0, 0, 0) url('<%= portfolio.photos[0].img %>') no-repeat scroll center center / cover">
<div class="imgFigure"></div>
</div>
</div>
<div class="insetCol2 box-sizing disTab text-center">
<a href="{% url 'projects:contractor-portfolio-detail' p.pk %}">{{ p.name }}</a>
<a href="#"><%= portfolio.name %></a>
</div>
</div>
{% empty %}
<div class="col-lg-12">
<p style="text-align: center;margin-top: 25px;">Работ в портфолио пока нет</p>
</div>
{% endfor %}
</script>
</div>
<div class="col-lg-9 col-lg-offset-3">
<div class="col-lg-9 col-lg-offset-3 -more-portfolios-btn">
<div class="linkElse">
<a href="javascript:void(0)" class="showElse">показать еще</a>
<a href="#" onclick="loadMorePortfolios(); return false" class="showElse">показать еще</a>
</div>
</div>
</div>
<div id="tab12" class="tab-pane fade">
<div class="galleryWork2 disTab">
{% for ws in work_sells %}
<div class="galleryWork2 disTab -work-sells-container">
<script type="text/template" class="-work-sell-item-templ">
<div class="col-lg-4">
<div class="insetCol box-sizing disTab">
<div class="imgGal" style="background:rgba(0, 0, 0, 0) url('{{ ws.photos.first.img.url }}') no-repeat scroll center center / cover ;">
<div class="imgGal" style="background:rgba(0, 0, 0, 0) url('<%= workSell.photos[0].img %>') no-repeat scroll center center / cover ;">
<div class="imgFigure"></div>
</div>
<div class="cenaImg box-sizing">
<div class="cenaImgInset">
{{ ws.budget }} <i class="fa fa-rub"></i>
{ { ws.budget } } <i class="fa fa-rub"></i>
</div>
</div>
</div>
<div class="insetCol2 box-sizing disTab">
<a href="{% url 'work_sell:detail' ws.pk %}">{{ ws.name }}</a>
{# <a href="{% url 'work_sell:detail' ws.pk %}"><%= workSell.name %></a>#}
<a href="#"><%= workSell.name %></a>
</div>
</div>
{% empty %}
<div class="col-lg-12">
<p style="text-align: center;margin-top: 25px;">Готовых работ пока нет</p>
</div>
{% endfor %}
</script>
</div>
<div class="col-lg-9 col-lg-offset-3">
<div class="col-lg-9 col-lg-offset-3 -more-work-sells-btn">
<div class="linkElse">
<a href="javascript:void(0)" class="showElse">показать еще</a>
<a href="#" onclick="loadMoreWorkSells(); return false" class="showElse">показать еще</a>
</div>
</div>
</div>
@ -254,3 +248,69 @@
</div>
</div>
{% endblock %}
{% block js_block %}
<script>
(function() {
var $portfoliosContainer = $('.-portfolios-container').first()
var portfolioItemTempl = _.template($portfoliosContainer.find('.-portfolio-item-templ').first().html())
var $morePortfBtn = $('.-more-portfolios-btn').first()
var $workSellsContainer = $('.-work-sells-container').first()
var workSellItemTempl = _.template($workSellsContainer.find('.-work-sell-item-templ').first().html())
var $moreWorkSellsfBtn = $('.-more-work-sells-btn').first()
var teamId = {{ contractor.team.pk }}
var contractorIds
var portfUrl = new URI('/api/portfolios/')
var workSellUrl = new URI('/api/work-sells/')
var pageSize = 3
$.get('/api/teams/' + teamId + '/').then(function(res) {
contractorIds = _.map(function(contractor) {
return contractor.id
}, res.contractors)
})
.then(loadMorePortfolios)
.then(loadMoreWorkSells)
function loadMorePortfolios() {
var query = portfUrl.query(true)
portfUrl.setQuery('user__id__in', _.join(',', contractorIds))
portfUrl.setQuery('page_size', pageSize)
portfUrl.setQuery('page', query.page ? Number(query.page) + 1 : 2)
$.get(portfUrl.href()).then(function(res) {
_.each(function(portfolio) {
$portfoliosContainer.append(portfolioItemTempl({portfolio: portfolio}))
}, res.results)
if (!res.next)
$morePortfBtn.css('display', 'none')
})
}
function loadMoreWorkSells() {
var query = workSellUrl.query(true)
workSellUrl.setQuery('contractor__in', _.join(',', contractorIds))
workSellUrl.setQuery('page_size', pageSize)
workSellUrl.setQuery('page', query.page ? Number(query.page) + 1 : 2)
$.get(workSellUrl.href()).then(function(res) {
_.each(function(ws) {
$workSellsContainer.append(workSellItemTempl({workSell: ws}))
}, res.results)
if (!res.next)
$moreWorkSellsfBtn.css('display', 'none')
})
}
window.loadMorePortfolios = loadMorePortfolios
window.loadMoreWorkSells = loadMoreWorkSells
}())
</script>
{% endblock %}

@ -1,6 +1,8 @@
import django_filters
from rest_framework_filters import FilterSet, RelatedFilter, AllLookupsFilter
from work_sell.models import WorkSell, WorkSellPhoto
from work_sell.models import WorkSell
class WorkSellFilter(django_filters.FilterSet):
budget = django_filters.NumberFilter()
@ -10,3 +12,32 @@ class WorkSellFilter(django_filters.FilterSet):
class Meta:
model = WorkSell
class WorkSellPhotoFilterSet(FilterSet):
id = AllLookupsFilter()
work_sell = RelatedFilter('work_sell.filters.WorkSellFilterSet')
# img = ???
class Meta:
model = WorkSellPhoto
class WorkSellFilterSet(FilterSet):
budget = AllLookupsFilter()
created = AllLookupsFilter()
currency = AllLookupsFilter()
description = AllLookupsFilter()
id = AllLookupsFilter()
name = AllLookupsFilter()
term = AllLookupsFilter()
term_type = AllLookupsFilter()
building_classification = RelatedFilter('projects.filters.BuildingClassficationFilterSet')
construction_type = RelatedFilter('projects.filters.ConstructionTypeFilterSet')
contractor = RelatedFilter('users.filters.UserFilterSet')
location = RelatedFilter('common.filters.LocationFilterSet')
photos = RelatedFilter('work_sell.filters.WorkSellPhotoFilterSet')
specialization = RelatedFilter('specializations.filters.SpecializationFilterSet')
class Meta:
model = WorkSell

@ -1,9 +1,7 @@
from mptt.models import TreeForeignKey
from sorl.thumbnail import ImageField
from django.db import models
from django.utils import timezone
from mptt.models import TreeForeignKey
from sorl.thumbnail import ImageField
from users.models import User, Team
from projects.models import BuildingClassfication, ConstructionType, TERMS, CURRENCIES
@ -17,7 +15,7 @@ class WorkSell(models.Model):
building_classification = models.ForeignKey(BuildingClassfication, related_name='worksells', null=True, blank=True)
construction_type = models.ForeignKey(ConstructionType, related_name='worksells', null=True, blank=True)
contractor = models.ForeignKey(User, related_name='work_sell', null=True, blank=True) # TODO: Pluralize related name
created = models.DateTimeField(default=timezone.now, auto_now_add=True)
created = models.DateTimeField(auto_now_add=True)
currency = models.CharField(max_length=20, default='rur', choices=CURRENCIES, null=True, blank=True)
description = models.TextField(blank=True)
location = TreeForeignKey('common.Location', related_name='worksells', null=True, blank=True)

@ -0,0 +1,52 @@
from generic_relations.relations import GenericRelatedField
from rest_framework.serializers import ModelSerializer, ImageField, FileField, SerializerMethodField, PrimaryKeyRelatedField, ReadOnlyField
from .models import WorkSell, WorkSellPhoto
from common.serializers import LocationSerializer
from projects.serializers import BuildingClassficationSerializer, ConstructionTypeSerializer
from specializations.serializers import SpecializationSerializer
from users.serializers import UserSerializer
class WorkSellPhotoSerializer(ModelSerializer):
img = ImageField()
worksell_id = PrimaryKeyRelatedField(read_only=True, source='worksell')
class Meta:
model = WorkSellPhoto
fields = (
'id',
'img',
'worksell_id',
)
class WorkSellSerializer(ModelSerializer):
building_classification = BuildingClassficationSerializer()
construction_type = ConstructionTypeSerializer()
contractor = UserSerializer()
id = ReadOnlyField()
location = LocationSerializer()
photos = WorkSellPhotoSerializer(many=True)
specialization = SpecializationSerializer()
class Meta:
model = WorkSell
fields = (
'budget',
'building_classification',
'construction_type',
'contractor',
'created',
'currency',
'description',
'id',
'location',
'name',
'photos',
'specialization',
'term',
'term_type',
)
Loading…
Cancel
Save