port to new django, AI automated
This commit is contained in:
@@ -1,32 +1,128 @@
|
||||
from django.contrib import admin
|
||||
from django.contrib.auth.admin import UserAdmin
|
||||
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
|
||||
from django.contrib.auth.models import User
|
||||
from django.utils.translation import ugettext as _
|
||||
from musicians.models import Musician
|
||||
# from eventplanner.admin import EventParticipationInline
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from .models import Musician
|
||||
|
||||
|
||||
# Define an inline admin descriptor for Musician model
|
||||
# which acts a bit like a singleton
|
||||
class MusicianInline(admin.StackedInline):
|
||||
"""Inline admin for Musician model attached to User."""
|
||||
|
||||
model = Musician
|
||||
can_delete = False
|
||||
verbose_name_plural = _('musicians')
|
||||
verbose_name = _('musician')
|
||||
verbose_name_plural = _("musician profile")
|
||||
verbose_name = _("musician profile")
|
||||
|
||||
fieldsets = (
|
||||
(
|
||||
_("Images"),
|
||||
{
|
||||
"fields": ("image", "small_image"),
|
||||
"classes": ("collapse",),
|
||||
},
|
||||
),
|
||||
(
|
||||
_("Contact"),
|
||||
{
|
||||
"fields": ("phone_home", "phone_mobile", "phone_work"),
|
||||
},
|
||||
),
|
||||
(
|
||||
_("Address"),
|
||||
{
|
||||
"fields": ("street", "city", "zip_code"),
|
||||
},
|
||||
),
|
||||
(
|
||||
_("Details"),
|
||||
{
|
||||
"fields": ("instrument", "birthday", "position", "public_description"),
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
# Define a new User admin
|
||||
class UserAdmin(UserAdmin):
|
||||
class CustomUserAdmin(BaseUserAdmin):
|
||||
"""Extended User admin with Musician inline."""
|
||||
|
||||
inlines = (MusicianInline,)
|
||||
list_display = (
|
||||
"username",
|
||||
"email",
|
||||
"first_name",
|
||||
"last_name",
|
||||
"is_staff",
|
||||
"get_instrument",
|
||||
)
|
||||
list_select_related = ("musician",)
|
||||
|
||||
@admin.display(description=_("Instrument"))
|
||||
def get_instrument(self, obj):
|
||||
try:
|
||||
return obj.musician.get_instrument_display()
|
||||
except Musician.DoesNotExist:
|
||||
return "-"
|
||||
|
||||
|
||||
@admin.register(Musician)
|
||||
class MusicianAdmin(admin.ModelAdmin):
|
||||
readonly_fields = ('user',)
|
||||
# inlines = ( EventParticipationInline, )
|
||||
model = Musician
|
||||
"""Admin configuration for Musician model."""
|
||||
|
||||
list_display = (
|
||||
"user",
|
||||
"instrument",
|
||||
"phone_mobile",
|
||||
"city",
|
||||
"position",
|
||||
)
|
||||
list_filter = ("instrument",)
|
||||
search_fields = (
|
||||
"user__username",
|
||||
"user__first_name",
|
||||
"user__last_name",
|
||||
"city",
|
||||
"phone_mobile",
|
||||
)
|
||||
readonly_fields = ("user",)
|
||||
ordering = ("position", "user__username")
|
||||
|
||||
fieldsets = (
|
||||
(
|
||||
None,
|
||||
{
|
||||
"fields": ("user", "instrument", "position"),
|
||||
},
|
||||
),
|
||||
(
|
||||
_("Images"),
|
||||
{
|
||||
"fields": ("image", "small_image"),
|
||||
"classes": ("collapse",),
|
||||
},
|
||||
),
|
||||
(
|
||||
_("Contact Information"),
|
||||
{
|
||||
"fields": ("phone_home", "phone_mobile", "phone_work"),
|
||||
},
|
||||
),
|
||||
(
|
||||
_("Address"),
|
||||
{
|
||||
"fields": ("street", "city", "zip_code"),
|
||||
},
|
||||
),
|
||||
(
|
||||
_("Personal"),
|
||||
{
|
||||
"fields": ("birthday", "public_description"),
|
||||
"classes": ("collapse",),
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
# Re-register UserAdmin
|
||||
# Re-register UserAdmin with Musician inline
|
||||
admin.site.unregister(User)
|
||||
admin.site.register(User, UserAdmin)
|
||||
admin.site.register(Musician, MusicianAdmin)
|
||||
admin.site.register(User, CustomUserAdmin)
|
||||
|
||||
40
musicians/migrations/0001_initial.py
Normal file
40
musicians/migrations/0001_initial.py
Normal file
@@ -0,0 +1,40 @@
|
||||
# Generated by Django 5.1.15 on 2026-03-30 19:15
|
||||
|
||||
import django.db.models.deletion
|
||||
import musicians.models
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='Musician',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('image', models.ImageField(blank=True, null=True, upload_to=musicians.models.musicianPictureName, verbose_name='image')),
|
||||
('small_image', models.ImageField(blank=True, null=True, upload_to=musicians.models.musicianSmallPictureName, verbose_name='circular thumbnail')),
|
||||
('instrument', models.CharField(blank=True, choices=[('TR', 'Trumpet'), ('TRB', 'Trombone'), ('HRN', 'Horn'), ('TUBA', 'Tuba')], max_length=4, verbose_name='instrument')),
|
||||
('birthday', models.DateField(blank=True, null=True, verbose_name='birthday')),
|
||||
('street', models.CharField(blank=True, max_length=80, verbose_name='street')),
|
||||
('city', models.CharField(blank=True, max_length=40, verbose_name='city')),
|
||||
('zip_code', models.IntegerField(blank=True, null=True, verbose_name='zip_code')),
|
||||
('phone_home', models.CharField(blank=True, max_length=18, verbose_name='phone_home')),
|
||||
('phone_mobile', models.CharField(blank=True, max_length=18, verbose_name='phone_mobile')),
|
||||
('phone_work', models.CharField(blank=True, max_length=18, verbose_name='phone_work')),
|
||||
('position', models.IntegerField(blank=True, null=True, verbose_name='Position')),
|
||||
('public_description', models.TextField(blank=True, verbose_name='public_description')),
|
||||
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='user')),
|
||||
],
|
||||
options={
|
||||
'ordering': ['position', 'user__username'],
|
||||
},
|
||||
),
|
||||
]
|
||||
0
musicians/migrations/__init__.py
Normal file
0
musicians/migrations/__init__.py
Normal file
@@ -1,14 +1,14 @@
|
||||
from django.db import models
|
||||
from django.contrib.auth.models import User
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
import os
|
||||
|
||||
from django.contrib.auth.models import User
|
||||
from django.db import models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
INSTRUMENTS = (
|
||||
('TR', _('Trumpet')),
|
||||
('TRB', _('Trombone')),
|
||||
('HRN', _('Horn')),
|
||||
('TUBA', _('Tuba'))
|
||||
("TR", _("Trumpet")),
|
||||
("TRB", _("Trombone")),
|
||||
("HRN", _("Horn")),
|
||||
("TUBA", _("Tuba")),
|
||||
)
|
||||
|
||||
|
||||
@@ -24,35 +24,58 @@ def musicianSmallPictureName(musician, originalName):
|
||||
|
||||
class Musician(models.Model):
|
||||
# Link to user object, contains first name and last name
|
||||
user = models.OneToOneField(User, verbose_name=_("user"), on_delete=models.CASCADE)
|
||||
user = models.OneToOneField(User, on_delete=models.CASCADE, verbose_name=_("user"))
|
||||
|
||||
image = models.ImageField(upload_to=musicianPictureName, verbose_name=_("image"))
|
||||
small_image = models.ImageField(upload_to=musicianSmallPictureName, verbose_name=_("circular thumbnail"))
|
||||
image = models.ImageField(
|
||||
upload_to=musicianPictureName,
|
||||
verbose_name=_("image"),
|
||||
blank=True,
|
||||
null=True,
|
||||
)
|
||||
small_image = models.ImageField(
|
||||
upload_to=musicianSmallPictureName,
|
||||
verbose_name=_("circular thumbnail"),
|
||||
blank=True,
|
||||
null=True,
|
||||
)
|
||||
|
||||
# Properties
|
||||
instrument = models.CharField(max_length=4, choices=INSTRUMENTS, blank=True, verbose_name=_("instrument"))
|
||||
instrument = models.CharField(
|
||||
max_length=4, choices=INSTRUMENTS, blank=True, verbose_name=_("instrument")
|
||||
)
|
||||
|
||||
birthday = models.DateField(null=True, verbose_name=_("birthday"))
|
||||
birthday = models.DateField(null=True, blank=True, verbose_name=_("birthday"))
|
||||
|
||||
street = models.CharField(max_length=80, blank=True, verbose_name=_("street"))
|
||||
city = models.CharField(max_length=40, blank=True, verbose_name=_("city"))
|
||||
zip_code = models.IntegerField(null=True, verbose_name=_("zip_code"))
|
||||
zip_code = models.IntegerField(null=True, blank=True, verbose_name=_("zip_code"))
|
||||
|
||||
phone_home = models.CharField(max_length=18, blank=True, verbose_name=_("phone_home"))
|
||||
phone_mobile = models.CharField(max_length=18, blank=True, verbose_name=_("phone_mobile"))
|
||||
phone_work = models.CharField(max_length=18, blank=True, verbose_name=_("phone_work"))
|
||||
phone_home = models.CharField(
|
||||
max_length=18, blank=True, verbose_name=_("phone_home")
|
||||
)
|
||||
phone_mobile = models.CharField(
|
||||
max_length=18, blank=True, verbose_name=_("phone_mobile")
|
||||
)
|
||||
phone_work = models.CharField(
|
||||
max_length=18, blank=True, verbose_name=_("phone_work")
|
||||
)
|
||||
|
||||
position = models.IntegerField(null=True, verbose_name=_("Position"))
|
||||
position = models.IntegerField(null=True, blank=True, verbose_name=_("Position"))
|
||||
|
||||
public_description = models.TextField(blank=True, verbose_name=_("public_description"))
|
||||
public_description = models.TextField(
|
||||
blank=True, verbose_name=_("public_description")
|
||||
)
|
||||
|
||||
class Meta:
|
||||
ordering = ["position", "user__username"]
|
||||
|
||||
@property
|
||||
def isDeepBrass(self):
|
||||
return self.instrument == 'TRB' or self.instrument == "EUPH" or self.instrument == "TUBA" or self.instrument == "HRN"
|
||||
return self.instrument in ("TRB", "EUPH", "TUBA", "HRN")
|
||||
|
||||
@property
|
||||
def isHighBrass(self):
|
||||
return self.instrument == 'TR'
|
||||
return self.instrument == "TR"
|
||||
|
||||
def __unicode__(self):
|
||||
def __str__(self):
|
||||
return self.user.username
|
||||
|
||||
@@ -1,178 +1,236 @@
|
||||
{% extends "website/base.html" %}
|
||||
|
||||
|
||||
{% load sekizai_tags staticfiles %}
|
||||
|
||||
|
||||
|
||||
{% block content %}
|
||||
|
||||
{% addtoblock "css" strip %}<link rel="stylesheet" type="text/css" href="{{STATIC_URL}}css/portfolio.css" media="screen, projection">{% endaddtoblock %}
|
||||
|
||||
{% addtoblock "css" strip %}<link rel="stylesheet" type="text/css" href="{{STATIC_URL}}css/lib/isotope.css">{% endaddtoblock %}
|
||||
{% addtoblock "css" strip %}<link rel="stylesheet" type="text/css" href="{{STATIC_URL}}css/lib/animate.css">{% endaddtoblock %}
|
||||
|
||||
{% addtoblock "css" %}
|
||||
{% extends "website/base.html" %} {% load sekizai_tags static %} {% block content %} {% addtoblock "css" strip %}<link
|
||||
rel="stylesheet"
|
||||
type="text/css"
|
||||
href="{{STATIC_URL}}/css/portfolio.css"
|
||||
media="screen, projection"
|
||||
/>{% endaddtoblock %} {% addtoblock "css" strip %}<link
|
||||
rel="stylesheet"
|
||||
type="text/css"
|
||||
href="{{STATIC_URL}}/css/lib/isotope.css"
|
||||
/>{% endaddtoblock %} {% addtoblock "css" strip %}<link
|
||||
rel="stylesheet"
|
||||
type="text/css"
|
||||
href="{{STATIC_URL}}/css/lib/animate.css"
|
||||
/>{% endaddtoblock %} {% addtoblock "css" %}
|
||||
<style>
|
||||
.addressbook_entry {
|
||||
box-shadow: 0px 0px 7px -1px rgb(214, 214, 214);
|
||||
border: 2px solid rgb(217, 217, 217);
|
||||
width: 360px !important;
|
||||
float: left;
|
||||
padding-top: 20px;
|
||||
padding-left: 5px;
|
||||
padding-bottom: 20px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
.addressbook_entry {
|
||||
box-shadow: 0px 0px 7px -1px rgb(214, 214, 214);
|
||||
border: 2px solid rgb(217, 217, 217);
|
||||
width: 360px !important;
|
||||
float: left;
|
||||
padding-top: 20px;
|
||||
padding-left: 5px;
|
||||
padding-bottom: 20px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.addressbook_entry .name {
|
||||
color: rgb(83, 83, 83);
|
||||
font-weight: normal;
|
||||
font-style: italic;
|
||||
font-size: 18px;
|
||||
margin: 0px 0px 5px;
|
||||
}
|
||||
.addressbook_entry .name {
|
||||
color: rgb(83, 83, 83);
|
||||
font-weight: normal;
|
||||
font-style: italic;
|
||||
font-size: 18px;
|
||||
margin: 0px 0px 5px;
|
||||
}
|
||||
|
||||
.addressbook_entry td {
|
||||
padding-right: 15px;
|
||||
}
|
||||
.addressbook_entry td {
|
||||
padding-right: 15px;
|
||||
}
|
||||
|
||||
.addressbook_entry .picture {
|
||||
max-width: 55px;
|
||||
float: left;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.addressbook_entry td.labelCell {
|
||||
white-space: nowrap;
|
||||
}
|
||||
@media (max-width: 480px) {
|
||||
.addressbook_entry {
|
||||
font-size: 11px;
|
||||
width: 265px !important;
|
||||
}
|
||||
.addressbook_entry .picture {
|
||||
max-width: 55px;
|
||||
float: left;
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
}
|
||||
}
|
||||
@media (max-width: 300px) {
|
||||
.addressbook_entry .picture {
|
||||
display: none;
|
||||
}
|
||||
.addressbook_entry {
|
||||
width: 200px !important;
|
||||
}
|
||||
}
|
||||
.addressbook_entry .picture {
|
||||
max-width: 55px;
|
||||
float: left;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.addressbook_entry td.labelCell {
|
||||
white-space: nowrap;
|
||||
}
|
||||
@media (max-width: 480px) {
|
||||
.addressbook_entry {
|
||||
font-size: 11px;
|
||||
width: 265px !important;
|
||||
}
|
||||
.addressbook_entry .picture {
|
||||
max-width: 55px;
|
||||
float: left;
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
}
|
||||
}
|
||||
@media (max-width: 300px) {
|
||||
.addressbook_entry .picture {
|
||||
display: none;
|
||||
}
|
||||
.addressbook_entry {
|
||||
width: 200px !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
{% endaddtoblock %}
|
||||
|
||||
|
||||
{% addtoblock "js" strip %} <script src="{{STATIC_URL}}js/jquery.isotope.min.js"></script> {% endaddtoblock %}
|
||||
|
||||
|
||||
{% addtoblock "js" %}
|
||||
{% endaddtoblock %} {% addtoblock "js" strip %}
|
||||
<script src="{{STATIC_URL}}/js/jquery.isotope.min.js"></script>
|
||||
{% endaddtoblock %} {% addtoblock "js" %}
|
||||
<script>
|
||||
$(function(){
|
||||
$(function () {
|
||||
var $container = $("#gallery_container"),
|
||||
$filters = $("#filters a");
|
||||
|
||||
var $container = $('#gallery_container'),
|
||||
$filters = $("#filters a");
|
||||
|
||||
$container.imagesLoaded( function(){
|
||||
$container.isotope({
|
||||
itemSelector : '.photo',
|
||||
masonry: {
|
||||
columnWidth: 102
|
||||
}
|
||||
});
|
||||
$container.imagesLoaded(function () {
|
||||
$container.isotope({
|
||||
itemSelector: ".photo",
|
||||
masonry: {
|
||||
columnWidth: 102,
|
||||
},
|
||||
});
|
||||
|
||||
// filter items when filter link is clicked
|
||||
$filters.click(function() {
|
||||
$filters.removeClass("active");
|
||||
$(this).addClass("active");
|
||||
var selector = $(this).data('filter');
|
||||
$container.isotope({ filter: selector });
|
||||
return false;
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
</script>
|
||||
|
||||
// filter items when filter link is clicked
|
||||
$filters.click(function () {
|
||||
$filters.removeClass("active");
|
||||
$(this).addClass("active");
|
||||
var selector = $(this).data("filter");
|
||||
$container.isotope({ filter: selector });
|
||||
return false;
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
{% endaddtoblock %}
|
||||
|
||||
|
||||
<div id="portfolio">
|
||||
<div class="container">
|
||||
<div class="section_header">
|
||||
<h3>Adressbuch</h3>
|
||||
<div class="container">
|
||||
<div class="section_header">
|
||||
<h3>Adressbuch</h3>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="span12">
|
||||
<div id="filters_container">
|
||||
<ul id="filters">
|
||||
<li><a href="#" data-filter="*" class="active">Alle</a></li>
|
||||
<li class="separator">/</li>
|
||||
<li><a href="#" data-filter=".unterstimme">Unterstimmen</a></li>
|
||||
<li class="separator">/</li>
|
||||
<li><a href="#" data-filter=".oberstimme">Oberstimmen</a></li>
|
||||
<li class="separator">/</li>
|
||||
<li><a href="#" data-filter=".rest">Rest</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="span12">
|
||||
<div id="gallery_container" >
|
||||
{% for m in musicians %}
|
||||
<div class="photo isotope-item addressbook_entry {% if m.isDeepBrass %} unterstimme {% elif m.isHighBrass %} oberstimme {% else %} rest {% endif %} ">
|
||||
|
||||
<div>
|
||||
<img src="{{MEDIA_URL}}/user_images/{{m.user}}_thumb.png" class="img-circle picture">
|
||||
</div>
|
||||
|
||||
<div class="name">
|
||||
{{ m.user.first_name }} {{m.user.last_name }}
|
||||
</div>
|
||||
|
||||
{% if not request.device.android %}
|
||||
<table>
|
||||
{% if m.street %} <tr><td class="labelCell"> Adresse </td><td>{{m.street}} </td>
|
||||
<tr><td class="labelCell"> </td><td>{{m.zip_code}} {{m.city}}</td>{% endif %}
|
||||
{% if m.birthday %} <tr><td class="labelCell"> Geburtstag: </td><td>{{m.birthday }} </td>{% endif %}
|
||||
{% if m.phone_home %} <tr><td class="labelCell"> Telefon (Home): </td><td>{{m.phone_home }} </td>{% endif %}
|
||||
{% if m.phone_mobile %}<tr><td class="labelCell"> Telefon (Mobil): </td><td>{{m.phone_mobile }} </td>{% endif %}
|
||||
{% if m.phone_work %} <tr><td class="labelCell"> Telefon (Arbeit): </td><td>{{m.phone_work }} </td>{% endif %}
|
||||
</table>
|
||||
{% else %}
|
||||
<table>
|
||||
{% if m.street %} <tr><td class="labelCell"> Adresse </td><td>{{m.street}} </td>
|
||||
<tr><td class="labelCell"> </td><td>{{m.zip_code}} {{m.city}}</td>{% endif %}
|
||||
{% if m.birthday %} <tr><td class="labelCell"> Geburtstag: </td><td>{{m.birthday }} </td>{% endif %}
|
||||
{% if m.phone_home %} <tr><td class="labelCell"> Telefon (Home): </td><td><a href="tel:{{m.phone_home }}"> {{m.phone_home }} </a> </td>{% endif %}
|
||||
{% if m.phone_mobile %}<tr><td class="labelCell"> Telefon (Mobil): </td><td><a href="tel:{{m.phone_mobile }}"> {{m.phone_mobile }} </a> </td>{% endif %}
|
||||
{% if m.phone_work %} <tr><td class="labelCell"> Telefon (Arbeit): </td><td><a href="tel:{{m.phone_work }}"> {{m.phone_work }} </a> </td>{% endif %}
|
||||
</table>
|
||||
{% endif %}
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="span12">
|
||||
<div id="filters_container">
|
||||
<ul id="filters">
|
||||
<li>
|
||||
<a href="#" data-filter="*" class="active">Alle</a>
|
||||
</li>
|
||||
<li class="separator">/</li>
|
||||
<li>
|
||||
<a href="#" data-filter=".unterstimme"
|
||||
>Unterstimmen</a
|
||||
>
|
||||
</li>
|
||||
<li class="separator">/</li>
|
||||
<li>
|
||||
<a href="#" data-filter=".oberstimme"
|
||||
>Oberstimmen</a
|
||||
>
|
||||
</li>
|
||||
<li class="separator">/</li>
|
||||
<li><a href="#" data-filter=".rest">Rest</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="span12">
|
||||
<div id="gallery_container">
|
||||
{% for m in musicians %}
|
||||
<div
|
||||
class="photo isotope-item addressbook_entry {% if m.isDeepBrass %} unterstimme {% elif m.isHighBrass %} oberstimme {% else %} rest {% endif %}"
|
||||
>
|
||||
<div>
|
||||
<img
|
||||
src="{{MEDIA_URL}}/user_images/{{m.user}}_thumb.png"
|
||||
class="img-circle picture"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="name">
|
||||
{{ m.user.first_name }} {{m.user.last_name }}
|
||||
</div>
|
||||
|
||||
{% if not request.device.android %}
|
||||
<table>
|
||||
{% if m.street %}
|
||||
<tr>
|
||||
<td class="labelCell">Adresse</td>
|
||||
<td>{{m.street}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="labelCell"></td>
|
||||
<td>{{m.zip_code}} {{m.city}}</td>
|
||||
{% endif %} {% if m.birthday %}
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="labelCell">Geburtstag:</td>
|
||||
<td>{{m.birthday }}</td>
|
||||
{% endif %} {% if m.phone_home %}
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="labelCell">Telefon (Home):</td>
|
||||
<td>{{m.phone_home }}</td>
|
||||
{% endif %} {% if m.phone_mobile %}
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="labelCell">Telefon (Mobil):</td>
|
||||
<td>{{m.phone_mobile }}</td>
|
||||
{% endif %} {% if m.phone_work %}
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="labelCell">Telefon (Arbeit):</td>
|
||||
<td>{{m.phone_work }}</td>
|
||||
{% endif %}
|
||||
</tr>
|
||||
</table>
|
||||
{% else %}
|
||||
<table>
|
||||
{% if m.street %}
|
||||
<tr>
|
||||
<td class="labelCell">Adresse</td>
|
||||
<td>{{m.street}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="labelCell"></td>
|
||||
<td>{{m.zip_code}} {{m.city}}</td>
|
||||
{% endif %} {% if m.birthday %}
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="labelCell">Geburtstag:</td>
|
||||
<td>{{m.birthday }}</td>
|
||||
{% endif %} {% if m.phone_home %}
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="labelCell">Telefon (Home):</td>
|
||||
<td>
|
||||
<a href="tel:{{m.phone_home }}">
|
||||
{{m.phone_home }}
|
||||
</a>
|
||||
</td>
|
||||
{% endif %} {% if m.phone_mobile %}
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="labelCell">Telefon (Mobil):</td>
|
||||
<td>
|
||||
<a href="tel:{{m.phone_mobile }}">
|
||||
{{m.phone_mobile }}
|
||||
</a>
|
||||
</td>
|
||||
{% endif %} {% if m.phone_work %}
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="labelCell">Telefon (Arbeit):</td>
|
||||
<td>
|
||||
<a href="tel:{{m.phone_work }}">
|
||||
{{m.phone_work }}
|
||||
</a>
|
||||
</td>
|
||||
{% endif %}
|
||||
</tr>
|
||||
</table>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
{% endblock %}
|
||||
|
||||
|
||||
@@ -1,101 +1,120 @@
|
||||
{% extends "website/base.html" %}
|
||||
{% extends "website/base.html" %} {% load sekizai_tags static %} {% block menu_contents %} {% endblock %} {% block content %} {% addtoblock "css" strip %}<link
|
||||
rel="stylesheet"
|
||||
href="{{STATIC_URL}}/css/lib/animate.css"
|
||||
type="text/css"
|
||||
media="screen, projection"
|
||||
/>{% endaddtoblock %} {% addtoblock "css" strip %}<link
|
||||
rel="stylesheet"
|
||||
href="{{STATIC_URL}}/css/sign-in.css"
|
||||
type="text/css"
|
||||
media="screen"
|
||||
/>
|
||||
{% endaddtoblock %} {% addtoblock "js" strip %}
|
||||
<script src="{{STATIC_URL}}/js/jquery.noty.js"></script>
|
||||
{% endaddtoblock %} {% addtoblock "css" strip %}<link
|
||||
rel="stylesheet"
|
||||
href="{{STATIC_URL}}/css/jquery.noty.css"
|
||||
type="text/css"
|
||||
media="screen"
|
||||
/>
|
||||
{% endaddtoblock %} {% addtoblock "css" strip %}<link
|
||||
rel="stylesheet"
|
||||
href="{{STATIC_URL}}/css/noty_theme_default.css"
|
||||
type="text/css"
|
||||
media="screen"
|
||||
/>
|
||||
{% endaddtoblock %}
|
||||
|
||||
<!-- For Autocompete -->
|
||||
{% addtoblock "js" strip %}
|
||||
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js"></script>
|
||||
{% endaddtoblock %} {% addtoblock "css" strip %}<link
|
||||
rel="stylesheet"
|
||||
href="{{STATIC_URL}}/css/jquery-ui-1.8.21.custom.css"
|
||||
type="text/css"
|
||||
media="screen"
|
||||
/>
|
||||
{% endaddtoblock %}
|
||||
|
||||
{% load sekizai_tags staticfiles %}
|
||||
<!-- Notifications -->
|
||||
{% addtoblock "js" %}
|
||||
<script>
|
||||
$(document).ready(function () {
|
||||
$("#loginform").submit(function (e) {
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: "",
|
||||
data: $("#loginform").serialize(),
|
||||
dataType: "json",
|
||||
success: function (data) {
|
||||
if (data["err"]) {
|
||||
noty({
|
||||
text: data["err"],
|
||||
layout: "top",
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
if (data["redirect"]) {
|
||||
window.location.href = data["redirect"];
|
||||
}
|
||||
},
|
||||
error: function (jqXHR, text1, text2) {
|
||||
console.log(jqXHR);
|
||||
console.log(text1);
|
||||
console.log(text2);
|
||||
},
|
||||
});
|
||||
e.preventDefault();
|
||||
});
|
||||
|
||||
{% block menu_contents %}
|
||||
{% endblock %}
|
||||
$.get("/musicians/login/usernames", function (data) {
|
||||
$("#username").autocomplete({ source: data });
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{% endaddtoblock %}
|
||||
|
||||
<div id="sign_in">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="span12 header">
|
||||
<h4>Login zum internen Bereich</h4>
|
||||
<p>Hier dürfen nur Ensemble Mitglieder rein...</p>
|
||||
</div>
|
||||
|
||||
<div class="span12 footer" action="index.html" method="post">
|
||||
<form id="loginform">
|
||||
{% csrf_token %}
|
||||
<input
|
||||
name="username"
|
||||
type="text"
|
||||
placeholder="Benutzername"
|
||||
id="username"
|
||||
/>
|
||||
<input
|
||||
name="password"
|
||||
type="password"
|
||||
placeholder="Passwort"
|
||||
/>
|
||||
<input name="next" type="hidden" value="{{next}}" />
|
||||
<input type="submit" placeholder="OK" value="einloggen" />
|
||||
</form>
|
||||
</div>
|
||||
|
||||
{% block content %}
|
||||
|
||||
{% addtoblock "css" strip %}<link rel="stylesheet" href="{{STATIC_URL}}css/lib/animate.css" type="text/css" media="screen, projection">{% endaddtoblock %}
|
||||
{% addtoblock "css" strip %}<link rel="stylesheet" href="{{STATIC_URL}}css/sign-in.css" type="text/css" media="screen" /> {% endaddtoblock %}
|
||||
|
||||
|
||||
{% addtoblock "js" strip %} <script src="{{STATIC_URL}}js/jquery.noty.js"></script> {% endaddtoblock %}
|
||||
{% addtoblock "css" strip %}<link rel="stylesheet" href="{{STATIC_URL}}css/jquery.noty.css" type="text/css" media="screen" /> {% endaddtoblock %}
|
||||
{% addtoblock "css" strip %}<link rel="stylesheet" href="{{STATIC_URL}}css/noty_theme_default.css" type="text/css" media="screen" /> {% endaddtoblock %}
|
||||
|
||||
<!-- for auto complete -->
|
||||
{% addtoblock "js" strip %} <script src="{{STATIC_URL}}js/jquery-ui-1.12.1.min.js"></script> {% endaddtoblock %}
|
||||
{% addtoblock "css" strip %}<link rel="stylesheet" href="{{STATIC_URL}}css/jquery-ui-1.12.1.min.css" type="text/css" media="screen" /> {% endaddtoblock %}
|
||||
|
||||
|
||||
|
||||
<!-- Notifications -->
|
||||
{% addtoblock "js" %}
|
||||
<script>
|
||||
$(document).ready(function(){
|
||||
$('#loginform').submit(function(e){
|
||||
|
||||
$.ajax({
|
||||
type:"POST",
|
||||
url:"",
|
||||
data:$('#loginform').serialize(),
|
||||
dataType: "json",
|
||||
success: function( data )
|
||||
{
|
||||
if ( data['err'] ) {
|
||||
noty ( { "text": data['err'],"layout":"top","type":"error" } )
|
||||
}
|
||||
if ( data['redirect']) {
|
||||
window.location.href = data['redirect'];
|
||||
}
|
||||
},
|
||||
error: function( jqXHR, text1, text2 ) {
|
||||
console.log( jqXHR );
|
||||
console.log( text1 );
|
||||
console.log( text2 );
|
||||
}
|
||||
});
|
||||
e.preventDefault();
|
||||
});
|
||||
|
||||
|
||||
$.get( "/musicians/login/usernames", function( data ) {
|
||||
$("#username").autocomplete( { source: data } );
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{% endaddtoblock %}
|
||||
|
||||
|
||||
|
||||
<div id="sign_in">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="span12 header">
|
||||
<h4>Login zum internen Bereich</h4>
|
||||
<p>Hier dürfen nur Ensemble Mitglieder rein... </p>
|
||||
<div class="span12 proof">
|
||||
<div class="span6 remember">
|
||||
<label class="checkbox">
|
||||
<input id="remember" type="checkbox" /> Eingeloggt
|
||||
bleiben
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="span12 footer" action="index.html" method="post">
|
||||
<form id="loginform">
|
||||
{% csrf_token %}
|
||||
<input name="username" type="text" placeholder="Benutzername" id="username">
|
||||
<input name="password" type="password" placeholder="Passwort">
|
||||
<input name="next" type="hidden" value="{{next}}" >
|
||||
<input type="submit" placeholder="OK" value="einloggen">
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="span12 proof">
|
||||
<div class="span6 remember">
|
||||
<label class="checkbox">
|
||||
<input id="remember" type="checkbox"> Eingeloggt bleiben
|
||||
</label>
|
||||
</div>
|
||||
<!--
|
||||
<!--
|
||||
<div class="span3 dosnt">
|
||||
<a href="reset.html">Passwort vergessen?</a>
|
||||
</div> -->
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
from django.conf.urls import url
|
||||
from django.urls import path
|
||||
|
||||
import musicians.views
|
||||
from . import views
|
||||
|
||||
app_name = "musicians"
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^$', musicians.views.addressbook),
|
||||
url(r'^profile$', musicians.views.own_profile),
|
||||
url(r'^changePassword/$', musicians.views.change_password),
|
||||
url(r'^login/$', musicians.views.login_view),
|
||||
url(r'^login/usernames$', musicians.views.userlistForAutocompletion),
|
||||
url(r'^logout/$', musicians.views.logout_view),
|
||||
path("", views.addressbook, name="addressbook"),
|
||||
path("profile/", views.own_profile, name="profile"),
|
||||
path("changePassword/", views.change_password, name="change_password"),
|
||||
path("login/", views.login_view, name="login"),
|
||||
path("login/usernames/", views.userlistForAutocompletion, name="usernames"),
|
||||
path("logout/", views.logout_view, name="logout"),
|
||||
]
|
||||
|
||||
@@ -1,10 +1,17 @@
|
||||
from django.views.generic.edit import UpdateView
|
||||
from django.views.generic import ListView
|
||||
from musicians.models import Musician
|
||||
import json
|
||||
from datetime import timedelta
|
||||
|
||||
from django import forms
|
||||
from django.http import HttpResponseRedirect
|
||||
from django.shortcuts import render
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.contrib.auth import authenticate, login, logout
|
||||
from django.contrib.auth.models import User
|
||||
from django.contrib.auth.views import PasswordChangeView
|
||||
from django.http import HttpResponse, HttpResponseRedirect
|
||||
from django.shortcuts import get_object_or_404, redirect, render
|
||||
from django.urls import reverse_lazy
|
||||
from django.views.generic import ListView
|
||||
from django.views.generic.edit import UpdateView
|
||||
|
||||
from .models import Musician
|
||||
|
||||
|
||||
class MusicianList(ListView):
|
||||
@@ -14,32 +21,49 @@ class MusicianList(ListView):
|
||||
class UserEditForm(forms.ModelForm):
|
||||
email = forms.EmailField()
|
||||
|
||||
def __init__(self, *args, **kw):
|
||||
|
||||
if 'instance' in kw.keys():
|
||||
user = kw['instance'].user
|
||||
initVals = {'email': user.email}
|
||||
if not 'initial' in kw.keys():
|
||||
kw['initial'] = initVals
|
||||
else:
|
||||
kw['initial'].update(initVals)
|
||||
|
||||
super(UserEditForm, self).__init__(*args, **kw)
|
||||
|
||||
self.fields.keyOrder.remove('email')
|
||||
|
||||
self.fields.keyOrder.insert(2, 'email')
|
||||
|
||||
def save(self):
|
||||
if self.is_valid():
|
||||
super(UserEditForm, self).save()
|
||||
self.instance.user.email = self.cleaned_data['email']
|
||||
self.instance.user.save()
|
||||
|
||||
class Meta:
|
||||
model = Musician
|
||||
exclude = ['user', 'image', 'small_image', 'instrument', 'position', 'public_description']
|
||||
# fields = '__all__'
|
||||
exclude = [
|
||||
"user",
|
||||
"image",
|
||||
"small_image",
|
||||
"instrument",
|
||||
"position",
|
||||
"public_description",
|
||||
]
|
||||
|
||||
def __init__(self, *args, **kw):
|
||||
if "instance" in kw:
|
||||
user = kw["instance"].user
|
||||
initVals = {"email": user.email}
|
||||
if "initial" not in kw:
|
||||
kw["initial"] = initVals
|
||||
else:
|
||||
kw["initial"].update(initVals)
|
||||
|
||||
super().__init__(*args, **kw)
|
||||
|
||||
# Reorder fields to put email near the top
|
||||
if "email" in self.fields:
|
||||
email_field = self.fields.pop("email")
|
||||
new_fields = {}
|
||||
field_names = list(self.fields.keys())
|
||||
# Insert email at position 2 (after first two fields)
|
||||
for i, name in enumerate(field_names):
|
||||
if i == 2:
|
||||
new_fields["email"] = email_field
|
||||
new_fields[name] = self.fields[name]
|
||||
if "email" not in new_fields:
|
||||
new_fields["email"] = email_field
|
||||
self.fields = new_fields
|
||||
|
||||
def save(self, commit=True):
|
||||
if self.is_valid():
|
||||
instance = super().save(commit=commit)
|
||||
self.instance.user.email = self.cleaned_data["email"]
|
||||
self.instance.user.save()
|
||||
return instance
|
||||
return None
|
||||
|
||||
|
||||
def own_profile(request):
|
||||
@@ -49,30 +73,31 @@ def own_profile(request):
|
||||
def user_edit(request, username):
|
||||
musician = get_object_or_404(Musician, user__username=username)
|
||||
|
||||
if request.method == 'POST': # If the form has been submitted...
|
||||
form = UserEditForm(request.POST) # A form bound to the POST data
|
||||
form.instance = musician
|
||||
if form.is_valid(): # All validation rules pass
|
||||
if request.method == "POST":
|
||||
form = UserEditForm(request.POST, instance=musician)
|
||||
if form.is_valid():
|
||||
form.save()
|
||||
return HttpResponseRedirect('/') # Redirect after POST
|
||||
return HttpResponseRedirect("/")
|
||||
else:
|
||||
form = UserEditForm(instance=musician)
|
||||
|
||||
return render(request, 'musicians/musician_edit.html', {'form': form, 'musician': musician})
|
||||
return render(
|
||||
request, "musicians/musician_edit.html", {"form": form, "musician": musician}
|
||||
)
|
||||
|
||||
|
||||
class MusicianUpdate(UpdateView):
|
||||
model = Musician
|
||||
# fields = []
|
||||
template_name = "musicians/musician_edit.html"
|
||||
success_url = '/books/'
|
||||
success_url = "/books/"
|
||||
fields = "__all__"
|
||||
|
||||
|
||||
def addressbook(request):
|
||||
context = dict()
|
||||
context['musicians'] = Musician.objects.all().order_by('user__first_name')
|
||||
context = {}
|
||||
context["musicians"] = Musician.objects.all().order_by("user__first_name")
|
||||
|
||||
return render(request, 'musicians/addressbook.html', context)
|
||||
return render(request, "musicians/addressbook.html", context)
|
||||
|
||||
|
||||
############################################################################################################
|
||||
@@ -80,17 +105,13 @@ def addressbook(request):
|
||||
############################################################################################################
|
||||
|
||||
|
||||
from django.contrib.auth.views import PasswordChangeView
|
||||
from django.contrib.auth import authenticate, login, logout
|
||||
from django.shortcuts import redirect
|
||||
from django.http import HttpResponse
|
||||
import json
|
||||
from django.contrib.auth.models import User
|
||||
from datetime import timedelta
|
||||
class ChangePasswordView(PasswordChangeView):
|
||||
template_name = "musicians/change_password.html"
|
||||
success_url = reverse_lazy("website:home")
|
||||
|
||||
|
||||
def change_password(request):
|
||||
return PasswordChangeView.as_view(request, "musicians/change_password.html", post_change_redirect="/")
|
||||
return ChangePasswordView.as_view()(request)
|
||||
|
||||
|
||||
def logout_view(request):
|
||||
@@ -100,47 +121,44 @@ def logout_view(request):
|
||||
|
||||
def userlistForAutocompletion(request):
|
||||
result = [u.username for u in User.objects.all()]
|
||||
return HttpResponse(json.dumps(result), content_type='application/json')
|
||||
return HttpResponse(json.dumps(result), content_type="application/json")
|
||||
|
||||
|
||||
def login_view(request):
|
||||
if request.method == 'POST': # If the form has been submitted...
|
||||
raise_first_letter = lambda s: s[:1].upper() + s[1:] if s else ''
|
||||
username = raise_first_letter(request.POST['username'])
|
||||
password = request.POST['password']
|
||||
user = authenticate(username=username, password=password)
|
||||
result = dict()
|
||||
result['err'] = ""
|
||||
if request.method == "POST":
|
||||
raiseFirstLetter = lambda s: s[:1].upper() + s[1:] if s else ""
|
||||
username = raiseFirstLetter(request.POST.get("username", ""))
|
||||
password = request.POST.get("password", "")
|
||||
user = authenticate(request, username=username, password=password)
|
||||
result = {}
|
||||
result["err"] = ""
|
||||
if user is not None:
|
||||
if user.is_active:
|
||||
if not request.POST.get('remember', None):
|
||||
if not request.POST.get("remember", None):
|
||||
# Expire in one year
|
||||
request.session.set_expiry(timedelta(weeks=52).seconds)
|
||||
request.session.set_expiry(timedelta(weeks=52))
|
||||
else:
|
||||
# Expire on browser close
|
||||
request.session.set_expiry(0)
|
||||
|
||||
login(request, user)
|
||||
result['redirect'] = "/"
|
||||
print("Setting Redirect")
|
||||
if 'next' in request.POST:
|
||||
result['redirect'] = request.POST["next"]
|
||||
print("Using " + request.POST["next"])
|
||||
result["redirect"] = "/"
|
||||
if "next" in request.POST:
|
||||
result["redirect"] = request.POST["next"]
|
||||
else:
|
||||
result['err'] = "Dein Account wurde deaktiviert."
|
||||
# Return a 'disabled account' error message
|
||||
result["err"] = "Dein Account wurde deaktiviert."
|
||||
else:
|
||||
result['err'] = "Falscher Benutzername oder falsches Kennwort."
|
||||
result["err"] = "Falscher Benutzername oder falsches Kennwort."
|
||||
|
||||
return HttpResponse(json.dumps(result), content_type='application/json')
|
||||
return HttpResponse(json.dumps(result), content_type="application/json")
|
||||
|
||||
else:
|
||||
# Check if user already logged in
|
||||
if request.user.is_authenticated:
|
||||
return redirect("/")
|
||||
|
||||
if 'next' in request.GET:
|
||||
nextPage = request.GET['next']
|
||||
if "next" in request.GET:
|
||||
nextPage = request.GET["next"]
|
||||
else:
|
||||
nextPage = "/"
|
||||
return render(request, 'musicians/login.html', {'next': nextPage})
|
||||
return render(request, "musicians/login.html", {"next": nextPage})
|
||||
|
||||
Reference in New Issue
Block a user