#ARC-25 Add pipeline for add email

remotes/origin/setup
Mukhtar 10 years ago
parent 83ae308d97
commit 678d9b4fed
  1. 60
      archilance/settings/base.py
  2. 2
      archilance/urls.py
  3. 51
      projects/templates/project_list.html
  4. 7
      requirements/base.txt
  5. 1
      templates/registration/login.html
  6. 41
      templates/registration/registration_form.html
  7. 2
      users/admin.py
  8. 38
      users/migrations/0019_auto_20160708_1653.py
  9. 17
      users/models.py
  10. 27
      users/pipeline.py
  11. 5
      users/templates/add_email_form.html
  12. 10
      users/templates/portfolio_create_form.html
  13. 6
      work_sell/templates/upload.html
  14. 2
      work_sell/urls.py
  15. 10
      work_sell/views.py

@ -31,6 +31,7 @@ DJANGO_APPS = [
THIRD_PARTY_APPS = [ THIRD_PARTY_APPS = [
'django_extensions', 'django_extensions',
'social.apps.django_app.default',
'mptt', 'mptt',
'registration', 'registration',
'rest_framework', 'rest_framework',
@ -117,11 +118,67 @@ AUTH_PASSWORD_VALIDATORS = [
{'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator'}, {'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator'},
] ]
AUTHENTICATION_BACKENDS = ( AUTHENTICATION_BACKENDS = (
'social.backends.facebook.FacebookOAuth2',
'social.backends.google.GoogleOAuth2',
'social.backends.twitter.TwitterOAuth',
'social.backends.vk.VKOAuth2',
'social.backends.odnoklassniki.OdnoklassnikiOAuth2',
'django.contrib.auth.backends.ModelBackend', 'django.contrib.auth.backends.ModelBackend',
# 'guardian.backends.ObjectPermissionBackend',
) )
# SOCIAL_AUTH_FACEBOOK_KEY = '222531191461451'
# SOCIAL_AUTH_FACEBOOK_SECRET = '95e88f7ef396c5b803375f8476cf2ba4'
SOCIAL_AUTH_FACEBOOK_KEY = '1030546170341186'
SOCIAL_AUTH_FACEBOOK_SECRET = '1b22e95040b209c5d2f2d7f69462bf95'
SOCIAL_AUTH_FACEBOOK_SCOPE = ['email']
SOCIAL_AUTH_FACEBOOK_PROFILE_EXTRA_PARAMS = {
'fields': 'id,email',
}
SOCIAL_AUTH_ODNOKLASSNIKI_OAUTH2_KEY = '1247035904'
SOCIAL_AUTH_ODNOKLASSNIKI_OAUTH2_SECRET = '9AD83DB399405EEFAE7641BD'
SOCIAL_AUTH_ODNOKLASSNIKI_OAUTH2_PUBLIC_NAME = 'CBADEFFLEBABABABA'
SOCIAL_AUTH_GOOGLE_OAUTH2_KEY = '499898042244-bt7v18v4f46k8qg98n1ne8u2hjtmj0cn.apps.googleusercontent.com'
SOCIAL_AUTH_GOOGLE_OAUTH2_SECRET = 's69NCyhSlwY0OuGGT8_dFI7E'
SOCIAL_AUTH_TWITTER_KEY = 'YAe05K4IYYxHhA6J1mTOdDBjq'
SOCIAL_AUTH_TWITTER_SECRET = 'iRuYqRRaoGkCD4ip74NICb8FeZMxvM6MZ8HLMbm1jX99o7pcaL'
SOCIAL_AUTH_VK_OAUTH2_KEY = '5469025'
SOCIAL_AUTH_VK_OAUTH2_SECRET = '3Wild7HqYq6YFiLz9i7l'
SOCIAL_AUTH_VK_OAUTH2_SCOPE = [
'notify',
'friends',
'email',
]
SOCIAL_AUTH_LOGIN_REDIRECT_URL = '/'
SOCIAL_AUTH_NEW_USER_REDIRECT_URL = '/'
SOCIAL_AUTH_NEW_ASSOCIATION_REDIRECT_URL = '/'
SOCIAL_AUTH_PIPELINE = (
'social.pipeline.social_auth.social_details',
'social.pipeline.social_auth.social_uid',
'social.pipeline.social_auth.auth_allowed',
'social.pipeline.social_auth.social_user',
'social.pipeline.user.get_username',
'users.pipeline.add_email_for_user',
'users.pipeline.test_contractor',
'social.pipeline.mail.mail_validation',
'social.pipeline.user.create_user',
'social.pipeline.social_auth.associate_user',
'social.pipeline.social_auth.load_extra_data',
'social.pipeline.user.user_details',
)
FIELDS_STORED_IN_SESSION = ['user_type']
# Internationalization # Internationalization
# https://docs.djangoproject.com/en/1.9/topics/i18n/ # https://docs.djangoproject.com/en/1.9/topics/i18n/
@ -155,6 +212,7 @@ ACCOUNT_ACTIVATION_DAYS = 7
REGISTRATION_AUTO_LOGIN = True REGISTRATION_AUTO_LOGIN = True
LOGIN_REDIRECT_URL = '/projects/' LOGIN_REDIRECT_URL = '/projects/'
if DEBUG: if DEBUG:
EMAIL_BACKEND = 'django.core.mail.backends.dummy.EmailBackend' EMAIL_BACKEND = 'django.core.mail.backends.dummy.EmailBackend'

@ -9,12 +9,14 @@ from .views import HomeTemplateView, TestChatTemplateView
urlpatterns = [ urlpatterns = [
url(r'^$', HomeTemplateView.as_view()), url(r'^$', HomeTemplateView.as_view()),
url('', include('social.apps.django_app.urls', namespace='social')),
url(r'^chattest$', TestChatTemplateView.as_view()), url(r'^chattest$', TestChatTemplateView.as_view()),
url(r'^work_sell/', include('work_sell.urls')), url(r'^work_sell/', include('work_sell.urls')),
url(r'^test/$', TemplateView.as_view(template_name='test.html'), name='test'), url(r'^test/$', TemplateView.as_view(template_name='test.html'), name='test'),
url(r'^projects/', include('projects.urls')), url(r'^projects/', include('projects.urls')),
url(r'^chat/', include('chat.urls')), url(r'^chat/', include('chat.urls')),
url(r'^specializations/', include('specializations.urls')), url(r'^specializations/', include('specializations.urls')),
url(r'^users/', include('registration.backends.default.urls')), url(r'^users/', include('registration.backends.default.urls')),
url(r'^users/', include('users.urls')), url(r'^users/', include('users.urls')),
url(r'^admin/', admin.site.urls), url(r'^admin/', admin.site.urls),

@ -12,33 +12,26 @@
<div class="filter clearfix"> <div class="filter clearfix">
<div class="triangle1"></div> <div class="triangle1"></div>
<div class="titleF1 disTab"> <div class="titleF1 disTab">
<div class="col-lg-3">Тип работ:</div>
<div class="col-lg-3">Специализации:</div> <div class="col-lg-3">Специализации:</div>
<div class="col-lg-3"></div> <div class="col-lg-3"></div>
<div class="col-lg-3"></div> <div class="col-lg-3"></div>
<div class="col-lg-3"></div>
</div> </div>
<div class="polsF1 disTab"> <div class="polsF1 disTab">
<div class="col-lg-3"> <div class="col-lg-3">
<select class="selectpicker"> <input type='hidden' class="-spec-select -spec-select-level-1" style="width: 100%">
<option>Mustard</option> </div>
</select> <div class="col-lg-3">
</div> <input type='hidden' class="-spec-select -spec-select-level-2" style="width: 100%">
<div class="col-lg-3"> </div>
<select class="selectpicker"> <div class="col-lg-3">
<option>Mustard</option> <input type='hidden' class="-spec-select -spec-select-level-3" style="width: 100%">
</select> </div>
</div> <div class="col-lg-3">
<div class="col-lg-3"> <input type='hidden' class="-spec-select -spec-select-level-4" style="width: 100%">
<select class="selectpicker"> </div>
<option>Mustard</option>
</select> </div>
</div>
<div class="col-lg-3">
<select class="selectpicker">
<option>Mustard</option>
</select>
</div>
</div>
<div class="searchF1"> <div class="searchF1">
<div class="col-lg-6"> <div class="col-lg-6">
<input type="text" class="searchInp box-sizing" placeholder="Ключевые слова" name="search"> <input type="text" class="searchInp box-sizing" placeholder="Ключевые слова" name="search">
@ -67,30 +60,28 @@
</div> </div>
<div class="slideRes disTab activeSlide"> <div class="slideRes disTab activeSlide">
<div class="titleF1 disTab"> <div class="titleF1 disTab">
<div class="col-lg-3">Тип работ:</div> <div class="col-lg-3">Классификация здания</div>
<div class="col-lg-3">Специализации:</div> <div class="col-lg-3">Вид строительства</div>
<div class="col-lg-3"></div> <div class="col-lg-3">Местоположение</div>
<div class="col-lg-3"></div> <div class="col-lg-3"></div>
</div> </div>
<div class="polsF1 disTab"> <div class="polsF1 disTab">
<div class="col-lg-3"> <div class="col-lg-3">
<select class="selectpicker"> <select class="selectpicker">
<option>Mustard</option> <option></option>
</select> </select>
</div> </div>
<div class="col-lg-3"> <div class="col-lg-3">
<select class="selectpicker"> <select class="selectpicker">
<option>Mustard</option>
</select> </select>
</div> </div>
<div class="col-lg-3"> <div class="col-lg-3">
<select class="selectpicker"> <select class="selectpicker">
<option>Mustard</option>
</select> </select>
</div> </div>
<div class="col-lg-3"> <div class="col-lg-3">
<select class="selectpicker"> <select class="selectpicker">
<option>Mustard</option>
</select> </select>
</div> </div>
</div> </div>

@ -1,8 +1,10 @@
Django==1.9.6 Django==1.9.6
Momoko==2.2.3 Momoko==2.2.3
Pillow==3.2.0 Pillow==3.2.0
PyJWT==1.4.0
Werkzeug==0.11.10 Werkzeug==0.11.10
backports-abc==0.4 backports-abc==0.4
defusedxml==0.4.1
django-appconf==1.0.2 django-appconf==1.0.2
django-compressor==2.0 django-compressor==2.0
django-debug-toolbar==1.4 django-debug-toolbar==1.4
@ -17,12 +19,16 @@ djangorestframework==3.3.3
djangorestframework-filters==0.8.0 djangorestframework-filters==0.8.0
fake-factory==0.5.7 fake-factory==0.5.7
jsonschema==2.5.1 jsonschema==2.5.1
oauthlib==1.1.2
psycopg2==2.6.1 psycopg2==2.6.1
pydash==3.4.3 pydash==3.4.3
python-dateutil==2.5.3 python-dateutil==2.5.3
python-social-auth==0.2.19
python3-openid==3.0.10
rcssmin==1.0.6 rcssmin==1.0.6
redis==2.10.5 redis==2.10.5
requests==2.10.0 requests==2.10.0
requests-oauthlib==0.6.1
rjsmin==1.0.12 rjsmin==1.0.12
six==1.10.0 six==1.10.0
sorl-thumbnail==12.3 sorl-thumbnail==12.3
@ -30,3 +36,4 @@ sqlparse==0.1.19
tornado==4.3 tornado==4.3

@ -5,6 +5,7 @@
<p class="titleScore">Вход на сайт</p> <p class="titleScore">Вход на сайт</p>
</div> </div>
<div class="form-regestration"> <div class="form-regestration">
{{ form.errors }}
<form method="post">{% csrf_token %} <form method="post">{% csrf_token %}
<div class="col-lg-12 select-reg"> <div class="col-lg-12 select-reg">
<input type="text" name="{{ form.username.name }}" class="box-sizing email-reg" placeholder="Электронная почта"> <input type="text" name="{{ form.username.name }}" class="box-sizing email-reg" placeholder="Электронная почта">

@ -1,5 +1,6 @@
{% extends 'partials/base.html' %} {% extends 'partials/base.html' %}
{% block content %} {% block content %}
{% include 'partials/header.html' %}
<div class="col-lg-12"> <div class="col-lg-12">
<p class="titleScore">Регистрация </p> <p class="titleScore">Регистрация </p>
</div> </div>
@ -14,6 +15,9 @@
{% endif %} {% endif %}
</div> </div>
<div class="col-lg-12 select-reg"> <div class="col-lg-12 select-reg">
<input type="text" name="{{ form.username.name }}" class="box-sizing email-reg" placeholder="Nickname">
</div>
<div class="col-lg-12 select-reg">
<input type="text" name="{{ form.email.name }}" class="box-sizing email-reg" placeholder="Электронная почта"> <input type="text" name="{{ form.email.name }}" class="box-sizing email-reg" placeholder="Электронная почта">
</div> </div>
<div class="col-lg-12 select-reg"> <div class="col-lg-12 select-reg">
@ -26,6 +30,43 @@
<div class="col-lg-12 select-reg"> <div class="col-lg-12 select-reg">
<button class="reg-sub">Зарегистрироваться</button> <button class="reg-sub">Зарегистрироваться</button>
</div> </div>
<div class="col-lg-12">
<div class="col-xs-12 text-center">
<div class="btn-group" role="group">
<div class="pull-left -social -fb">
<a href="{% url 'social:begin' 'facebook' %}?user_type=contractor">
<img src="http://nepesh.com/static/img/social/fb.png" alt="fb">
</a>
</div>
<div class="pull-left -social -tw">
<a href="{% url 'social:begin' 'twitter' %}">
<img src="http://nepesh.com/static/img/social/tw.png" alt="tw">
</a>
</div>
<div class="pull-left -social -gplus">
<a href="{% url 'social:begin' 'google-oauth2' %}">
<img src="http://nepesh.com/static/img/social/gplus.png" alt="gplus">
</a>
</div>
<div class="pull-left -social -vk">
<a href="{% url 'social:begin' 'vk-oauth2' %}">
<img src="http://nepesh.com/static/img/social/vk.png" alt="vk">
</a>
</div>
<div class="pull-left -social -ok">
<a href="{% url 'social:begin' 'odnoklassniki-oauth2' %}">
<img src="http://nepesh.com/static/img/social/ok.gif" alt="yt">
</a>
</div>
</div>
</div>
</div>
<div class="col-lg-12 select-reg"> <div class="col-lg-12 select-reg">
<div class="check-reg"> <div class="check-reg">
<label><input type="checkbox" name="check-reg"><span></span></label> <label><input type="checkbox" name="check-reg"><span></span></label>

@ -5,7 +5,7 @@ from .models import User, Team, ContractorFinancialInfo
class UserAdmin(admin.ModelAdmin): class UserAdmin(admin.ModelAdmin):
readonly_fields = ('pk',) readonly_fields = ('pk',)
list_display = ('email', 'get_groups', 'cro', 'is_active',) list_display = ('username', 'email', 'get_groups', 'cro', 'is_active',)
def get_groups(self, obj): def get_groups(self, obj):
return ', '.join(g.name for g in obj.groups.all()) return ', '.join(g.name for g in obj.groups.all())

@ -0,0 +1,38 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.6 on 2016-07-08 13:53
from __future__ import unicode_literals
import datetime
from django.db import migrations, models
import django.utils.timezone
from django.utils.timezone import utc
class Migration(migrations.Migration):
dependencies = [
('users', '0018_auto_20160630_1846'),
]
operations = [
# migrations.RemoveField(
# model_name='user',
# name='nickname',
# ),
# migrations.AddField(
# model_name='user',
# name='data_joined',
# field=models.DateTimeField(default=django.utils.timezone.now),
# ),
# migrations.AddField(
# model_name='user',
# name='username',
# field=models.CharField(default=datetime.datetime(2016, 7, 8, 13, 53, 51, 625003, tzinfo=utc), max_length=50, unique=True),
# preserve_default=False,
# ),
migrations.AlterField(
model_name='user',
name='date_of_birth',
field=models.DateTimeField(blank=True, null=True),
),
]

@ -8,17 +8,19 @@ from specializations.models import Specialization
class UserManager(BaseUserManager): class UserManager(BaseUserManager):
def create_user(self, email, password=None): def create_user(self, username, email, password=None, **kwargs):
# import code; code.interact(local=dict(globals(), **locals()))
if not email: if not email:
raise ValueError('Users must have an email address') raise ValueError('Users must have an email address')
user = self.model(email=UserManager.normalize_email(email),) user = self.model(username=username,
email=UserManager.normalize_email(email),)
user.set_password(password) user.set_password(password)
user.save(using=self._db) user.save(using=self._db)
return user return user
def create_superuser(self, email, password): def create_superuser(self, username, password):
user = self.create_user(email, password) user = self.create_user(username, "admin@exampletest.com", password)
user.is_superuser = True user.is_superuser = True
user.save(using=self._db) user.save(using=self._db)
return user return user
@ -81,13 +83,14 @@ class User(AbstractBaseUser, PermissionsMixin):
('busy', 'Занят'), ('busy', 'Занят'),
) )
nickname = models.CharField(max_length=50, blank=True,null=True) username = models.CharField(max_length=50, unique=True)
first_name = models.CharField(max_length=255, blank=True) first_name = models.CharField(max_length=255, blank=True)
last_name = models.CharField(max_length=255, blank=True) last_name = models.CharField(max_length=255, blank=True)
patronym = models.CharField(max_length=255, blank=True) patronym = models.CharField(max_length=255, blank=True)
email = models.EmailField(max_length=255, unique=True, db_index=True) email = models.EmailField(max_length=255, unique=True, db_index=True)
is_active = models.BooleanField(default=True) is_active = models.BooleanField(default=True)
created = models.DateTimeField(default=timezone.now) created = models.DateTimeField(default=timezone.now)
data_joined = models.DateTimeField(default=timezone.now)
last_time_visit = models.DateTimeField(default=timezone.now) last_time_visit = models.DateTimeField(default=timezone.now)
contractor_specializations = TreeManyToManyField(Specialization, related_name='contractors', blank=True) contractor_specializations = TreeManyToManyField(Specialization, related_name='contractors', blank=True)
contractor_status = models.CharField(default='free', max_length=20, choices=STATUSES) contractor_status = models.CharField(default='free', max_length=20, choices=STATUSES)
@ -97,7 +100,7 @@ class User(AbstractBaseUser, PermissionsMixin):
gender = models.CharField(max_length=30, choices=GENDERS, blank=True) gender = models.CharField(max_length=30, choices=GENDERS, blank=True)
cro = models.BooleanField(default=False) cro = models.BooleanField(default=False)
website = models.CharField(max_length=255, blank=True) website = models.CharField(max_length=255, blank=True)
date_of_birth = models.DateTimeField() date_of_birth = models.DateTimeField(null=True,blank=True)
avatar = models.ImageField(upload_to='users/avatars/', blank=True) avatar = models.ImageField(upload_to='users/avatars/', blank=True)
phone = models.CharField(max_length=30, blank=True, null=True) phone = models.CharField(max_length=30, blank=True, null=True)
@ -121,7 +124,7 @@ class User(AbstractBaseUser, PermissionsMixin):
def get_profile_image(self): def get_profile_image(self):
return self.avatar return self.avatar
USERNAME_FIELD = 'email' USERNAME_FIELD = 'username'
REQUIRED_FIELDS = [] REQUIRED_FIELDS = []
objects = UserManager() objects = UserManager()
contractor_objects = ContractorUserManager() contractor_objects = ContractorUserManager()

@ -0,0 +1,27 @@
from django.shortcuts import redirect, render_to_response
from social.pipeline.partial import partial
@partial
def test_contractor(backend, details, response, is_new=False, *args, **kwargs):
import code; code.interact(local=dict(globals(), **locals()))
@partial
def add_email_for_user(backend, details, response, is_new=False, *args, **kwargs):
data = backend.strategy.request_data()
if details.get('contractor') is None:
return render_to_response('add_email_form.html')
else:
return {'contractor': details.get('contractor')}
@partial
def require_email(strategy, details, user=None, is_new=False, *args, **kwargs):
if kwargs.get('ajax') or user and user.email:
return
elif is_new and not details.get('email'):
email = strategy.request_data().get('email')
if email:
details['email'] = email
else:
return redirect('require_email')

@ -0,0 +1,5 @@
<h1>Введите свой email</h1>
<form method="post">
<input type="text" name="contractor">
<input type="submit" value="Send">
</form>

@ -40,10 +40,10 @@
<div class="textAreaBlock2 text-nn box-sizing disTab"> <div class="textAreaBlock2 text-nn box-sizing disTab">
<p>Бюджет{{ portfolio_form.budget.errors.as_text }}</p> <p>Бюджет{{ portfolio_form.budget.errors.as_text }}</p>
<div class="row"> <div class="row">
<div class="col-lg-8"> <div class="col-lg-6">
<input type="text" class="box-sizing" name="{{ form.budget.html_name }}" value="{{ form.budget.value }}"> <input type="text" class="box-sizing" name="{{ form.budget.html_name }}" value="{{ form.budget.value }}">
</div> </div>
<div class="col-lg-4"> <div class="col-lg-6">
{{ portfolio_form.currency}} {{ portfolio_form.currency}}
</div> </div>
</div> </div>
@ -52,10 +52,10 @@
<div class="textAreaBlock2 text-nn box-sizing disTab"> <div class="textAreaBlock2 text-nn box-sizing disTab">
<p>Срок выполнения{{ portfolio_form.budget.errors.as_text }}</p> <p>Срок выполнения{{ portfolio_form.budget.errors.as_text }}</p>
<div class="row"> <div class="row">
<div class="col-lg-8"> <div class="col-lg-6">
<input type="text" class="box-sizing" name="{{ form.budget.html_name }}" value="{{ form.budget.value }}"> <input type="text" class="box-sizing" name="{{ form.budget.html_name }}" value="{{ form.budget.value }}">
</div> </div>
<div class="col-lg-4"> <div class="col-lg-6">
{{ portfolio_form.term_type }} {{ portfolio_form.term_type }}
</div> </div>
</div> </div>
@ -73,7 +73,7 @@
</div> </div>
<div class="polsF1 polsF2 disTab"> <div class="polsF1 polsF2 disTab">
<input type="text" name="{{ portfolio_form.user.html_name }}" value="{{ request.user.pk }}" /> <input type="hidden" name="{{ portfolio_form.user.html_name }}" value="{{ request.user.pk }}" />
</div> </div>
<div class="polsF1 polsF2 disTab"> <div class="polsF1 polsF2 disTab">

@ -0,0 +1,6 @@
{% extends 'partials/base.html' %}
{% block content %}
<h1>Upload Files</h1>
{% endblock %}

@ -6,6 +6,7 @@ from .views import (
WorkSellCreateView, WorkSellCreateView,
WorkSellUpdateView, WorkSellUpdateView,
WorkSellDeleteView, WorkSellDeleteView,
UploadView,
work_sell_create, work_sell_create,
) )
@ -14,6 +15,7 @@ app_name = 'work_sell'
urlpatterns = [ urlpatterns = [
urls.url(r'^$', WorkSellsView.as_view(), name='list'), urls.url(r'^$', WorkSellsView.as_view(), name='list'),
urls.url(r'^create/$', WorkSellCreateView.as_view(), name='create'), urls.url(r'^create/$', WorkSellCreateView.as_view(), name='create'),
urls.url(r'^upload/$', UploadView.as_view(), name='upload'),
urls.url(r'^(?P<pk>\d+)/edit/$',WorkSellUpdateView.as_view(), name='edit'), urls.url(r'^(?P<pk>\d+)/edit/$',WorkSellUpdateView.as_view(), name='edit'),
urls.url(r'^(?P<pk>\d+)/delete/$',WorkSellDeleteView.as_view(), name='delete'), urls.url(r'^(?P<pk>\d+)/delete/$',WorkSellDeleteView.as_view(), name='delete'),
urls.url(r'^test/$', work_sell_create, name='test'), urls.url(r'^test/$', work_sell_create, name='test'),

@ -2,7 +2,8 @@ import json
from django.shortcuts import render from django.shortcuts import render
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.http import JsonResponse, HttpResponse from django.http import JsonResponse, HttpResponse
from django.views.generic import ListView, DetailView, CreateView, UpdateView, DeleteView, TemplateView from django.views.generic import ListView, DetailView, CreateView, View,\
UpdateView, DeleteView, TemplateView
from projects.models import BuildingClassfication, ConstructionType from projects.models import BuildingClassfication, ConstructionType
from .models import WorkSell from .models import WorkSell
@ -75,6 +76,13 @@ class WorkSellDeleteView(DeleteView):
return reverse('work_sell:list') return reverse('work_sell:list')
class UploadView(View):
template_name = 'upload.html'
def get(self, request, *args, **kwargs):
return render(request,self.template_name)
class JSONResponseMixin(object): class JSONResponseMixin(object):
def render_to_json_response(self, context, **response_kwargs): def render_to_json_response(self, context, **response_kwargs):
return JsonResponse( return JsonResponse(

Loading…
Cancel
Save