mirror of
https://github.com/OpenBankProject/API-Manager.git
synced 2026-02-06 13:06:45 +00:00
Added app to create customers #25
This commit is contained in:
parent
374ff8e016
commit
a38cd9e5b3
@ -48,6 +48,7 @@ INSTALLED_APPS = [
|
||||
'oauth',
|
||||
'consumers',
|
||||
'users',
|
||||
'customers',
|
||||
'metrics',
|
||||
#'api_config',
|
||||
]
|
||||
@ -167,6 +168,14 @@ LOGGING = {
|
||||
'handlers': ['console'],
|
||||
'level': 'INFO',
|
||||
},
|
||||
'customers': {
|
||||
'handlers': ['console'],
|
||||
'level': 'INFO',
|
||||
},
|
||||
'metrics': {
|
||||
'handlers': ['console'],
|
||||
'level': 'INFO',
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@ -13,6 +13,7 @@ urlpatterns = [
|
||||
url(r'^oauth/', include('oauth.urls')),
|
||||
url(r'^consumers/', include('consumers.urls')),
|
||||
url(r'^users/', include('users.urls')),
|
||||
url(r'^customers/', include('customers.urls')),
|
||||
url(r'^metrics/', include('metrics.urls')),
|
||||
#url(r'^api_config/', include('api_config.urls')),
|
||||
]
|
||||
|
||||
@ -31,6 +31,8 @@
|
||||
<li{% if consumers_index_url in request.path %} class="active"{% endif %}><a href="{{ consumers_index_url }}">Consumers</a></li>
|
||||
{% url "users-index" as users_index_url %}
|
||||
<li{% if users_index_url in request.path %} class="active"{% endif %}><a href="{{ users_index_url }}">Users</a></li>
|
||||
{% url "customers-create" as customers_create_url %}
|
||||
<li{% if customers_create_url in request.path %} class="active"{% endif %}><a href="{{ customers_create_url }}">Customers</a></li>
|
||||
{% url "metrics-index" as metrics_index_url %}
|
||||
<li{% if metrics_index_url in request.path %} class="active"{% endif %}><a href="{{ metrics_index_url }}">Metrics</a></li>
|
||||
{% comment %}
|
||||
|
||||
0
apimanager/customers/__init__.py
Normal file
0
apimanager/customers/__init__.py
Normal file
5
apimanager/customers/apps.py
Normal file
5
apimanager/customers/apps.py
Normal file
@ -0,0 +1,5 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class CustomersConfig(AppConfig):
|
||||
name = 'customers'
|
||||
216
apimanager/customers/forms.py
Normal file
216
apimanager/customers/forms.py
Normal file
@ -0,0 +1,216 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Forms of customers app
|
||||
"""
|
||||
|
||||
from django import forms
|
||||
|
||||
DATETIME_INPUT_FORMAT = '%Y-%m-%dT%H:%M:%SZ'
|
||||
|
||||
|
||||
class CreateCustomerForm(forms.Form):
|
||||
bank_id = forms.ChoiceField(
|
||||
label='Bank',
|
||||
widget=forms.Select(
|
||||
attrs={
|
||||
'class': 'form-control',
|
||||
}
|
||||
),
|
||||
choices=[],
|
||||
)
|
||||
user_id = forms.ChoiceField(
|
||||
label='User',
|
||||
widget=forms.Select(
|
||||
attrs={
|
||||
'class': 'form-control',
|
||||
}
|
||||
),
|
||||
choices=[],
|
||||
)
|
||||
customer_number = forms.CharField(
|
||||
label='Customer Number',
|
||||
widget=forms.TextInput(
|
||||
attrs={
|
||||
'placeholder': 'new customer number, e.g. 687687678',
|
||||
'class': 'form-control',
|
||||
}
|
||||
),
|
||||
)
|
||||
legal_name = forms.CharField(
|
||||
label='Legal Name',
|
||||
widget=forms.TextInput(
|
||||
attrs={
|
||||
'placeholder': 'NONE',
|
||||
'class': 'form-control',
|
||||
}
|
||||
),
|
||||
required=False,
|
||||
)
|
||||
mobile_phone_number = forms.CharField(
|
||||
label='Mobile Phone Number',
|
||||
widget=forms.TextInput(
|
||||
attrs={
|
||||
'placeholder': '+49 123 456 78 90 12',
|
||||
'class': 'form-control',
|
||||
}
|
||||
),
|
||||
required=False,
|
||||
)
|
||||
email = forms.CharField(
|
||||
label='Email',
|
||||
widget=forms.TextInput(
|
||||
attrs={
|
||||
'placeholder': 'person@example.com',
|
||||
'class': 'form-control',
|
||||
}
|
||||
),
|
||||
required=False,
|
||||
)
|
||||
face_image_url = forms.CharField(
|
||||
label='Face Image URL',
|
||||
widget=forms.TextInput(
|
||||
attrs={
|
||||
'placeholder': 'https://static.openbankproject.com/images/OBP/favicon.png',
|
||||
'class': 'form-control',
|
||||
}
|
||||
),
|
||||
required=False,
|
||||
)
|
||||
face_image_date = forms.DateTimeField(
|
||||
label='Face Image Date',
|
||||
input_formats=[DATETIME_INPUT_FORMAT],
|
||||
widget=forms.DateTimeInput(
|
||||
attrs={
|
||||
'placeholder': '2013-01-22T00:08:00Z',
|
||||
'class': 'form-control',
|
||||
}
|
||||
),
|
||||
required=True,
|
||||
)
|
||||
date_of_birth = forms.DateTimeField(
|
||||
label='Date of Birth',
|
||||
input_formats=[DATETIME_INPUT_FORMAT],
|
||||
widget=forms.DateTimeInput(
|
||||
attrs={
|
||||
'placeholder': '2013-01-22T00:08:00Z',
|
||||
'class': 'form-control',
|
||||
}
|
||||
),
|
||||
required=True,
|
||||
)
|
||||
relationship_status = forms.CharField(
|
||||
label='Relationship Status',
|
||||
widget=forms.TextInput(
|
||||
attrs={
|
||||
'placeholder': 'Single',
|
||||
'class': 'form-control',
|
||||
}
|
||||
),
|
||||
required=False,
|
||||
)
|
||||
dependants = forms.IntegerField(
|
||||
label='Dependants',
|
||||
widget=forms.TextInput(
|
||||
attrs={
|
||||
'placeholder': '0',
|
||||
'class': 'form-control',
|
||||
}
|
||||
),
|
||||
initial=0,
|
||||
required=True,
|
||||
)
|
||||
dob_of_dependants = forms.CharField(
|
||||
label='Date of Birth of Dependants',
|
||||
widget=forms.TextInput(
|
||||
attrs={
|
||||
'placeholder': '2013-01-22T00:08:00Z, 2010-01-22T00:08:00Z',
|
||||
'class': 'form-control',
|
||||
}
|
||||
),
|
||||
required=False,
|
||||
)
|
||||
credit_rating_rating = forms.CharField(
|
||||
label='Credit Rating (Rating)',
|
||||
widget=forms.TextInput(
|
||||
attrs={
|
||||
'placeholder': 'OBP',
|
||||
'class': 'form-control',
|
||||
}
|
||||
),
|
||||
required=False,
|
||||
)
|
||||
credit_rating_source = forms.CharField(
|
||||
label='Credit Rating (Source)',
|
||||
widget=forms.TextInput(
|
||||
attrs={
|
||||
'placeholder': 'OBP',
|
||||
'class': 'form-control',
|
||||
}
|
||||
),
|
||||
required=False,
|
||||
)
|
||||
credit_limit_currency = forms.CharField(
|
||||
label='Credit Limit (Currency)',
|
||||
widget=forms.TextInput(
|
||||
attrs={
|
||||
'placeholder': 'EUR',
|
||||
'class': 'form-control',
|
||||
}
|
||||
),
|
||||
required=False,
|
||||
)
|
||||
credit_limit_amount = forms.CharField(
|
||||
label='Credit Limit (Amount)',
|
||||
widget=forms.TextInput(
|
||||
attrs={
|
||||
'placeholder': '10',
|
||||
'class': 'form-control',
|
||||
}
|
||||
),
|
||||
required=False,
|
||||
)
|
||||
highest_education_attained = forms.CharField(
|
||||
label='Highest Education Attained',
|
||||
widget=forms.TextInput(
|
||||
attrs={
|
||||
'placeholder': 'Bachelor’s Degree',
|
||||
'class': 'form-control',
|
||||
}
|
||||
),
|
||||
required=False,
|
||||
)
|
||||
employment_status = forms.CharField(
|
||||
label='Employment Status',
|
||||
widget=forms.TextInput(
|
||||
attrs={
|
||||
'placeholder': 'Employed',
|
||||
'class': 'form-control',
|
||||
}
|
||||
),
|
||||
required=False,
|
||||
)
|
||||
kyc_status = forms.BooleanField(
|
||||
label='KYC Status',
|
||||
widget=forms.CheckboxInput(
|
||||
attrs={
|
||||
'class': 'form-control',
|
||||
}
|
||||
),
|
||||
initial=True,
|
||||
required=False,
|
||||
)
|
||||
last_ok_date = forms.DateTimeField(
|
||||
label='Last OK Date',
|
||||
input_formats=[DATETIME_INPUT_FORMAT],
|
||||
widget=forms.DateTimeInput(
|
||||
attrs={
|
||||
'placeholder': '2013-01-22T00:08:00Z',
|
||||
'class': 'form-control',
|
||||
}
|
||||
),
|
||||
required=True,
|
||||
)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
kwargs.setdefault('label_suffix', '')
|
||||
super(CreateCustomerForm, self).__init__(*args, **kwargs)
|
||||
8
apimanager/customers/static/customers/css/customers.css
Normal file
8
apimanager/customers/static/customers/css/customers.css
Normal file
@ -0,0 +1,8 @@
|
||||
#customers {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
input#id_kyc_status {
|
||||
width: auto;
|
||||
margin: -4px 0;
|
||||
}
|
||||
2
apimanager/customers/static/customers/js/customers.js
Normal file
2
apimanager/customers/static/customers/js/customers.js
Normal file
@ -0,0 +1,2 @@
|
||||
$(document).ready(function($) {
|
||||
});
|
||||
201
apimanager/customers/templates/customers/create.html
Normal file
201
apimanager/customers/templates/customers/create.html
Normal file
@ -0,0 +1,201 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load static %}
|
||||
|
||||
{% block page_title %}{{ block.super }} / Customers{% endblock page_title %}
|
||||
|
||||
|
||||
{% block content %}
|
||||
<div id="customers">
|
||||
<h1>Create Customer</h1>
|
||||
|
||||
<form action="{% url 'customers-create' %}" method="post">
|
||||
{% csrf_token %}
|
||||
{% if form.non_field_errors %}
|
||||
<div class="alert alert-danger">
|
||||
{{ form.non_field_errors }}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="row">
|
||||
<div class="col-xs-12 col-sm-4">
|
||||
{% if form.bank_id.errors %}<div class="alert alert-danger">{{ form.bank_id.errors }}</div>{% endif %}
|
||||
<div class="form-group">
|
||||
{{ form.bank_id.label_tag }}
|
||||
{{ form.bank_id }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-4">
|
||||
{% if form.user_id.errors %}<div class="alert alert-danger">{{ form.user_id.errors }}</div>{% endif %}
|
||||
<div class="form-group">
|
||||
{{ form.user_id.label_tag }}
|
||||
{{ form.user_id }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-4">
|
||||
{% if form.customer_number.errors %}<div class="alert alert-danger">{{ form.customer_number.errors }}</div>{% endif %}
|
||||
<div class="form-group">
|
||||
{{ form.customer_number.label_tag }}
|
||||
{{ form.customer_number }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-xs-12 col-sm-4">
|
||||
{% if form.legal_name.errors %}<div class="alert alert-danger">{{ form.legal_name.errors }}</div>{% endif %}
|
||||
<div class="form-group">
|
||||
{{ form.legal_name.label_tag }}
|
||||
{{ form.legal_name }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-4">
|
||||
{% if form.mobile_phone_number.errors %}<div class="alert alert-danger">{{ form.mobile_phone_number.errors }}</div>{% endif %}
|
||||
<div class="form-group">
|
||||
{{ form.mobile_phone_number.label_tag }}
|
||||
{{ form.mobile_phone_number }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-4">
|
||||
{% if form.email.errors %}<div class="alert alert-danger">{{ form.email.errors }}</div>{% endif %}
|
||||
<div class="form-group">
|
||||
{{ form.email.label_tag }}
|
||||
{{ form.email }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-xs-12 col-sm-6">
|
||||
{% if form.face_image_url.errors %}<div class="alert alert-danger">{{ form.face_image_url.errors }}</div>{% endif %}
|
||||
<div class="form-group">
|
||||
{{ form.face_image_url.label_tag }}
|
||||
{{ form.face_image_url }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-6">
|
||||
{% if form.face_image_date.errors %}<div class="alert alert-danger">{{ form.face_image_date.errors }}</div>{% endif %}
|
||||
<div class="form-group">
|
||||
{{ form.face_image_date.label_tag }}
|
||||
{{ form.face_image_date }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-xs-12 col-sm-6">
|
||||
{% if form.date_of_birth.errors %}<div class="alert alert-danger">{{ form.date_of_birth.errors }}</div>{% endif %}
|
||||
<div class="form-group">
|
||||
{{ form.date_of_birth.label_tag }}
|
||||
{{ form.date_of_birth }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-6">
|
||||
{% if form.relationship_status.errors %}<div class="alert alert-danger">{{ form.relationship_status.errors }}</div>{% endif %}
|
||||
<div class="form-group">
|
||||
{{ form.relationship_status.label_tag }}
|
||||
{{ form.relationship_status }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-xs-12 col-sm-6">
|
||||
{% if form.dependants.errors %}<div class="alert alert-danger">{{ form.dependants.errors }}</div>{% endif %}
|
||||
<div class="form-group">
|
||||
{{ form.dependants.label_tag }}
|
||||
{{ form.dependants }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-6">
|
||||
{% if form.dob_of_dependants.errors %}<div class="alert alert-danger">{{ form.dob_of_dependants.errors }}</div>{% endif %}
|
||||
<div class="form-group">
|
||||
{{ form.dob_of_dependants.label_tag }}
|
||||
{{ form.dob_of_dependants }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-xs-12 col-sm-6 col-md-3">
|
||||
{% if form.credit_rating_rating.errors %}<div class="alert alert-danger">{{ form.credit_rating_rating.errors }}</div>{% endif %}
|
||||
<div class="form-group">
|
||||
{{ form.credit_rating_rating.label_tag }}
|
||||
{{ form.credit_rating_rating }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-6 col-md-3">
|
||||
{% if form.credit_rating_source.errors %}<div class="alert alert-danger">{{ form.credit_rating_source.errors }}</div>{% endif %}
|
||||
<div class="form-group">
|
||||
{{ form.credit_rating_source.label_tag }}
|
||||
{{ form.credit_rating_source }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-xs-12 col-sm-6 col-md-3">
|
||||
{% if form.credit_limit_currency.errors %}<div class="alert alert-danger">{{ form.credit_limit_currency.errors }}</div>{% endif %}
|
||||
<div class="form-group">
|
||||
{{ form.credit_limit_currency.label_tag }}
|
||||
{{ form.credit_limit_currency }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-6 col-md-3">
|
||||
{% if form.credit_limit_amount.errors %}<div class="alert alert-danger">{{ form.credit_limit_amount.errors }}</div>{% endif %}
|
||||
<div class="form-group">
|
||||
{{ form.credit_limit_amount.label_tag }}
|
||||
{{ form.credit_limit_amount }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-xs-12 col-sm-6">
|
||||
{% if form.highest_education_attained.errors %}<div class="alert alert-danger">{{ form.highest_education_attained.errors }}</div>{% endif %}
|
||||
<div class="form-group">
|
||||
{{ form.highest_education_attained.label_tag }}
|
||||
{{ form.highest_education_attained }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-6">
|
||||
{% if form.employment_status.errors %}<div class="alert alert-danger">{{ form.employment_status.errors }}</div>{% endif %}
|
||||
<div class="form-group">
|
||||
{{ form.employment_status.label_tag }}
|
||||
{{ form.employment_status }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-xs-12 col-sm-6">
|
||||
{% if form.kyc_status.errors %}<div class="alert alert-danger">{{ form.kyc_status.errors }}</div>{% endif %}
|
||||
<div class="form-group">
|
||||
{{ form.kyc_status.label_tag }}
|
||||
{{ form.kyc_status }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-12 col-sm-6">
|
||||
{% if form.last_ok_date.errors %}<div class="alert alert-danger">{{ form.last_ok_date.errors }}</div>{% endif %}
|
||||
<div class="form-group">
|
||||
{{ form.last_ok_date.label_tag }}
|
||||
{{ form.last_ok_date }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<input type="submit" value="Submit" class="btn btn-primary" />
|
||||
</form>
|
||||
</div>
|
||||
{% endblock content %}
|
||||
|
||||
|
||||
{% block extrajs %}
|
||||
{% comment %}
|
||||
<script type="text/javascript" src="{% static 'customers/js/customers.js' %}"></script>
|
||||
<script type="text/javascript">
|
||||
</script>
|
||||
{% endcomment %}
|
||||
{% endblock extrajs %}
|
||||
|
||||
|
||||
{% block extracss %}
|
||||
<link href="{% static 'customers/css/customers.css' %}" rel="stylesheet">
|
||||
{% endblock extracss %}
|
||||
14
apimanager/customers/urls.py
Normal file
14
apimanager/customers/urls.py
Normal file
@ -0,0 +1,14 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
URLs for customers app
|
||||
"""
|
||||
|
||||
from django.conf.urls import url
|
||||
|
||||
from .views import CreateView
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^$',
|
||||
CreateView.as_view(),
|
||||
name='customers-create'),
|
||||
]
|
||||
101
apimanager/customers/views.py
Normal file
101
apimanager/customers/views.py
Normal file
@ -0,0 +1,101 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Views of customers app
|
||||
"""
|
||||
|
||||
import datetime
|
||||
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.http import HttpResponseRedirect
|
||||
from django.urls import reverse_lazy
|
||||
from django.views.generic import FormView
|
||||
|
||||
from base.api import api, APIError
|
||||
|
||||
from .forms import CreateCustomerForm, DATETIME_INPUT_FORMAT
|
||||
|
||||
|
||||
class CreateView(LoginRequiredMixin, FormView):
|
||||
"""View to create a customer"""
|
||||
form_class = CreateCustomerForm
|
||||
template_name = 'customers/create.html'
|
||||
success_url = reverse_lazy('customers-create')
|
||||
|
||||
def get_bank_id_choices(self):
|
||||
choices = [('', 'Choose ...')]
|
||||
try:
|
||||
result = api.get(self.request, '/banks')
|
||||
for bank in result['banks']:
|
||||
choices.append((bank['id'], bank['short_name']))
|
||||
except APIError as err:
|
||||
messages.error(err)
|
||||
return choices
|
||||
|
||||
def get_user_id_choices(self):
|
||||
choices = [('', 'Choose ...')]
|
||||
try:
|
||||
result = api.get(self.request, '/users')
|
||||
for user in result['users']:
|
||||
choices.append((user['user_id'], user['username']))
|
||||
except APIError as err:
|
||||
messages.error(err)
|
||||
return choices
|
||||
|
||||
def get_form(self, *args, **kwargs):
|
||||
form = super(CreateView, self).get_form(*args, **kwargs)
|
||||
fields = form.fields
|
||||
fields['bank_id'].choices = self.get_bank_id_choices()
|
||||
fields['user_id'].choices = self.get_user_id_choices()
|
||||
fields['last_ok_date'].initial =\
|
||||
datetime.datetime.now().strftime(DATETIME_INPUT_FORMAT)
|
||||
return form
|
||||
|
||||
def form_valid(self, form):
|
||||
try:
|
||||
data = form.cleaned_data
|
||||
urlpath = '/banks/{}/customers'.format(data['bank_id'])
|
||||
if data['dob_of_dependants']:
|
||||
dob_of_dependants = data['dob_of_dependants'].split(',')
|
||||
else:
|
||||
dob_of_dependants = []
|
||||
payload = {
|
||||
'user_id': data['user_id'],
|
||||
'customer_number': data['customer_number'],
|
||||
'legal_name': data['legal_name'],
|
||||
'mobile_phone_number': data['mobile_phone_number'],
|
||||
'email': data['email'],
|
||||
'face_image': {
|
||||
'url': data['face_image_url'],
|
||||
'date':
|
||||
data['face_image_date'].strftime(DATETIME_INPUT_FORMAT),
|
||||
},
|
||||
'date_of_birth':
|
||||
data['date_of_birth'].strftime(DATETIME_INPUT_FORMAT),
|
||||
'relationship_status': data['relationship_status'],
|
||||
'dependants': data['dependants'],
|
||||
'dob_of_dependants': dob_of_dependants,
|
||||
'credit_rating': {
|
||||
'rating': data['credit_rating_rating'],
|
||||
'source': data['credit_rating_source'],
|
||||
},
|
||||
'credit_limit': {
|
||||
'currency': data['credit_limit_currency'],
|
||||
'amount': data['credit_limit_amount'],
|
||||
},
|
||||
'highest_education_attained':
|
||||
data['highest_education_attained'],
|
||||
'employment_status': data['employment_status'],
|
||||
'kyc_status': data['kyc_status'],
|
||||
'last_ok_date':
|
||||
data['last_ok_date'].strftime(DATETIME_INPUT_FORMAT),
|
||||
}
|
||||
result = api.post(self.request, urlpath, payload=payload)
|
||||
except APIError as err:
|
||||
messages.error(self.request, err)
|
||||
return super(CreateView, self).form_invalid(form)
|
||||
|
||||
msg = 'Customer number {} has been created successfully!'.format(
|
||||
result['customer_number'])
|
||||
messages.success(self.request, msg)
|
||||
return super(CreateView, self).form_valid(form)
|
||||
Loading…
Reference in New Issue
Block a user