From c5c94ba6c96f2d931156b3ef18f8f6efc9621302 Mon Sep 17 00:00:00 2001 From: ArturBaybulatov Date: Tue, 26 Jul 2016 16:20:55 +0300 Subject: [PATCH 1/2] #ARC-11 --- .../commands/generate_portfolios.py | 2 +- .../management/commands/generate_projects.py | 2 +- .../management/commands/generate_reviews.py | 2 +- .../management/commands/generate_users.py | 3 +- archilance/settings/base.py | 2 +- archilance/util.py | 17 + common/utils.py | 9 - .../templates/customer_project_detail.html | 1 + projects/templates/project_detail.html | 1 + projects/templates/project_filter.html | 147 +++-- .../templatetags/specializtions_tags.py | 6 +- templates/partials/pagination.html | 54 +- users/forms.py | 23 +- users/templates/contractor_filter.html | 510 +++++++++--------- .../customer_profile_open_projects.html | 51 +- users/templates/customer_profile_reviews.html | 2 +- .../customer_profile_trashed_projects.html | 17 +- .../partials/customer_profile_info_block.html | 13 +- users/templatetags/user_tags.py | 1 + users/views.py | 115 +++- work_sell/templates/worksells_list.html | 109 ++-- 21 files changed, 596 insertions(+), 491 deletions(-) delete mode 100644 common/utils.py diff --git a/archilance/management/commands/generate_portfolios.py b/archilance/management/commands/generate_portfolios.py index c50b957..0cf8efa 100644 --- a/archilance/management/commands/generate_portfolios.py +++ b/archilance/management/commands/generate_portfolios.py @@ -38,7 +38,7 @@ class Command(BaseCommand): def create_portfolio(i): portf = Portfolio( name='Portforlio %s' % i, - description="Portforlio %s's description" % i, + description=util.lorem(_.random(5, 30)), budget=util.random_amount(), currency=_.sample(CURRENCIES)[0], term=_.random(0, 20), diff --git a/archilance/management/commands/generate_projects.py b/archilance/management/commands/generate_projects.py index 7ff5779..4ef30fe 100644 --- a/archilance/management/commands/generate_projects.py +++ b/archilance/management/commands/generate_projects.py @@ -63,7 +63,7 @@ class Command(BaseCommand): deal_type=_.sample(Project.DEAL_TYPES)[0], term=_.random(0, 20), term_type=_.sample(TERMS)[0], - text='Project %s text' % i, + text=util.lorem(_.random(5, 30)), work_type=_.sample(Project.WORK_TYPES)[0], state='active', ) diff --git a/archilance/management/commands/generate_reviews.py b/archilance/management/commands/generate_reviews.py index 649a162..d902b73 100644 --- a/archilance/management/commands/generate_reviews.py +++ b/archilance/management/commands/generate_reviews.py @@ -23,7 +23,7 @@ class Command(BaseCommand): review.project = Project.objects.order_by('?').first() review.stars = _.random(1, 5) - review.text = 'This is a review %s text' % i + review.text = util.lorem(_.random(5, 15)) review.is_secured = _.sample((True, False)) review.save() diff --git a/archilance/management/commands/generate_users.py b/archilance/management/commands/generate_users.py index e46aac1..72c81cb 100644 --- a/archilance/management/commands/generate_users.py +++ b/archilance/management/commands/generate_users.py @@ -79,7 +79,8 @@ class Command(BaseCommand): username = 'user-%s' % i return User.objects.create( - first_name='User-%s' % i, + first_name='Василий', + last_name='Пупкин', username=username, email='%s@example.com' % username, is_active=True, diff --git a/archilance/settings/base.py b/archilance/settings/base.py index 8b68b49..93ab74a 100644 --- a/archilance/settings/base.py +++ b/archilance/settings/base.py @@ -240,7 +240,7 @@ REST_FRAMEWORK = { 'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly', ], - 'PAGE_SIZE': 10, + 'PAGE_SIZE': 100, 'DEFAULT_FILTER_BACKENDS': ('rest_framework_filters.backends.DjangoFilterBackend',), # djangorestframework-filters } diff --git a/archilance/util.py b/archilance/util.py index c96141b..c2edc56 100644 --- a/archilance/util.py +++ b/archilance/util.py @@ -1,3 +1,4 @@ +from django.shortcuts import _get_queryset from django.utils import timezone from pprint import pprint, pformat import pydash as _; _.map = _.map_; _.filter = _.filter_ @@ -41,6 +42,22 @@ def random_amount(): return random.random() * random.choice((100, 1000, 10000)) +def get_or_none(klass, *args, **kwargs): + queryset = _get_queryset(klass) + + try: + return queryset.get(*args, **kwargs) + except queryset.model.DoesNotExist: + return None + + +def get_attr_or_none(klass, *args, attr=None, **kwargs): + object = get_or_none(klass, *args, **kwargs) + + if object and attr and isinstance(attr, str): + return getattr(object, attr, None) + + def model_fields(model, width=200): pprint([( f.name, diff --git a/common/utils.py b/common/utils.py deleted file mode 100644 index 4a75d6a..0000000 --- a/common/utils.py +++ /dev/null @@ -1,9 +0,0 @@ -from django.shortcuts import _get_queryset - -def get_or_none(klass, *args, **kwargs): - queryset = _get_queryset(klass) - - try: - return queryset.get(*args, **kwargs) - except queryset.model.DoesNotExist: - return None diff --git a/projects/templates/customer_project_detail.html b/projects/templates/customer_project_detail.html index 3906342..481dce8 100644 --- a/projects/templates/customer_project_detail.html +++ b/projects/templates/customer_project_detail.html @@ -201,6 +201,7 @@ {% endfor %} +
{% include 'partials/pagination.html' %}
diff --git a/projects/templates/project_detail.html b/projects/templates/project_detail.html index 695dfad..04f3f27 100644 --- a/projects/templates/project_detail.html +++ b/projects/templates/project_detail.html @@ -242,6 +242,7 @@ {% endfor %} +
{% include 'partials/pagination.html' %}
diff --git a/projects/templates/project_filter.html b/projects/templates/project_filter.html index f8231f2..2443d41 100644 --- a/projects/templates/project_filter.html +++ b/projects/templates/project_filter.html @@ -166,85 +166,78 @@ - - - - - - - -
- {% for proj in projects %} -
-
-

- {{ proj }} -

-
    -
  • - Объект "{{ proj.realty.name }}" -
  • -
  • - 0 ответ от имени группы -
  • -
-

{{ proj.text }}

- - {% if TEMPLATE_DEBUG %} -
{{ proj|inspect }}

Specialization: {{ proj.specialization }}

Realty location: {{ proj.realty.location }}

Constr. type: {{ proj.realty.construction_type }}

Build. classif.: {{ proj.realty.building_classification }}
+ + + + + +
+ {% for proj in projects %} +
+
+

+ {{ proj }} +

+
    +
  • + Объект "{{ proj.realty.name }}" +
  • +
  • + 0 ответ от имени группы +
  • +
+

{{ proj.text }}

+ + {% if TEMPLATE_DEBUG %} +
{{ proj|inspect }}

Specialization: {{ proj.specialization }}

Realty location: {{ proj.realty.location }}

Constr. type: {{ proj.realty.construction_type }}

Build. classif.: {{ proj.realty.building_classification }}
+ {% endif %} + +
    +
  • {{ proj.created }}
  • +
  • 0
  • +
  • {{ proj.answers.count }}
  • +
  • {{ proj.user }}
  • +
+
+
+

+ {{ proj.budget }} +

+
    + {% if proj.secure_deal %} +
  • Безопасная сделка
  • {% endif %} - -
      -
    • {{ proj.created }}
    • -
    • 0
    • -
    • {{ proj.answers.count }}
    • -
    • {{ proj.user }}
    • -
    -
-
-

- {{ proj.budget }} -

-
    - {% if proj.secure_deal %} -
  • Безопасная сделка
  • - {% endif %} - -
  • - Стадия: "П" -
  • - -
  • - Отказаться и переместить - в корзину -
  • -
-
+ +
  • + Стадия: "П" +
  • + +
  • + Отказаться и переместить + в корзину +
  • +
    - {% endfor %} -
    - - - - -
    - {% include 'partials/pagination.html' %} -
    - - - - - +
    + {% endfor %} +
    + + +
    + {% include 'partials/pagination.html' %} +
    + + {% include 'partials/footer.html' %}
    diff --git a/specializations/templatetags/specializtions_tags.py b/specializations/templatetags/specializtions_tags.py index 8e6579a..8f067c9 100644 --- a/specializations/templatetags/specializtions_tags.py +++ b/specializations/templatetags/specializtions_tags.py @@ -1,13 +1,15 @@ from django import template -from common.utils import get_or_none + +from archilance import util from users.models import User + register = template.Library() @register.inclusion_tag('templatetags/specializations_widget.html', takes_context=True) def specialization_widget(context, user_id): user_id = int(user_id) - user = get_or_none(User, pk=user_id) + user = util.get_or_none(User, pk=user_id) if user: specializations = user.contractor_specializations.all() else: diff --git a/templates/partials/pagination.html b/templates/partials/pagination.html index bf07867..db632a0 100644 --- a/templates/partials/pagination.html +++ b/templates/partials/pagination.html @@ -1,29 +1,51 @@ {% if is_paginated %} + + {% endif %} diff --git a/users/forms.py b/users/forms.py index cf3b0ec..0812d8f 100644 --- a/users/forms.py +++ b/users/forms.py @@ -1,10 +1,11 @@ from django import forms from django.forms import ModelForm import itertools +import pydash as _; _.map = _.map_; _.filter = _.filter_ from .models import User, ContractorFinancialInfo from common.models import Location -from projects.models import Project, BuildingClassfication, ConstructionType +from projects.models import Project, Realty, BuildingClassfication, ConstructionType from specializations.models import Specialization @@ -110,6 +111,26 @@ class ContractorFilterForm(forms.Form): super().__init__(*args, **kwargs) +class CustomerProfileProjectRealtyForm(forms.Form): + def __init__(self, *args, **kwargs): + self.request = kwargs.pop('request') + self.customer = kwargs.pop('customer') + + super().__init__(*args, **kwargs) + + realties = _.uniq(tuple(p.realty for p in self.customer.projects.all())) + + self.fields['realty'] = forms.ChoiceField( + widget=forms.Select(attrs={ + 'class': 'selectpicker', + 'onchange': "$(this).closest('form').submit()", + }), + + choices=(('', 'Все объекты'),) + tuple((r.pk, r.name) for r in realties), + required=False, + ) + + class ContractorFinancicalInfoForm(ModelForm): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) diff --git a/users/templates/contractor_filter.html b/users/templates/contractor_filter.html index 0eded61..9ec79b4 100644 --- a/users/templates/contractor_filter.html +++ b/users/templates/contractor_filter.html @@ -163,281 +163,281 @@ - - - - {% for obj in coll %} - {% if obj|class_name == 'Team' %} - {% with team=obj %} -
    -
    -
    - execitor-image -
    -

    - {{ team.name }} + + + + + {% for obj in coll %} + {% if obj|class_name == 'Team' %} + {% with team=obj %} +

    +
    +
    + execitor-image +
    +

    + {{ team.name }} +

    + +
    Свободен
    +
    + + + + + +
    +
    +

    + Специализации:

    - -
    Свободен
    -
    - - - - - -
    -
    -

    - Специализации: -

    -
    - Интерьеры - 2-й -
    +
    + Интерьеры + 2-й +
    +
    + Визуализация/3D + 45-й +
    +
    + Экстерьеры + 10-й +
    +
    - Визуализация/3D - 45-й + Архитектура + 3-й
    - Экстерьеры - 10-й -
    -
    -
    - Архитектура - 3-й -
    -
    - 3D Моделирование - 100-й -
    + 3D Моделирование + 100-й
    -
    +
    - - -
    - -
    -
    -

    Есть допуск СРО

    -
    +
    + + +
    + +
    +
    +

    Есть допуск СРО

    - - - -{# {% if TEMPLATE_DEBUG %}#} -{#
    #} -{#
    ######## Team owner #########

    Specializations: {{ team.owner.contractor_specializations.all }}

    Location: {{ team.owner.location }}

    Build. classif-s: {% for o in team.owner.orders.all %}{{ o.project.realty.building_classification }}, {% endfor %}

    Constr. types: {% for o in team.owner.orders.all %}{{ o.project.realty.construction_type }}, {% endfor %}

    CRO: {{ team.owner.cro }}

    Work types: {% for o in team.owner.orders.all %}{{ o.project.work_type }}, {% endfor %}



    ######## Team users #########

    Specializations: {% for u in team.users.all %}{{ u.contractor_specializations.all }}, {% endfor %}

    Location: {% for u in team.users.all %}{{ u.location }}, {% endfor %}

    Build. classif-s: {% for u in team.users.all %}{% for o in u.orders.all %}{{ o.project.realty.building_classification }}, {% endfor %}; {% endfor %}

    Constr. types: {% for u in team.users.all %}{% for o in u.orders.all %}{{ o.project.realty.construction_type }}, {% endfor %}; {% endfor %}

    CRO: {% for u in team.users.all %}{{ u.cro }}, {% endfor %}

    Work types: {% for u in team.users.all %}{% for o in u.orders.all %}{{ o.project.work_type }}, {% endfor %}; {% endfor %}
    #} -{#
    #} -{# {% endif %}#} - -
    - {% for portf in team.portfolios.all|slice:':4' %} - - {% endfor %} +
    + + + {% if TEMPLATE_DEBUG %} +
    +
    ######## Team owner #########

    Specializations: {{ team.owner.contractor_specializations.all }}

    Location: {{ team.owner.location }}

    Build. classif-s: {% for o in team.owner.orders.all %}{{ o.project.realty.building_classification }}, {% endfor %}

    Constr. types: {% for o in team.owner.orders.all %}{{ o.project.realty.construction_type }}, {% endfor %}

    CRO: {{ team.owner.cro }}

    Work types: {% for o in team.owner.orders.all %}{{ o.project.work_type }}, {% endfor %}



    ######## Team users #########

    Specializations: {% for u in team.users.all %}{{ u.contractor_specializations.all }}, {% endfor %}

    Location: {% for u in team.users.all %}{{ u.location }}, {% endfor %}

    Build. classif-s: {% for u in team.users.all %}{% for o in u.orders.all %}{{ o.project.realty.building_classification }}, {% endfor %}; {% endfor %}

    Constr. types: {% for u in team.users.all %}{% for o in u.orders.all %}{{ o.project.realty.construction_type }}, {% endfor %}; {% endfor %}

    CRO: {% for u in team.users.all %}{{ u.cro }}, {% endfor %}

    Work types: {% for u in team.users.all %}{% for o in u.orders.all %}{{ o.project.work_type }}, {% endfor %}; {% endfor %}
    + {% endif %} + + +
    + {% for portf in team.portfolios.all|slice:':4' %} + + {% endfor %}
    - {% endwith %} - {% elif obj|class_name == 'User' %} - {% with contractor=obj %} -
    - + {% endwith %} + {% elif obj|class_name == 'User' %} + {% with contractor=obj %} +
    +
    +
    + execitor-image +
    +

    + {{ contractor.get_full_name }} [{{ contractor.username }}] +

    + +
    Свободен
    +
    + + + + + +
    +
    +

    + Специализации:

    - -
    Свободен
    -
    - - - - - -
    -
    -

    - Специализации: -

    -
    - Интерьеры - 2-й -
    +
    + Интерьеры + 2-й +
    +
    + Визуализация/3D + 45-й +
    +
    + Экстерьеры + 10-й +
    +
    - Визуализация/3D - 45-й + Архитектура + 3-й
    - Экстерьеры - 10-й -
    -
    -
    - Архитектура - 3-й -
    -
    - 3D Моделирование - 100-й -
    + 3D Моделирование + 100-й
    -
    +
    - - -
    - -
    -
    -

    Есть допуск СРО

    -
    +
    + + +
    + +
    +
    +

    Есть допуск СРО

    - - -{# {% if TEMPLATE_DEBUG %}#} -{#
    #} -{#
    Specializations: {{ contractor.contractor_specializations.all }}

    Location: {{ contractor.location }}

    Build. classif-s: {% for o in contractor.orders.all %}{{ o.project.realty.building_classification }}, {% endfor %}

    Constr. types: {% for o in contractor.orders.all %}{{ o.project.realty.construction_type }}, {% endfor %}

    CRO: {{ contractor.cro }}

    Work types: {% for o in contractor.orders.all %}{{ o.project.work_type }}, {% endfor %}
    #} -{#
    #} -{# {% endif %}#} - -
    - {% for portf in contractor.portfolios.all|slice:':4' %} - - {% endfor %} +
    + + + {% if TEMPLATE_DEBUG %} +
    +
    Specializations: {{ contractor.contractor_specializations.all }}

    Location: {{ contractor.location }}

    Build. classif-s: {% for o in contractor.orders.all %}{{ o.project.realty.building_classification }}, {% endfor %}

    Constr. types: {% for o in contractor.orders.all %}{{ o.project.realty.construction_type }}, {% endfor %}

    CRO: {{ contractor.cro }}

    Work types: {% for o in contractor.orders.all %}{{ o.project.work_type }}, {% endfor %}
    + {% endif %} + +
    + {% for portf in contractor.portfolios.all|slice:':4' %} + + {% endfor %}
    - {% endwith %} - {% endif %} - {% endfor %} - - -
    - {% include 'partials/pagination.html' %} -
    - +
    + {% endwith %} + {% endif %} + {% endfor %} + + +
    + {% include 'partials/pagination.html' %} +
    {% include 'partials/footer.html' %} diff --git a/users/templates/customer_profile_open_projects.html b/users/templates/customer_profile_open_projects.html index 69157cd..1c060a1 100644 --- a/users/templates/customer_profile_open_projects.html +++ b/users/templates/customer_profile_open_projects.html @@ -1,7 +1,6 @@ {% extends 'partials/base.html' %} -{% load staticfiles %} - + {% block content %} {% include 'partials/header.html' %} @@ -9,36 +8,35 @@
    {% include 'partials/customer_profile_info_block.html' %} -
    + + +
    {% for proj in projects %}
    @@ -80,11 +78,10 @@
  • -
    + {% csrf_token %} - - Переместить в корзину + Переместить в корзину
  • @@ -93,6 +90,10 @@ {% endfor %}
    +
    + {% include 'partials/pagination.html' %} +
    + {% include 'partials/footer.html' %}
    diff --git a/users/templates/customer_profile_reviews.html b/users/templates/customer_profile_reviews.html index 46f4490..6b43394 100644 --- a/users/templates/customer_profile_reviews.html +++ b/users/templates/customer_profile_reviews.html @@ -35,7 +35,7 @@ {% endif %}
    -

    {{ review.text }}{% if TEMPLATE_DEBUG %}. {% lorem %}{% endif %}

    +

    {{ review.text }}

    {% endfor %} diff --git a/users/templates/customer_profile_trashed_projects.html b/users/templates/customer_profile_trashed_projects.html index 4be67cb..e5e221b 100644 --- a/users/templates/customer_profile_trashed_projects.html +++ b/users/templates/customer_profile_trashed_projects.html @@ -11,21 +11,19 @@
    - +
    + {{ form.realty }} +
    @@ -34,6 +32,7 @@

    +
    {% for proj in projects %}
    @@ -94,6 +93,10 @@
    {% endfor %}
    + +
    + {% include 'partials/pagination.html' %} +
    {% include 'partials/footer.html' %}
    diff --git a/users/templates/partials/customer_profile_info_block.html b/users/templates/partials/customer_profile_info_block.html index 0f9b96e..64617ac 100644 --- a/users/templates/partials/customer_profile_info_block.html +++ b/users/templates/partials/customer_profile_info_block.html @@ -1,4 +1,6 @@ -{% load staticfiles %} +{% load projects_tags %} + +
    @@ -11,16 +13,15 @@

    - {{ object.get_full_name }} [ivanov_petr] + {{ customer.get_full_name }} [{{ customer.username }}]

    -

    {{ object.location.name }}

    - +

    {{ customer.location.name }}

    +
    - {% load projects_tags %} - {% ratings_widget customer.pk %} + {% ratings_widget customer.pk %}
    diff --git a/users/templatetags/user_tags.py b/users/templatetags/user_tags.py index 3bae815..be8033c 100644 --- a/users/templatetags/user_tags.py +++ b/users/templatetags/user_tags.py @@ -7,6 +7,7 @@ def has_group(user, group_name): groups = user.groups.all().values_list('name', flat=True) return True if group_name in groups else False + @register.simple_tag def test(): return 'Hello there' diff --git a/users/views.py b/users/views.py index 98b5286..1da9d36 100644 --- a/users/views.py +++ b/users/views.py @@ -13,16 +13,23 @@ import itertools import natsort import pydash as _; _.map = _.map_; _.filter = _.filter_ -from .forms import UserEditForm, ContractorFilterForm, ContractorFinancicalInfoForm from .mixins import CheckForUserMixin from .models import User, Team, ContractorFinancialInfo +from archilance import util from archilance.mixins import BaseMixin -from common.utils import get_or_none from projects.forms import PortfolioForm +from projects.models import Project from reviews.models import Review from specializations.models import Specialization from work_sell.forms import WorkSellForm +from .forms import ( + ContractorFilterForm, + ContractorFinancicalInfoForm, + CustomerProfileProjectRealtyForm, + UserEditForm, +) + def send_mail_test(request): send_mail('Subject here', 'Here is the message.Mukhtar hello ', '', ['muhtarzubanchi05@gmail.com'], fail_silently=False) @@ -244,26 +251,100 @@ class ContractorOfficeDetailView(DetailView): context_object_name = 'contractor' -class CustomerProfileOpenProjectsView(BaseMixin, DetailView): - model = User +class CustomerProfileOpenProjectsView(BaseMixin, View): template_name = 'customer_profile_open_projects.html' - context_object_name = 'customer' + form_class = CustomerProfileProjectRealtyForm - def get_context_data(self, **kwargs): - c = super().get_context_data(**kwargs) - c['projects'] = self.object.projects.filter(state='active') - return c + def get(self, request, *args, **kwargs): + context = self.get_context_data(**_.merge({}, request.GET, kwargs)) + customer = get_object_or_404(User.customer_objects, pk=kwargs.get('pk')) + form = self.form_class(request.GET, request=request, customer=customer) + projects = customer.projects.filter(state='active') + + if form.is_valid(): + realty = form.cleaned_data.get('realty') + + if realty: + projects = projects.filter(realty=realty) + else: + if form.errors: + messages.info(request, ( + '

    Произошла ошибка (form)

    ' + '
    {form}
    ' + ).format(form=pformat(form.errors))) + + paginator = Paginator(projects, settings.PAGE_SIZE) + page = request.GET.get('page') + + try: + projects = paginator.page(page) + except PageNotAnInteger: + projects = paginator.page(1) + except EmptyPage: + projects = paginator.page(paginator.num_pages) + + context.update({ + 'form': form, + + 'projects': projects, + 'customer': customer, + + 'open_project_count': projects.paginator.count, + 'trashed_project_count': customer.projects.filter(state='trashed').count(), + + 'is_paginated': True, + 'page_obj': projects, + }) + + return render(request, self.template_name, context) -class CustomerProfileTrashedProjectsView(BaseMixin, DetailView): - model = User +class CustomerProfileTrashedProjectsView(BaseMixin, View): template_name = 'customer_profile_trashed_projects.html' - context_object_name = 'customer' + form_class = CustomerProfileProjectRealtyForm - def get_context_data(self, **kwargs): - c = super().get_context_data(**kwargs) - c['projects'] = self.object.projects.filter(state='trashed') - return c + def get(self, request, *args, **kwargs): + context = self.get_context_data(**_.merge({}, request.GET, kwargs)) + customer = get_object_or_404(User.customer_objects, pk=kwargs.get('pk')) + form = self.form_class(request.GET, request=request, customer=customer) + projects = customer.projects.filter(state='trashed') + + if form.is_valid(): + realty = form.cleaned_data.get('realty') + + if realty: + projects = projects.filter(realty=realty) + else: + if form.errors: + messages.info(request, ( + '

    Произошла ошибка (form)

    ' + '
    {form}
    ' + ).format(form=pformat(form.errors))) + + paginator = Paginator(projects, settings.PAGE_SIZE) + page = request.GET.get('page') + + try: + projects = paginator.page(page) + except PageNotAnInteger: + projects = paginator.page(1) + except EmptyPage: + projects = paginator.page(paginator.num_pages) + + context.update({ + 'form': form, + + 'projects': projects, + 'customer': customer, + + 'open_project_count': customer.projects.filter(state='active').count(), + 'trashed_project_count': projects.paginator.count, + + 'is_paginated': True, + 'page_obj': projects, + }) + + return render(request, self.template_name, context) class CustomerProfileCurrentProjectsView(BaseMixin, DetailView): @@ -319,7 +400,7 @@ class ContractorProfileEditView(CheckForUserMixin, View): def get(self, request, *args, **kwargs): instance = get_object_or_404(User, pk=request.user.pk) form = self.form_class(instance=instance) - root = get_or_none(Specialization, name='_root') + root = util.get_or_none(Specialization, name='_root') nodes = root.get_descendants('lft') return render(request, self.template_name, {'form': form, 'nodes': nodes}) diff --git a/work_sell/templates/worksells_list.html b/work_sell/templates/worksells_list.html index 5a4ed00..bbb975b 100644 --- a/work_sell/templates/worksells_list.html +++ b/work_sell/templates/worksells_list.html @@ -1,8 +1,10 @@ {% extends 'partials/base.html' %} + {% load staticfiles %} {% load thumbnail %} {% block content %} + {% include 'partials/header.html' %}
    @@ -108,83 +110,50 @@
    - -
    - {% for work in object_list %} -
    -
    - - {% thumbnail work.img "265x265" crop="center" as im %} -
    -
    -
    - {% endthumbnail %} -
    -
    -
    - {{ work.budget }} + + + +
    + {% for work in object_list %} +
    +
    + + {% thumbnail work.img "265x265" crop="center" as im %} +
    +
    + {% endthumbnail %} +
    +
    +
    + {{ work.budget }}
    -
    -

    {{ work }}

    +
    +
    +

    {{ work }}

    - - {% endfor %} -
    - - - - -{# {% if is_paginated %}#} -{#
    #} -{# #} -{#
    #} -{# {% endif %}#} - - -
    - {% include 'partials/pagination.html' %} -
    - +
    + {% endfor %} +
    + + +
    + {% include 'partials/pagination.html' %} +
    {% include 'partials/footer.html' %} From 60c05d03109f8bdf0f500e57b04d577b1fad1824 Mon Sep 17 00:00:00 2001 From: ArturBaybulatov Date: Tue, 26 Jul 2016 19:53:45 +0300 Subject: [PATCH 2/2] #ARC-11 --- .../management/commands/generate_reviews.py | 2 +- .../management/commands/generate_users.py | 1 + archilance/util.py | 6 +- .../migrations/0004_auto_20160726_1931.py | 26 +++ templates/home.html | 7 - templates/partials/base.html | 12 +- users/admin.py | 4 +- users/forms.py | 6 +- users/migrations/0003_auto_20160726_1931.py | 29 +++ users/mixins.py | 1 - users/models.py | 4 +- users/templates/contractor_profile.html | 7 +- users/templates/contractor_profile_edit.html | 26 +-- users/templates/customer_profile_edit.html | 207 ++++++++++-------- .../partials/customer_profile_info_block.html | 4 +- users/urls.py | 4 +- users/views.py | 96 ++++++-- 17 files changed, 283 insertions(+), 159 deletions(-) create mode 100644 projects/migrations/0004_auto_20160726_1931.py create mode 100644 users/migrations/0003_auto_20160726_1931.py diff --git a/archilance/management/commands/generate_reviews.py b/archilance/management/commands/generate_reviews.py index d902b73..98f8a94 100644 --- a/archilance/management/commands/generate_reviews.py +++ b/archilance/management/commands/generate_reviews.py @@ -23,7 +23,7 @@ class Command(BaseCommand): review.project = Project.objects.order_by('?').first() review.stars = _.random(1, 5) - review.text = util.lorem(_.random(5, 15)) + review.text = util.lorem() review.is_secured = _.sample((True, False)) review.save() diff --git a/archilance/management/commands/generate_users.py b/archilance/management/commands/generate_users.py index 72c81cb..5940f83 100644 --- a/archilance/management/commands/generate_users.py +++ b/archilance/management/commands/generate_users.py @@ -81,6 +81,7 @@ class Command(BaseCommand): return User.objects.create( first_name='Василий', last_name='Пупкин', + patronym='Иванович', username=username, email='%s@example.com' % username, is_active=True, diff --git a/archilance/util.py b/archilance/util.py index c2edc56..adbd3a1 100644 --- a/archilance/util.py +++ b/archilance/util.py @@ -1,6 +1,7 @@ from django.shortcuts import _get_queryset from django.utils import timezone from pprint import pprint, pformat +import natsort import pydash as _; _.map = _.map_; _.filter = _.filter_ import random @@ -59,13 +60,14 @@ def get_attr_or_none(klass, *args, attr=None, **kwargs): def model_fields(model, width=200): + fields = natsort.natsorted(model._meta.get_fields(), key=lambda f: f.name) + pprint([( f.name, 'Relation? %s' % f.is_relation, 'Null? %s' % f.null, 'Blank? %s' % f.blank if not f.is_relation else '(relation)', - 'Hidden? %s' % (f.is_hidden() if hasattr(f, 'is_hidden') else False), - ) for f in model._meta.get_fields(include_hidden=True)], width=width) + ) for f in fields], width=width) def lorem(sentences=5): diff --git a/projects/migrations/0004_auto_20160726_1931.py b/projects/migrations/0004_auto_20160726_1931.py new file mode 100644 index 0000000..d703839 --- /dev/null +++ b/projects/migrations/0004_auto_20160726_1931.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-07-26 16:31 +from __future__ import unicode_literals + +import datetime +from django.db import migrations, models +from django.utils.timezone import utc + + +class Migration(migrations.Migration): + + dependencies = [ + ('projects', '0003_auto_20160725_1606'), + ] + + operations = [ + migrations.AlterModelOptions( + name='stage', + options={'ordering': ['pos'], 'verbose_name': 'Этап', 'verbose_name_plural': 'Этапы'}, + ), + migrations.AlterField( + model_name='stage', + name='created', + field=models.DateTimeField(default=datetime.datetime(2016, 7, 26, 16, 31, 5, 738741, tzinfo=utc)), + ), + ] diff --git a/templates/home.html b/templates/home.html index de9778e..bc6c7a9 100644 --- a/templates/home.html +++ b/templates/home.html @@ -6,14 +6,7 @@ {% include 'partials/header.html' %}
    -{# {% url "password_reset_recover" %}#}

    Основная задача сайта

    - -

    - Authed? {{ request.user.is_authenticated }}
    - {{ request.user }} ({{ request.user.pk }})
    - {{ request.user.groups.all }}
    -

    diff --git a/templates/partials/base.html b/templates/partials/base.html index 0d72d28..09ff0fb 100644 --- a/templates/partials/base.html +++ b/templates/partials/base.html @@ -31,10 +31,19 @@ {% if messages %} {% for message in messages %} -
    {{ message | safe }}
    +
    {{ message|safe }}
    {% endfor %} {% endif %} +
    + {{ request.user }}
    + + {% if request.user.is_authenticated %} + PK: {{ request.user.pk }}
    + Groups: {{ request.user.groups.all }} + {% endif %} +
    + {% block content %}{% endblock %} @@ -50,6 +59,7 @@ + diff --git a/users/admin.py b/users/admin.py index 1d81876..1890f01 100644 --- a/users/admin.py +++ b/users/admin.py @@ -1,6 +1,6 @@ from django.contrib import admin -from .models import User, Team, ContractorFinancialInfo, ContractorResume, ContractorResumeFiles +from .models import User, Team, UserFinancialInfo, ContractorResume, ContractorResumeFiles class UserAdmin(admin.ModelAdmin): @@ -11,7 +11,7 @@ class UserAdmin(admin.ModelAdmin): return ', '.join(g.name for g in obj.groups.all()) admin.site.register(User, UserAdmin) -admin.site.register(ContractorFinancialInfo) +admin.site.register(UserFinancialInfo) admin.site.register(Team) admin.site.register(ContractorResume) admin.site.register(ContractorResumeFiles) diff --git a/users/forms.py b/users/forms.py index 0812d8f..7a4f24b 100644 --- a/users/forms.py +++ b/users/forms.py @@ -3,7 +3,7 @@ from django.forms import ModelForm import itertools import pydash as _; _.map = _.map_; _.filter = _.filter_ -from .models import User, ContractorFinancialInfo +from .models import User, UserFinancialInfo from common.models import Location from projects.models import Project, Realty, BuildingClassfication, ConstructionType from specializations.models import Specialization @@ -131,7 +131,7 @@ class CustomerProfileProjectRealtyForm(forms.Form): ) -class ContractorFinancicalInfoForm(ModelForm): +class UserFinancicalInfoForm(ModelForm): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.fields['residency'].choices = self.fields['residency'].choices[1:] @@ -141,7 +141,7 @@ class ContractorFinancicalInfoForm(ModelForm): # self.fields['residency'].widget.choices = self.fields['residency'].choices class Meta: - model = ContractorFinancialInfo + model = UserFinancialInfo fields = ( 'fio', diff --git a/users/migrations/0003_auto_20160726_1931.py b/users/migrations/0003_auto_20160726_1931.py new file mode 100644 index 0000000..6ee662f --- /dev/null +++ b/users/migrations/0003_auto_20160726_1931.py @@ -0,0 +1,29 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9.7 on 2016-07-26 16:31 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('users', '0002_auto_20160725_1605'), + ] + + operations = [ + migrations.RenameModel( + old_name='ContractorFinancialInfo', + new_name='UserFinancialInfo', + ), + migrations.RemoveField( + model_name='user', + name='contractor_financial_info', + ), + migrations.AddField( + model_name='user', + name='financial_info', + field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='user', to='users.UserFinancialInfo'), + ), + ] diff --git a/users/mixins.py b/users/mixins.py index d31cc8f..6bf0e1b 100644 --- a/users/mixins.py +++ b/users/mixins.py @@ -3,7 +3,6 @@ from django.contrib import messages class CheckForUserMixin(object): - def dispatch(self, request, *args, **kwargs): if request.user.is_authenticated(): pk = kwargs.get('pk') diff --git a/users/models.py b/users/models.py index 25e071f..3a819db 100644 --- a/users/models.py +++ b/users/models.py @@ -41,7 +41,7 @@ class CustomerUserManager(models.Manager): return super().get_queryset().filter(groups__name='Заказчики') -class ContractorFinancialInfo(models.Model): +class UserFinancialInfo(models.Model): RESIDENCIES = ( ('russian_resident', 'Резидент РФ'), ('non_russian_resident', 'Нерезидент РФ'), @@ -117,7 +117,6 @@ class User(AbstractBaseUser, PermissionsMixin): ) avatar = models.ImageField(upload_to='users/avatars/', blank=True) - contractor_financial_info = models.OneToOneField(ContractorFinancialInfo, related_name='contractor', blank=True, null=True) contractor_resume = models.OneToOneField(ContractorResume, related_name='contractor', blank=True, null=True) contractor_specializations = TreeManyToManyField(Specialization, related_name='contractors', blank=True) contractor_status = models.CharField(default='free', max_length=20, choices=STATUSES) @@ -126,6 +125,7 @@ class User(AbstractBaseUser, PermissionsMixin): date_joined = models.DateTimeField(default=timezone.now) date_of_birth = models.DateTimeField(null=True, blank=True) email = models.EmailField(max_length=255, unique=True, db_index=True) + financial_info = models.OneToOneField(UserFinancialInfo, related_name='user', blank=True, null=True) first_name = models.CharField(max_length=255, blank=True) gender = models.CharField(max_length=30, choices=GENDERS, blank=True) is_active = models.BooleanField(default=True) diff --git a/users/templates/contractor_profile.html b/users/templates/contractor_profile.html index 0cdaa44..c04773f 100644 --- a/users/templates/contractor_profile.html +++ b/users/templates/contractor_profile.html @@ -1,6 +1,7 @@ {% extends 'partials/base.html' %} -{% load staticfiles %} +{% load projects_tags %} +{% load specializtions_tags %} {% load thumbnail %} @@ -70,7 +71,7 @@

    - {{ contractor.get_full_name }}[{{ contractor.username }}] + {{ contractor.get_full_name }} [{{ contractor.username }}]

    Россия, Москва

    @@ -80,11 +81,9 @@ показать контакты
    - {% load specializtions_tags %} {% specialization_widget contractor.pk %}
    - {% load projects_tags %} {% ratings_widget contractor.pk %} {% if contractor.cro %} diff --git a/users/templates/contractor_profile_edit.html b/users/templates/contractor_profile_edit.html index 2d733c7..197d047 100644 --- a/users/templates/contractor_profile_edit.html +++ b/users/templates/contractor_profile_edit.html @@ -15,19 +15,19 @@ {% load mptt_tags %} {{ form.errors }}
    -
    -
    - - profile-image -
    -
    - -
    +
    +
    + + profile-image +
    +
    + +

    ФИО:

    diff --git a/users/templates/customer_profile_edit.html b/users/templates/customer_profile_edit.html index 0432434..effa6ff 100644 --- a/users/templates/customer_profile_edit.html +++ b/users/templates/customer_profile_edit.html @@ -1,113 +1,126 @@ {% extends 'partials/base.html' %} -{% load staticfiles %} {% load thumbnail %} {% block content %} -{% include 'partials/header.html' %} + {% include 'partials/header.html' %} +
    -
    {% csrf_token %} -
    -
    - {{ form.errors }} -
    -
    -
    - profile-image -
    -
    - -
    -
    -
    -

    ФИО:

    - - - -
    -
    -

    Местоположение: {{ form.location.value }}

    -
    - - - - - -
    -
    -
    -
    -
    -
    -
    - -
    -
    -
    -
    -
    -
    Дата рождения:
    -
    Пол:
    -
    -
    -
    - {{ form.date_of_birth }} -
    -
    - -

    Мужской

    - -

    Женский

    -
    -
    -
    -
    Сайт:
    -
    Skype:
    -{#
    Электронная почта:
    #} -
    Телефон:
    -
    -
    -
    - -
    -
    - -
    -{#
    #} -{# #} -{#
    #} -
    - -
    -
    -
    -
    - -

    Есть допуск СРО

    -
    -
    - -
    -
    + + {% csrf_token %} + +
    +
    + {{ form.errors }} + +
    +
    +
    + profile-image +
    +
    + +
    +
    +
    +

    ФИО:

    + + + +
    +
    +

    Местоположение: {{ form.location.value }}

    +
    + + + + + +
    +
    +
    +
    +
    + +
    +
    + +
    +
    + +
    +
    +
    +
    Дата рождения:
    +
    Пол:
    +
    + +
    +
    + {{ form.date_of_birth }} +
    +
    + +

    Мужской

    + +

    Женский

    +
    +
    + +
    +
    Сайт:
    +
    Skype:
    +{#
    Электронная почта:
    #} +
    Телефон:
    +
    + +
    +
    + +
    +
    + +
    +{#
    #} +{# #} +{#
    #} +
    + +
    +
    + +
    +
    + +

    Есть допуск СРО

    +
    +
    + + +
    +
    - {% include 'partials/footer.html' %} + + {% include 'partials/footer.html' %}
    {% endblock %} + + {% block js_block %} -