Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
R
re2o
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
1
Merge Requests
1
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Incidents
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Nounous
re2o
Commits
a4d31005
Commit
a4d31005
authored
Nov 01, 2016
by
chirac
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Crée des statistiques générales de la bdd + model alias
parent
6af40d9e
Changes
15
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
206 additions
and
4 deletions
+206
-4
cotisations/models.py
cotisations/models.py
+12
-0
logs/templates/logs/aff_actions.html
logs/templates/logs/aff_actions.html
+3
-1
logs/templates/logs/aff_stats_models.html
logs/templates/logs/aff_stats_models.html
+17
-0
logs/templates/logs/delete.html
logs/templates/logs/delete.html
+16
-0
logs/templates/logs/sidebar.html
logs/templates/logs/sidebar.html
+1
-0
logs/templates/logs/stats_models.html
logs/templates/logs/stats_models.html
+12
-0
logs/urls.py
logs/urls.py
+2
-0
logs/views.py
logs/views.py
+62
-0
machines/admin.py
machines/admin.py
+5
-1
machines/forms.py
machines/forms.py
+10
-1
machines/migrations/0027_alias.py
machines/migrations/0027_alias.py
+22
-0
machines/models.py
machines/models.py
+21
-0
machines/views.py
machines/views.py
+1
-1
topologie/models.py
topologie/models.py
+8
-0
users/models.py
users/models.py
+14
-0
No files found.
cotisations/models.py
View file @
a4d31005
...
...
@@ -6,6 +6,8 @@ from dateutil.relativedelta import relativedelta
from
django.core.validators
import
MinValueValidator
class
Facture
(
models
.
Model
):
PRETTY_NAME
=
"Factures émises"
user
=
models
.
ForeignKey
(
'users.User'
,
on_delete
=
models
.
PROTECT
)
paiement
=
models
.
ForeignKey
(
'Paiement'
,
on_delete
=
models
.
PROTECT
)
banque
=
models
.
ForeignKey
(
'Banque'
,
on_delete
=
models
.
PROTECT
,
blank
=
True
,
null
=
True
)
...
...
@@ -40,6 +42,8 @@ def facture_post_delete(sender, **kwargs):
#user.ldap_sync(base=False, access_refresh=True, mac_refresh=False)
class
Vente
(
models
.
Model
):
PRETTY_NAME
=
"Ventes effectuées"
facture
=
models
.
ForeignKey
(
'Facture'
,
on_delete
=
models
.
CASCADE
)
number
=
models
.
IntegerField
(
validators
=
[
MinValueValidator
(
1
)])
name
=
models
.
CharField
(
max_length
=
255
)
...
...
@@ -74,6 +78,8 @@ def vente_post_delete(sender, **kwargs):
#user.ldap_sync(base=False, access_refresh=True, mac_refresh=False)
class
Article
(
models
.
Model
):
PRETTY_NAME
=
"Articles en vente"
name
=
models
.
CharField
(
max_length
=
255
)
prix
=
models
.
DecimalField
(
max_digits
=
5
,
decimal_places
=
2
)
iscotisation
=
models
.
BooleanField
()
...
...
@@ -83,18 +89,24 @@ class Article(models.Model):
return
self
.
name
class
Banque
(
models
.
Model
):
PRETTY_NAME
=
"Banques enregistrées"
name
=
models
.
CharField
(
max_length
=
255
)
def
__str__
(
self
):
return
self
.
name
class
Paiement
(
models
.
Model
):
PRETTY_NAME
=
"Moyens de paiement"
moyen
=
models
.
CharField
(
max_length
=
255
)
def
__str__
(
self
):
return
self
.
moyen
class
Cotisation
(
models
.
Model
):
PRETTY_NAME
=
"Cotisations"
vente
=
models
.
OneToOneField
(
'Vente'
,
on_delete
=
models
.
CASCADE
,
null
=
True
)
date_start
=
models
.
DateTimeField
()
date_end
=
models
.
DateTimeField
()
...
...
logs/templates/logs/aff_actions.html
View file @
a4d31005
...
...
@@ -12,6 +12,7 @@
<th>
Modification par
</th>
<th>
Date de modification
</th>
<th>
Commentaire
</th>
<th></th>
</tr>
</thead>
{% for revision in revisions_list %}
...
...
@@ -21,6 +22,7 @@
<td>
{{ revision.user }}
</td>
<td>
{{ revision.date_created }}
</td>
<td>
{{ revision.comment }}
</td>
</tr>
{% if is_bureau %}
<td><a
class=
"btn btn-info btn-sm"
role=
"button"
href=
"{% url 'logs:revert-action' revision.id %}"
><i
class=
"glyphicon glyphicon-repeat"
></i>
Annuler
</a></p></td>
{% endif %}
</tr>
{% endfor %}
</table>
logs/templates/logs/aff_stats_models.html
0 → 100644
View file @
a4d31005
{% for key, stats in stats_list.items %}
<table
class=
"table table-striped"
>
<h4>
Statistiques de l'ensemble {{ key }}
</h4>
<thead>
<tr>
<th>
Type d'objet
</th>
<th>
Nombre d'entrée stockées
</th>
</tr>
</thead>
{% for key, stat in stats.items %}
<tr>
<td>
{{ stat.0 }}
</td>
<td>
{{ stat.1 }}
</td>
</tr>
{% endfor %}
</table>
{% endfor %}
logs/templates/logs/delete.html
0 → 100644
View file @
a4d31005
{% extends "logs/sidebar.html" %}
{% load bootstrap3 %}
{% block title %}Supression d'action{% endblock %}
{% block content %}
<form
class=
"form"
method=
"post"
>
{% csrf_token %}
<h4>
Attention, voulez-vous vraiment annuler cette action {{ objet_name }} ( {{ objet }} ) ?
</h4>
{% bootstrap_button "Confirmer" button_type="submit" icon="trash" %}
</form>
<br
/>
<br
/>
<br
/>
{% endblock %}
logs/templates/logs/sidebar.html
View file @
a4d31005
...
...
@@ -2,5 +2,6 @@
{% block sidebar %}
{% if is_cableur %}
<p><a
href=
"{% url "
logs:stats-models
"
%}"
>
Statistiques base de donnée
</a></p>
{% endif %}
{% endblock %}
logs/templates/logs/stats_models.html
0 → 100644
View file @
a4d31005
{% extends "logs/sidebar.html" %}
{% load bootstrap3 %}
{% block title %}Statistiques des objets base de données{% endblock %}
{% block content %}
<h2>
Statistiques bdd
</h2>
{% include "logs/aff_stats_models.html" with stats_list=stats_list %}
<br
/>
<br
/>
<br
/>
{% endblock %}
logs/urls.py
View file @
a4d31005
...
...
@@ -4,4 +4,6 @@ from . import views
urlpatterns
=
[
url
(
r
'^$'
,
views
.
index
,
name
=
'index'
),
url
(
r
'^revert_action/(?P<revision_id>[0-9]+)$'
,
views
.
revert_action
,
name
=
'revert-action'
),
url
(
r
'^stats_models/$'
,
views
.
stats_models
,
name
=
'stats-models'
),
]
logs/views.py
View file @
a4d31005
...
...
@@ -16,8 +16,18 @@ from django.db import transaction
from
reversion.models
import
Revision
from
reversion.models
import
Version
from
users.models
import
User
,
ServiceUser
,
Right
,
School
,
ListRight
,
ListShell
,
Ban
,
Whitelist
from
cotisations.models
import
Facture
,
Vente
,
Article
,
Banque
,
Paiement
,
Cotisation
from
machines.models
import
Machine
,
MachineType
,
IpType
,
Extension
,
Interface
,
Alias
,
IpList
from
topologie.models
import
Switch
,
Port
,
Room
from
re2o.settings
import
PAGINATION_NUMBER
,
PAGINATION_LARGE_NUMBER
def
form
(
ctx
,
template
,
request
):
c
=
ctx
c
.
update
(
csrf
(
request
))
return
render_to_response
(
template
,
c
,
context_instance
=
RequestContext
(
request
))
@
login_required
@
permission_required
(
'cableur'
)
def
index
(
request
):
...
...
@@ -34,3 +44,55 @@ def index(request):
revisions
=
paginator
.
page
(
paginator
.
num_pages
)
return
render
(
request
,
'logs/index.html'
,
{
'revisions_list'
:
revisions
})
@
login_required
@
permission_required
(
'bureau'
)
def
revert_action
(
request
,
revision_id
):
""" Annule l'action en question """
try
:
revision
=
Revision
.
objects
.
get
(
id
=
revision_id
)
except
Revision
.
DoesNotExist
:
messages
.
error
(
request
,
u
"Revision inexistante"
)
if
request
.
method
==
"POST"
:
revision
.
revert
()
messages
.
success
(
request
,
"L'action a été supprimée"
)
return
redirect
(
"/logs/"
)
return
form
({
'objet'
:
revision
,
'objet_name'
:
revision
.
__class__
.
__name__
},
'logs/delete.html'
,
request
)
@
login_required
@
permission_required
(
'cableur'
)
def
stats_models
(
request
):
stats
=
{
'Users'
:
{
'users'
:
[
User
.
PRETTY_NAME
,
User
.
objects
.
count
()],
'serviceuser'
:
[
ServiceUser
.
PRETTY_NAME
,
ServiceUser
.
objects
.
count
()],
'right'
:
[
Right
.
PRETTY_NAME
,
Right
.
objects
.
count
()],
'school'
:
[
School
.
PRETTY_NAME
,
School
.
objects
.
count
()],
'listright'
:
[
ListRight
.
PRETTY_NAME
,
ListRight
.
objects
.
count
()],
'listshell'
:
[
ListShell
.
PRETTY_NAME
,
ListShell
.
objects
.
count
()],
'ban'
:
[
Ban
.
PRETTY_NAME
,
Ban
.
objects
.
count
()],
'whitelist'
:
[
Whitelist
.
PRETTY_NAME
,
Whitelist
.
objects
.
count
()]
},
'Cotisations'
:
{
'factures'
:
[
Facture
.
PRETTY_NAME
,
Facture
.
objects
.
count
()],
'vente'
:
[
Vente
.
PRETTY_NAME
,
Vente
.
objects
.
count
()],
'cotisation'
:
[
Cotisation
.
PRETTY_NAME
,
Cotisation
.
objects
.
count
()],
'article'
:
[
Article
.
PRETTY_NAME
,
Article
.
objects
.
count
()],
'banque'
:
[
Banque
.
PRETTY_NAME
,
Banque
.
objects
.
count
()],
'cotisation'
:
[
Cotisation
.
PRETTY_NAME
,
Cotisation
.
objects
.
count
()],
},
'Machines'
:
{
'machine'
:
[
Machine
.
PRETTY_NAME
,
Machine
.
objects
.
count
()],
'typemachine'
:
[
MachineType
.
PRETTY_NAME
,
MachineType
.
objects
.
count
()],
'typeip'
:
[
IpType
.
PRETTY_NAME
,
IpType
.
objects
.
count
()],
'extension'
:
[
Extension
.
PRETTY_NAME
,
Extension
.
objects
.
count
()],
'interface'
:
[
Interface
.
PRETTY_NAME
,
Interface
.
objects
.
count
()],
'alias'
:
[
Alias
.
PRETTY_NAME
,
Alias
.
objects
.
count
()],
'iplist'
:
[
IpList
.
PRETTY_NAME
,
IpList
.
objects
.
count
()],
},
'Topologie'
:
{
'switch'
:
[
Switch
.
PRETTY_NAME
,
Switch
.
objects
.
count
()],
'port'
:
[
Port
.
PRETTY_NAME
,
Port
.
objects
.
count
()],
'chambre'
:
[
Room
.
PRETTY_NAME
,
Room
.
objects
.
count
()],
},
}
return
render
(
request
,
'logs/stats_models.html'
,
{
'stats_list'
:
stats
})
machines/admin.py
View file @
a4d31005
from
django.contrib
import
admin
from
reversion.admin
import
VersionAdmin
from
.models
import
IpType
,
Machine
,
MachineType
,
IpList
,
Interface
,
Extension
from
.models
import
IpType
,
Machine
,
MachineType
,
Alias
,
IpList
,
Interface
,
Extension
class
MachineAdmin
(
VersionAdmin
):
list_display
=
(
'user'
,
'name'
,
'active'
)
...
...
@@ -22,9 +22,13 @@ class IpListAdmin(VersionAdmin):
class
InterfaceAdmin
(
VersionAdmin
):
list_display
=
(
'machine'
,
'type'
,
'dns'
,
'mac_address'
,
'ipv4'
,
'details'
)
class
AliasAdmin
(
VersionAdmin
):
list_display
=
(
'interface_parent'
,
'alias'
)
admin
.
site
.
register
(
Machine
,
MachineAdmin
)
admin
.
site
.
register
(
MachineType
,
MachineTypeAdmin
)
admin
.
site
.
register
(
IpType
,
IpTypeAdmin
)
admin
.
site
.
register
(
Extension
,
ExtensionAdmin
)
admin
.
site
.
register
(
IpList
,
IpListAdmin
)
admin
.
site
.
register
(
Interface
,
InterfaceAdmin
)
admin
.
site
.
register
(
Alias
,
AliasAdmin
)
machines/forms.py
View file @
a4d31005
from
django.forms
import
ModelForm
,
Form
,
ValidationError
from
django
import
forms
from
.models
import
Machine
,
Interface
,
IpList
,
MachineType
,
Extension
,
IpType
from
.models
import
Alias
,
Machine
,
Interface
,
IpList
,
MachineType
,
Extension
,
IpType
class
EditMachineForm
(
ModelForm
):
class
Meta
:
...
...
@@ -59,6 +59,15 @@ class BaseEditInterfaceForm(EditInterfaceForm):
self
.
fields
[
'type'
].
queryset
=
MachineType
.
objects
.
filter
(
ip_type
=
IpType
.
objects
.
filter
(
need_infra
=
False
))
self
.
fields
[
'ipv4'
].
queryset
=
IpList
.
objects
.
filter
(
ip_type
=
IpType
.
objects
.
filter
(
need_infra
=
False
))
class
NewAliasForm
(
ModelForm
):
class
Meta
:
model
=
Alias
fields
=
[
'alias'
]
class
EditAliasFullForm
(
NewAliasForm
):
class
Meta
(
NewAliasForm
.
Meta
):
fields
=
'__all__'
class
MachineTypeForm
(
ModelForm
):
class
Meta
:
model
=
MachineType
...
...
machines/migrations/0027_alias.py
0 → 100644
View file @
a4d31005
# -*- coding: utf-8 -*-
from
__future__
import
unicode_literals
from
django.db
import
migrations
,
models
class
Migration
(
migrations
.
Migration
):
dependencies
=
[
(
'machines'
,
'0026_auto_20161026_1348'
),
]
operations
=
[
migrations
.
CreateModel
(
name
=
'Alias'
,
fields
=
[
(
'id'
,
models
.
AutoField
(
primary_key
=
True
,
serialize
=
False
,
auto_created
=
True
,
verbose_name
=
'ID'
)),
(
'alias'
,
models
.
CharField
(
max_length
=
255
,
help_text
=
'Obligatoire et unique, ne doit pas comporter de points'
,
unique
=
True
)),
(
'interface_parent'
,
models
.
ForeignKey
(
to
=
'machines.Interface'
)),
],
),
]
machines/models.py
View file @
a4d31005
...
...
@@ -8,6 +8,8 @@ from re2o.settings import MAIN_EXTENSION
class
Machine
(
models
.
Model
):
PRETTY_NAME
=
"Machine"
user
=
models
.
ForeignKey
(
'users.User'
,
on_delete
=
models
.
PROTECT
)
name
=
models
.
CharField
(
max_length
=
255
,
help_text
=
"Optionnel"
,
blank
=
True
,
null
=
True
)
active
=
models
.
BooleanField
(
default
=
True
)
...
...
@@ -16,6 +18,8 @@ class Machine(models.Model):
return
str
(
self
.
user
)
+
' - '
+
str
(
self
.
id
)
+
' - '
+
str
(
self
.
name
)
class
MachineType
(
models
.
Model
):
PRETTY_NAME
=
"Type de machine"
type
=
models
.
CharField
(
max_length
=
255
)
ip_type
=
models
.
ForeignKey
(
'IpType'
,
on_delete
=
models
.
PROTECT
,
blank
=
True
,
null
=
True
)
...
...
@@ -23,6 +27,8 @@ class MachineType(models.Model):
return
self
.
type
class
IpType
(
models
.
Model
):
PRETTY_NAME
=
"Type d'ip"
type
=
models
.
CharField
(
max_length
=
255
)
extension
=
models
.
ForeignKey
(
'Extension'
,
on_delete
=
models
.
PROTECT
)
need_infra
=
models
.
BooleanField
(
default
=
False
)
...
...
@@ -31,12 +37,16 @@ class IpType(models.Model):
return
self
.
type
class
Extension
(
models
.
Model
):
PRETTY_NAME
=
"Extensions dns"
name
=
models
.
CharField
(
max_length
=
255
)
def
__str__
(
self
):
return
self
.
name
class
Interface
(
models
.
Model
):
PRETTY_NAME
=
"Interface"
ipv4
=
models
.
OneToOneField
(
'IpList'
,
on_delete
=
models
.
PROTECT
,
blank
=
True
,
null
=
True
)
#ipv6 = models.GenericIPAddressField(protocol='IPv6', null=True)
mac_address
=
MACAddressField
(
integer
=
False
,
unique
=
True
)
...
...
@@ -54,7 +64,18 @@ class Interface(models.Model):
def
__str__
(
self
):
return
self
.
dns
class
Alias
(
models
.
Model
):
PRETTY_NAME
=
"Alias dns"
interface_parent
=
models
.
ForeignKey
(
'Interface'
,
on_delete
=
models
.
CASCADE
)
alias
=
models
.
CharField
(
help_text
=
"Obligatoire et unique, ne doit pas comporter de points"
,
max_length
=
255
,
unique
=
True
)
def
__str__
(
self
):
return
self
.
alias
class
IpList
(
models
.
Model
):
PRETTY_NAME
=
"Addresses ipv4"
ipv4
=
models
.
GenericIPAddressField
(
protocol
=
'IPv4'
,
unique
=
True
)
ip_type
=
models
.
ForeignKey
(
'IpType'
,
on_delete
=
models
.
PROTECT
)
...
...
machines/views.py
View file @
a4d31005
...
...
@@ -20,7 +20,7 @@ from reversion import revisions as reversion
import
re
from
.forms
import
NewMachineForm
,
EditMachineForm
,
EditInterfaceForm
,
AddInterfaceForm
,
MachineTypeForm
,
DelMachineTypeForm
,
ExtensionForm
,
DelExtensionForm
,
BaseEditInterfaceForm
,
BaseEditMachineForm
from
.forms
import
IpTypeForm
,
DelIpTypeForm
from
.forms
import
IpTypeForm
,
DelIpTypeForm
,
NewAliasForm
,
EditAliasFullForm
from
.models
import
IpType
,
Machine
,
Interface
,
IpList
,
MachineType
,
Extension
from
users.models
import
User
from
re2o.settings
import
PAGINATION_NUMBER
,
PAGINATION_LARGE_NUMBER
...
...
topologie/models.py
View file @
a4d31005
...
...
@@ -16,6 +16,8 @@ def clean_port_related(port):
related_port
.
save
()
class
Switch
(
models
.
Model
):
PRETTY_NAME
=
"Switch / Commutateur"
switch_interface
=
models
.
OneToOneField
(
'machines.Interface'
,
on_delete
=
models
.
CASCADE
)
location
=
models
.
CharField
(
max_length
=
255
)
number
=
models
.
IntegerField
()
...
...
@@ -25,6 +27,8 @@ class Switch(models.Model):
return
str
(
self
.
location
)
class
Port
(
models
.
Model
):
PRETTY_NAME
=
"Port de switch"
switch
=
models
.
ForeignKey
(
'Switch'
,
related_name
=
"ports"
)
port
=
models
.
IntegerField
()
room
=
models
.
ForeignKey
(
'Room'
,
on_delete
=
models
.
PROTECT
,
blank
=
True
,
null
=
True
)
...
...
@@ -36,6 +40,8 @@ class Port(models.Model):
unique_together
=
(
'switch'
,
'port'
)
def
clean
(
self
):
if
self
.
port
>
self
.
switch
.
number
:
raise
ValidationError
(
"Ce port ne peut exister, numero trop élevé"
)
if
self
.
room
and
self
.
machine_interface
or
self
.
room
and
self
.
related
or
self
.
machine_interface
and
self
.
related
:
raise
ValidationError
(
"Chambre, interface et related_port sont mutuellement exclusifs"
)
if
self
.
related
==
self
:
...
...
@@ -52,6 +58,8 @@ class Port(models.Model):
return
str
(
self
.
switch
)
+
" - "
+
str
(
self
.
port
)
class
Room
(
models
.
Model
):
PRETTY_NAME
=
"Chambre/ Prise murale"
name
=
models
.
CharField
(
max_length
=
255
,
unique
=
True
)
details
=
models
.
CharField
(
max_length
=
255
,
blank
=
True
)
...
...
users/models.py
View file @
a4d31005
...
...
@@ -101,6 +101,7 @@ class UserManager(BaseUserManager):
class
User
(
AbstractBaseUser
):
PRETTY_NAME
=
"Utilisateurs"
STATE_ACTIVE
=
0
STATE_DISABLED
=
1
STATE_ARCHIVE
=
2
...
...
@@ -287,6 +288,7 @@ def user_post_delete(sender, **kwargs):
#user.ldap_del()
class
ServiceUser
(
AbstractBaseUser
):
PRETTY_NAME
=
"Utilisateurs de service"
pseudo
=
models
.
CharField
(
max_length
=
32
,
unique
=
True
,
help_text
=
"Doit contenir uniquement des lettres, chiffres, ou tirets"
,
validators
=
[
linux_user_validator
])
...
...
@@ -323,6 +325,8 @@ def service_user_post_delete(sender, **kwargs):
service_user
.
ldap_del
()
class
Right
(
models
.
Model
):
PRETTY_NAME
=
"Droits affectés à des users"
user
=
models
.
ForeignKey
(
'User'
,
on_delete
=
models
.
PROTECT
)
right
=
models
.
ForeignKey
(
'ListRight'
,
on_delete
=
models
.
PROTECT
)
...
...
@@ -343,6 +347,8 @@ def right_post_delete(sender, **kwargs):
right
.
ldap_sync
()
class
School
(
models
.
Model
):
PRETTY_NAME
=
"Etablissements enregistrés"
name
=
models
.
CharField
(
max_length
=
255
)
def
__str__
(
self
):
...
...
@@ -350,6 +356,8 @@ class School(models.Model):
class
ListRight
(
models
.
Model
):
PRETTY_NAME
=
"Liste des droits existants"
listright
=
models
.
CharField
(
max_length
=
255
,
unique
=
True
)
gid
=
models
.
IntegerField
(
unique
=
True
,
null
=
True
)
...
...
@@ -383,12 +391,16 @@ def listright_post_delete(sender, **kwargs):
right
.
ldap_del
()
class
ListShell
(
models
.
Model
):
PRETTY_NAME
=
"Liste des shells disponibles"
shell
=
models
.
CharField
(
max_length
=
255
,
unique
=
True
)
def
__str__
(
self
):
return
self
.
shell
class
Ban
(
models
.
Model
):
PRETTY_NAME
=
"Liste des bannissements"
user
=
models
.
ForeignKey
(
'User'
,
on_delete
=
models
.
PROTECT
)
raison
=
models
.
CharField
(
max_length
=
255
)
date_start
=
models
.
DateTimeField
(
auto_now_add
=
True
)
...
...
@@ -399,6 +411,8 @@ class Ban(models.Model):
class
Whitelist
(
models
.
Model
):
PRETTY_NAME
=
"Liste des accès gracieux"
user
=
models
.
ForeignKey
(
'User'
,
on_delete
=
models
.
PROTECT
)
raison
=
models
.
CharField
(
max_length
=
255
)
date_start
=
models
.
DateTimeField
(
auto_now_add
=
True
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment