remotes/origin/PR-39
ArturBaybulatov 10 years ago
parent 3ed593b96c
commit b7db81918c
  1. 53
      assets/index.js
  2. 23
      projects/forms.py
  3. 16
      projects/migrations/0006_merge.py
  4. 33
      projects/migrations/0007_answermessage.py
  5. 25
      projects/migrations/0008_auto_20160815_1900.py
  6. 19
      projects/models.py
  7. 162
      projects/templates/project_detail.html
  8. 9
      projects/urls.py
  9. 55
      projects/views.py

@ -318,15 +318,60 @@ $fileUploadContainer.on('click', '.existing-file-remove-btn', function($evt) {
// Project answer portfolio selection ---------------------- // Project answer portfolio selection ----------------------
//function ...() { $('input[type="checkbox"].answer-portfolio-select').on('change', function($evt) {
// var $that = $(this)
//} var portfId = $that.val()
var $container = $('#answer-portfolio-photo-widget-container')
if ($that.prop('checked')) {
$.ajax({url: '/api/portfolios/' + portfId + '/', method: 'GET', dataType: 'json'})
.then(function(portf) {
var photoUrl = portf.photos[0].img
var $newWidget = $container.find('.answer-portfolio-photo-widget').first().clone()
$newWidget.data('portf-id', portfId)
var $newWidgetPhotoCont = $newWidget.find('.answer-portfolio-photo-widget-photo-cont').first()
$newWidgetPhotoCont.css('background', 'url("' + photoUrl + '") no-repeat center')
$container.append($newWidget)
$newWidget.css('display', 'block')
})
} else {
var $widgets = $container.find('.answer-portfolio-photo-widget')
var $widget = _.find(function(el) {return $(el).data('portf-id') === portfId}, $widgets)
$widget.remove()
}
})
var initialPortfIds = $('input[type="checkbox"]:checked.answer-portfolio-select').map(function(i, el) {return $(el).val()})
loadAllPhotos(initialPortfIds)
function loadAllPhotos(portfIds) {
var $container = $('#answer-portfolio-photo-widget-container')
_.each(function(portfId) {
$.ajax({url: '/api/portfolios/' + portfId + '/', method: 'GET', dataType: 'json'})
.then(function(portf) {
var photoUrl = portf.photos[0].img
var $newWidget = $container.find('.answer-portfolio-photo-widget').first().clone()
$newWidget.data('portf-id', portfId)
var $newWidgetPhotoCont = $newWidget.find('.answer-portfolio-photo-widget-photo-cont').first()
$newWidgetPhotoCont.css('background', 'url("' + photoUrl + '") no-repeat center')
$container.append($newWidget)
$newWidget.css('display', 'block')
})
}, portfIds)
}

@ -5,8 +5,9 @@ from mptt.forms import TreeNodeChoiceField
from pprint import pprint, pformat from pprint import pprint, pformat
import itertools import itertools
from .models import Project, ProjectFile, Portfolio, Answer, Realty, PortfolioPhoto, Stage, Specialization from .models import Project, ProjectFile, Portfolio, Answer, AnswerMessage, Realty, PortfolioPhoto, Stage
from common.models import Location from common.models import Location
from specializations.models import Specialization
from users.models import User from users.models import User
@ -148,10 +149,6 @@ class RealtyForm(forms.ModelForm):
# self.fields['location'].queryset = Location.objects # Migrate with this enabled # self.fields['location'].queryset = Location.objects # Migrate with this enabled
class Realty1Form(forms.Form):
pass
class PortfolioForm(forms.ModelForm): class PortfolioForm(forms.ModelForm):
class Meta: class Meta:
model = Portfolio model = Portfolio
@ -166,6 +163,8 @@ class PortfolioForm(forms.ModelForm):
class ProjectAnswerForm(forms.ModelForm): class ProjectAnswerForm(forms.ModelForm):
text = forms.CharField(widget=forms.Textarea)
class Meta: class Meta:
model = Answer model = Answer
@ -176,7 +175,6 @@ class ProjectAnswerForm(forms.ModelForm):
'secure_deal_only', 'secure_deal_only',
'term', 'term',
'term_type', 'term_type',
'text',
) )
widgets = { widgets = {
@ -203,6 +201,19 @@ class ProjectAnswerForm(forms.ModelForm):
self.fields['portfolios'].queryset = self.request.user.portfolios.all() self.fields['portfolios'].queryset = self.request.user.portfolios.all()
class ProjectAnswerMessageForm(forms.ModelForm):
class Meta:
model = AnswerMessage
fields = (
'text',
)
def __init__(self, *args, **kwargs):
self.request = kwargs.pop('request')
super().__init__(*args, **kwargs)
class StageForm(forms.ModelForm): class StageForm(forms.ModelForm):
class Meta: class Meta:
model = Stage model = Stage

@ -0,0 +1,16 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2016-08-15 08:24
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('projects', '0005_auto_20160812_1931'),
('projects', '0005_auto_20160812_1956'),
]
operations = [
]

@ -0,0 +1,33 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2016-08-15 14:38
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone
class Migration(migrations.Migration):
dependencies = [
('contenttypes', '0002_remove_content_type_name'),
('projects', '0006_merge'),
]
operations = [
migrations.CreateModel(
name='AnswerMessage',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created', models.DateTimeField(default=django.utils.timezone.now)),
('is_sender_customer', models.BooleanField(default=False)),
('object_id', models.IntegerField()),
('answer', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='messages', to='projects.Answer')),
('content_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType')),
],
options={
'verbose_name_plural': 'Отклики на проекты -- переписки',
'verbose_name': 'Отклики на проекты -- переписка',
},
),
]

@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2016-08-15 16:00
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('projects', '0007_answermessage'),
]
operations = [
migrations.RemoveField(
model_name='answer',
name='text',
),
migrations.AddField(
model_name='answermessage',
name='text',
field=models.TextField(default=''),
preserve_default=False,
),
]

@ -126,7 +126,6 @@ class Answer(models.Model):
secure_deal_only = models.BooleanField(default=False) secure_deal_only = models.BooleanField(default=False)
term = models.IntegerField(default=0) term = models.IntegerField(default=0)
term_type = models.CharField(max_length=10, choices=TERMS, default='hour') term_type = models.CharField(max_length=10, choices=TERMS, default='hour')
text = models.TextField()
content_type = models.ForeignKey(ContentType, limit_choices_to=Q(app_label='users', model='user') | Q(app_label='users', model='team')) content_type = models.ForeignKey(ContentType, limit_choices_to=Q(app_label='users', model='user') | Q(app_label='users', model='team'))
object_id = models.IntegerField() object_id = models.IntegerField()
@ -141,6 +140,24 @@ class Answer(models.Model):
ordering = ('-created',) ordering = ('-created',)
class AnswerMessage(models.Model):
answer = models.ForeignKey(Answer, related_name='messages')
created = models.DateTimeField(default=timezone.now)
is_sender_customer = models.BooleanField(default=False)
text = models.TextField()
content_type = models.ForeignKey(ContentType, limit_choices_to=Q(app_label='users', model='user') | Q(app_label='users', model='team'))
object_id = models.IntegerField()
contractor_or_team = GenericForeignKey('content_type', 'object_id')
def __str__(self):
return str(self.pk)
class Meta:
verbose_name = 'Отклики на проекты -- переписка'
verbose_name_plural = 'Отклики на проекты -- переписки'
class AnswerFile(models.Model): class AnswerFile(models.Model):
answer = models.ForeignKey(Answer, related_name='files', blank=True, null=True) answer = models.ForeignKey(Answer, related_name='files', blank=True, null=True)
name = models.CharField(max_length=255) name = models.CharField(max_length=255)

@ -267,50 +267,52 @@
<div class="commBlock44 disTab"> <div class="commBlock44 disTab">
<div class="comm44 disTab"> {% for message in answer.messages.all %}
<div class="col-lg-10 col-lg-offset-1"> <div class="comm44 disTab">
<p class="nameComm"> <div class="col-lg-10 col-lg-offset-1">
Иванов Петр Иванович {% if message.is_sender_customer %}
</p> <p class="nameComm nameCommAct">
<span class="dateComm44"> {{ project.customer.get_full_name }}
13.01.2016 / 21:05 </p>
</span> {% else %}
<div class="stars box-sizing"> <p class="nameComm">
<span class="glyphicon glyphicon-star starAct" aria-hidden="true"></span> {% if answer.author|class_name == 'User' %}
<span class="glyphicon glyphicon-star starAct" aria-hidden="true"></span> {{ answer.author.get_full_name }}
<span class="glyphicon glyphicon-star starAct" aria-hidden="true"></span> {% elif answer.author|class_name == 'Team' %}
<span class="glyphicon glyphicon-star" aria-hidden="true"></span> {{ answer.author.name }}
<span class="glyphicon glyphicon-star" aria-hidden="true"></span> {% endif %}
</p>
{% endif %}
<span class="dateComm44">
{{ message.created }}
</span>
<p class="textComm44">
{{ message.text }}
</p>
</div> </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> {% endfor %}
<div class="comm44 disTab"> <div class="comm44 disTab">
{# <div class="i col-lg-10 col-lg-offset-1">#}
{# <a href="#" onclick="return false" class="answerComm">#}
{# Ответить#}
{# </a>#}
{# </div>#}
<div class="col-lg-10 col-lg-offset-1"> <div class="col-lg-10 col-lg-offset-1">
<p class="nameComm nameCommAct"> <form action="{% url 'projects:create-answer-message' pk=project.pk %}" method="POST" novalidate>
Иванов Петр Иванович {% csrf_token %}
</p> <input type="hidden" name="next" value="{% url 'projects:detail' pk=project.pk %}">
<span class="dateComm44">
13.01.2016 / 21:05 <div><textarea name="text"></textarea></div>
</span> <div><button type="submit">Отправить</button></div>
<p class="textComm44"> </form>
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>
</div> </div>
</div> </div>
{% else %} {% else %}
@ -356,17 +358,15 @@
</div> </div>
<div class="col-lg-3"></div> <div class="col-lg-3"></div>
</div> </div>
<div class="polsF1 disTab searchF1"> <div id="answer-portfolio-photo-widget-container" class="polsF1 disTab searchF1">
{% for x in 'abc' %} <div class="col-lg-3 answer-portfolio-photo-widget" style="display: none">
<div class="col-lg-3"> <div class="insetCol box-sizing disTab">
<div class="insetCol box-sizing disTab"> <div class="imgGal answer-portfolio-photo-widget-photo-cont">
<div class="imgGal" s--tyle="background: url('{{ portf.photos.first.img.url }}') no-repeat center"> <div class="imgFigure"></div>
<div class="imgFigure"></div>
</div>
</div> </div>
</div> </div>
{% endfor %} </div>
</div> </div>
<div class="polsF1 disTab searchF1"> <div class="polsF1 disTab searchF1">
@ -380,7 +380,8 @@
type="checkbox" type="checkbox"
name="{{ form.portfolios.html_name }}" name="{{ form.portfolios.html_name }}"
value="{{ p.pk }}" value="{{ p.pk }}"
{% if p.pk|str in form.portfolios.value %}checked{% endif %}> {% if p.pk|str in form.portfolios.value %}checked{% endif %}
class="answer-portfolio-select">
{{ p.name }} {{ p.name }}
</li> </li>
@ -557,40 +558,49 @@
</div> </div>
<div class="commBlock44 disTab"> <div class="commBlock44 disTab">
<div class="comm44 disTab"> {% for message in answer.messages.all %}
<div class="col-lg-10 col-lg-offset-1"> <div class="comm44 disTab">
<p class="nameComm"> <div class="col-lg-10 col-lg-offset-1">
Иванов Петр Иванович {% if message.is_sender_customer %}
</p> <p class="nameComm nameCommAct">
<span class="dateComm44"> {{ project.customer.get_full_name }}
13.01.2016 / 21:05 </p>
</span> {% else %}
<div class="stars box-sizing"> <p class="nameComm">
<span class="glyphicon glyphicon-star starAct" aria-hidden="true"></span> {% if answer.author|class_name == 'User' %}
<span class="glyphicon glyphicon-star starAct" aria-hidden="true"></span> {{ answer.author.get_full_name }}
<span class="glyphicon glyphicon-star starAct" aria-hidden="true"></span> {% elif answer.author|class_name == 'Team' %}
<span class="glyphicon glyphicon-star" aria-hidden="true"></span> {{ answer.author.name }}
<span class="glyphicon glyphicon-star" aria-hidden="true"></span> {% endif %}
</p>
{% endif %}
<span class="dateComm44">
{{ message.created }}
</span>
<p class="textComm44">
{{ message.text }}
</p>
</div> </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> {% endfor %}
<div class="comm44 disTab"> <div class="comm44 disTab">
{# <div class="i col-lg-10 col-lg-offset-1">#}
{# <a href="#" onclick="return false" class="answerComm">#}
{# Ответить#}
{# </a>#}
{# </div>#}
<div class="col-lg-10 col-lg-offset-1"> <div class="col-lg-10 col-lg-offset-1">
<p class="nameComm nameCommAct"> <form action="{% url 'projects:create-answer-message' pk=project.pk %}" method="POST" novalidate>
Иванов Петр Иванович {% csrf_token %}
</p> <input type="hidden" name="next" value="{% url 'projects:detail' pk=project.pk %}">
<span class="dateComm44">
13.01.2016 / 21:05 <div><textarea name="text"></textarea></div>
</span> <div><button type="submit">Отправить</button></div>
<p class="textComm44"> </form>
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>

@ -3,7 +3,6 @@ from django.views.generic import TemplateView
from .views import ( from .views import (
add_candidate, add_candidate,
sort_candidates,
contractor_portfolio_create, contractor_portfolio_create,
ContractorPortfolioTrashView, ContractorPortfolioTrashView,
ContractorPortfolioUpdateView, ContractorPortfolioUpdateView,
@ -13,16 +12,18 @@ from .views import (
CustomerProjectRestoreView, CustomerProjectRestoreView,
CustomerProjectTrashView, CustomerProjectTrashView,
OfferOrderView, OfferOrderView,
ProjectAnswerCreateMessageView,
ProjectComparisonView, ProjectComparisonView,
ProjectDetailWithContractorAnswerView, ProjectDetailWithAnswerView,
ProjectFilterView, ProjectFilterView,
sort_candidates,
) )
app_name = 'projects' app_name = 'projects'
urlpatterns = [ urlpatterns = [
urls.url(r'^$', ProjectFilterView.as_view(), name='project-filter'), urls.url(r'^$', ProjectFilterView.as_view(), name='project-filter'),
urls.url(r'^(?P<pk>\d+)/$', ProjectDetailWithContractorAnswerView.as_view(), name='detail'), urls.url(r'^(?P<pk>\d+)/$', ProjectDetailWithAnswerView.as_view(), name='detail'),
urls.url(r'^create/$', CustomerProjectCreateView.as_view(), name='customer-project-create'), urls.url(r'^create/$', CustomerProjectCreateView.as_view(), name='customer-project-create'),
urls.url(r'^(?P<pk>\d+)/edit/$', CustomerProjectEditView.as_view(), name='customer-project-edit'), urls.url(r'^(?P<pk>\d+)/edit/$', CustomerProjectEditView.as_view(), name='customer-project-edit'),
@ -31,6 +32,8 @@ urlpatterns = [
urls.url(r'^(?P<pk>\d+)/restore/$', CustomerProjectRestoreView.as_view(), name='customer-project-restore'), urls.url(r'^(?P<pk>\d+)/restore/$', CustomerProjectRestoreView.as_view(), name='customer-project-restore'),
urls.url(r'^(?P<pk>\d+)/delete/$', CustomerProjectDeleteView.as_view(), name='customer-project-delete'), urls.url(r'^(?P<pk>\d+)/delete/$', CustomerProjectDeleteView.as_view(), name='customer-project-delete'),
urls.url(r'^(?P<pk>\d+)/create-answer-message/$', ProjectAnswerCreateMessageView.as_view(), name='create-answer-message'),
urls.url(r'^portfolio/create/$', contractor_portfolio_create, name='contractor-portfolio-create'), urls.url(r'^portfolio/create/$', contractor_portfolio_create, name='contractor-portfolio-create'),
urls.url(r'^portfolio/(?P<pk>\d+)/edit/$', ContractorPortfolioUpdateView.as_view(), name='contractor-portfolio-edit'), urls.url(r'^portfolio/(?P<pk>\d+)/edit/$', ContractorPortfolioUpdateView.as_view(), name='contractor-portfolio-edit'),

@ -7,7 +7,7 @@ from django.core.files.base import ContentFile
from django.db.models import Q from django.db.models import Q
from django.http import HttpResponseForbidden, HttpResponseRedirect, HttpResponse, Http404 from django.http import HttpResponseForbidden, HttpResponseRedirect, HttpResponse, Http404
from django.shortcuts import render, get_object_or_404, redirect from django.shortcuts import render, get_object_or_404, redirect
from django.views.generic import ListView, DetailView, CreateView, View, UpdateView, TemplateView, FormView from django.views.generic import ListView, DetailView, CreateView, DeleteView, View, UpdateView, TemplateView, FormView
from django.views.generic.base import ContextMixin from django.views.generic.base import ContextMixin
from pprint import pprint, pformat from pprint import pprint, pformat
import json import json
@ -18,27 +18,27 @@ _.filter = _.filter_
import re import re
from .mixins import LastAccessMixin from .mixins import LastAccessMixin
from .models import Project, ProjectFile, Portfolio, PortfolioPhoto, Candidate, Answer, AnswerFile, Realty, Order from .models import Project, ProjectFile, Portfolio, PortfolioPhoto, Candidate, Answer, AnswerFile, AnswerMessage, Realty, Order
from archilance.mixins import BaseMixin from archilance.mixins import BaseMixin
from users.models import User, Team from users.models import User, Team
from work_sell.models import Picture from work_sell.models import Picture
from .forms import ( from .forms import (
ContractorPortfolioTrashForm, ContractorPortfolioTrashForm,
ProjectAnswerForm,
CustomerProjectDeleteForm, CustomerProjectDeleteForm,
CustomerProjectEditForm, CustomerProjectEditForm,
CustomerProjectEditForm,
CustomerProjectRestoreForm, CustomerProjectRestoreForm,
CustomerProjectTrashForm, CustomerProjectTrashForm,
PortfolioForm, PortfolioForm,
ProjectAnswerForm,
ProjectAnswerMessageForm,
ProjectFilterForm, ProjectFilterForm,
ProjectFilterRealtyForm, ProjectFilterRealtyForm,
RealtyForm, RealtyForm,
) )
class ProjectDetailWithContractorAnswerView(BaseMixin, View): class ProjectDetailWithAnswerView(BaseMixin, View):
form_class = ProjectAnswerForm form_class = ProjectAnswerForm
template_name = 'project_detail.html' template_name = 'project_detail.html'
@ -111,6 +111,11 @@ class ProjectDetailWithContractorAnswerView(BaseMixin, View):
if len(file.name) <= 255: if len(file.name) <= 255:
AnswerFile.objects.create(file=file, name=file.name, answer=answer) AnswerFile.objects.create(file=file, name=file.name, answer=answer)
answer_message = AnswerMessage(text=form.cleaned_data.get('text'), is_sender_customer=False)
answer_message.answer = answer
answer_message.contractor_or_team = answer.author
answer_message.save()
messages.info(request, 'Отклик успешно размещён') messages.info(request, 'Отклик успешно размещён')
redirect_to = request.POST.get('next') redirect_to = request.POST.get('next')
return redirect(redirect_to) return redirect(redirect_to)
@ -127,6 +132,36 @@ class ProjectDetailWithContractorAnswerView(BaseMixin, View):
return HttpResponseForbidden('403 Forbidden') return HttpResponseForbidden('403 Forbidden')
class ProjectAnswerCreateMessageView(BaseMixin, View):
form_class = ProjectAnswerMessageForm
def dispatch(self, request, *args, **kwargs):
if request.user.is_authenticated():
return super().dispatch(request, *args, **kwargs)
else:
return HttpResponseForbidden('403 Forbidden')
def post(self, request, *args, **kwargs):
form = self.form_class(request.POST, request=request)
if form.is_valid():
# project = form.save(commit=False)
# project.customer = request.user
# project.save()
# form.save_m2m()
messages.info(request, 'OK')
else:
if form.errors:
messages.info(request, (
'<p>Произошла ошибка (form)</p>'
'<pre>{form}</pre>'
).format(form=pformat(form.errors)))
redirect_to = request.POST.get('next')
return redirect(redirect_to)
class ProjectFilterView(BaseMixin, View): class ProjectFilterView(BaseMixin, View):
template_name = 'project_filter.html' template_name = 'project_filter.html'
form_class = ProjectFilterForm form_class = ProjectFilterForm
@ -216,7 +251,6 @@ class ProjectFilterView(BaseMixin, View):
'<pre>{realty_form}</pre>' '<pre>{realty_form}</pre>'
).format(realty_form=pformat(realty_form.errors))) ).format(realty_form=pformat(realty_form.errors)))
# import code; code.interact(local=dict(globals(), **locals()))
paginator = Paginator(projects.all(), settings.PAGE_SIZE) paginator = Paginator(projects.all(), settings.PAGE_SIZE)
page = request.GET.get('page') page = request.GET.get('page')
@ -260,8 +294,7 @@ class CustomerProjectCreateView(BaseMixin, View):
return render(request, self.template_name, context) return render(request, self.template_name, context)
def post(self, request, *args, **kwargs): def post(self, request, *args, **kwargs):
form = self.form_class(request.POST, form = self.form_class(request.POST, request=request) # Passing `request.FILES` seems unnecessary here. Files are added manually below
request=request) # Passing `request.FILES` seems unnecessary here. Files are added manually below
form.is_valid() form.is_valid()
realty = form.cleaned_data.get('realty') realty = form.cleaned_data.get('realty')
@ -356,8 +389,7 @@ class CustomerProjectEditView(BaseMixin, View):
if form.is_valid() and realty_form.is_valid(): if form.is_valid() and realty_form.is_valid():
project = form.save(commit=False) project = form.save(commit=False)
project.customer = request.user project.customer = request.user
project.files = form.cleaned_data.get( project.files = form.cleaned_data.get('files') # TODO: Should we somehow get rid of this explicit assignment?
'files') # TODO: Should we somehow get rid of this explicit assignment?
project.save() project.save()
form.save_m2m() form.save_m2m()
@ -559,9 +591,6 @@ class ContractorPortfolioUpdateView(UpdateView):
return reverse('proje') return reverse('proje')
from django.views.generic import DeleteView
class PortfolioDelete(DeleteView): class PortfolioDelete(DeleteView):
model = Portfolio model = Portfolio
success_url = reverse_lazy('users:contractor-profile') success_url = reverse_lazy('users:contractor-profile')

Loading…
Cancel
Save