Move to consistent use of spaces instead of tabs

Required for python3 transition
This commit is contained in:
Sebastian Lohff 2020-01-26 11:36:47 +01:00
parent c9cff07432
commit ba9c99e0ce
8 changed files with 618 additions and 620 deletions

View File

@ -13,148 +13,148 @@ from .forms import QSOFormWithTime
import re import re
def parseCBR(raw): def parseCBR(raw):
""" Parse a CBR file for the CQTU """ Parse a CBR file for the CQTU
Yes, this could be used for other tools, BUT you'd have to take Yes, this could be used for other tools, BUT you'd have to take
look at the regex and parsingfoo, as there is some cqtu specific foo look at the regex and parsingfoo, as there is some cqtu specific foo
inside them. inside them.
""" """
kvlinere = re.compile(r"^(?P<key>[A-Z-]+):(?: (?P<value>.*))?$") kvlinere = re.compile(r"^(?P<key>[A-Z-]+):(?: (?P<value>.*))?$")
qsore = re.compile(r"^(?P<band>144|432)\s+(?P<mode>[A-Z]{2})\s+(?P<datetime>\d{4}-\d{2}-\d{2} \d{4}) (?P<call_s>[A-Z0-9/-]+)\s+(?P<rst_s>\d{2,3})\s+(?P<exc_s>[A-Z0-9-]+)\s+(?P<call_r>[A-Z0-9/-]+)\s+(?P<rst_r>\d{2,3})\s+(?P<exc_r>[A-Z0-9-]+)\s+0$") qsore = re.compile(r"^(?P<band>144|432)\s+(?P<mode>[A-Z]{2})\s+(?P<datetime>\d{4}-\d{2}-\d{2} \d{4}) (?P<call_s>[A-Z0-9/-]+)\s+(?P<rst_s>\d{2,3})\s+(?P<exc_s>[A-Z0-9-]+)\s+(?P<call_r>[A-Z0-9/-]+)\s+(?P<rst_r>\d{2,3})\s+(?P<exc_r>[A-Z0-9-]+)\s+0$")
qsoNo = 1 qsoNo = 1
info = { info = {
"call": None, "call": None,
"location": None, "location": None,
"qsos": [], "qsos": [],
} }
for n, line in enumerate(raw.split("\n"), 1): for n, line in enumerate(raw.split("\n"), 1):
line = line.strip() line = line.strip()
# ignore empty lines # ignore empty lines
if line == "": if line == "":
continue continue
m = kvlinere.match(line) m = kvlinere.match(line)
if m: if m:
k = m.group("key") k = m.group("key")
if k == "CALLSIGN": if k == "CALLSIGN":
info["call"] = m.group("value").strip().upper() info["call"] = m.group("value").strip().upper()
elif k == "LOCATION": elif k == "LOCATION":
info["location"] = m.group("value").strip().upper() info["location"] = m.group("value").strip().upper()
elif k == "QSO": elif k == "QSO":
q = m.group("value").strip() q = m.group("value").strip()
# no-s FM date UTC-HHMM call rst-s exch-s call-r rst-r exch-r # no-s FM date UTC-HHMM call rst-s exch-s call-r rst-r exch-r
# no-s / date UTC-HH-MM call rst-s # no-s / date UTC-HH-MM call rst-s
qm = qsore.search(q) qm = qsore.search(q)
if qm: if qm:
qsoData = qm.groupdict() qsoData = qm.groupdict()
qsoTime = timezone.datetime.strptime(qsoData["datetime"], "%Y-%m-%d %H%M") qsoTime = timezone.datetime.strptime(qsoData["datetime"], "%Y-%m-%d %H%M")
qsoData["datetime"] = timezone.get_current_timezone().localize(qsoTime) qsoData["datetime"] = timezone.get_current_timezone().localize(qsoTime)
qsoData["no_s"] = qsoNo qsoData["no_s"] = qsoNo
if qsoData["band"] == "144": if qsoData["band"] == "144":
qsoData["band"] = "2m" qsoData["band"] = "2m"
elif qsoData["band"] == "432": elif qsoData["band"] == "432":
qsoData["band"] = "70cm" qsoData["band"] = "70cm"
else: else:
raise forms.ValidationError("Error parsing band, needs to be either 144 or 432 (as we only support 2m and 70cm in this contest") raise forms.ValidationError("Error parsing band, needs to be either 144 or 432 (as we only support 2m and 70cm in this contest")
info["qsos"].append(qsoData) info["qsos"].append(qsoData)
if info["call"] != qsoData["call_s"]: if info["call"] != qsoData["call_s"]:
raise forms.ValidationError("Error in line %d: qso was not made by you? (callsigns do not match)" % n) raise forms.ValidationError("Error in line %d: qso was not made by you? (callsigns do not match)" % n)
if info["location"] != qsoData["exc_s"]: if info["location"] != qsoData["exc_s"]:
raise forms.ValidationError("Error in line %d: exchange does not match your location? (callsigns do not match)" % n) raise forms.ValidationError("Error in line %d: exchange does not match your location? (callsigns do not match)" % n)
else: else:
raise forms.ValidationError("Error in line %d: qso was broken, regex did not match" % n) raise forms.ValidationError("Error in line %d: qso was broken, regex did not match" % n)
qsoNo += 1 qsoNo += 1
elif k == "X-QSO": elif k == "X-QSO":
qsoNo += 1 qsoNo += 1
else: else:
raise forms.ValidationError("Error in line %d: could not parse \"KEY: value\" pair" % n) raise forms.ValidationError("Error in line %d: could not parse \"KEY: value\" pair" % n)
return info return info
class CBRForm(forms.Form): class CBRForm(forms.Form):
data = forms.CharField(widget=forms.Textarea, label="Cabrillo data", help_text="Paste your cabrillo file contents here") data = forms.CharField(widget=forms.Textarea, label="Cabrillo data", help_text="Paste your cabrillo file contents here")
def clean_data(self): def clean_data(self):
rawData = self.cleaned_data["data"] rawData = self.cleaned_data["data"]
parsedData = parseCBR(rawData) parsedData = parseCBR(rawData)
return parsedData return parsedData
def checkCBRConsistency(contest, user, info): def checkCBRConsistency(contest, user, info):
errors = [] errors = []
qsos = [] qsos = []
if user.username != info["call"]: if user.username != info["call"]:
errors.append("You are not the owner of this logfile! (%s != %s)" % (user.username, info["call"])) errors.append("You are not the owner of this logfile! (%s != %s)" % (user.username, info["call"]))
if user.ref.name != info["location"]: if user.ref.name != info["location"]:
errors.append("Location of logfile and registered exchange do not match! (%s != %s)" % (user.ref.name, info["location"])) errors.append("Location of logfile and registered exchange do not match! (%s != %s)" % (user.ref.name, info["location"]))
for n, qsoData in enumerate(info["qsos"], 1): for n, qsoData in enumerate(info["qsos"], 1):
qsoFormData = { qsoFormData = {
#"owner": user, #"owner": user,
"time": qsoData["datetime"], "time": qsoData["datetime"],
"call": qsoData["call_r"], "call": qsoData["call_r"],
"band": Band.objects.get(contest=contest, name=qsoData["band"]).id, "band": Band.objects.get(contest=contest, name=qsoData["band"]).id,
"reportTX": qsoData["rst_s"], "reportTX": qsoData["rst_s"],
"reportRX": qsoData["rst_r"], "reportRX": qsoData["rst_r"],
"ownNo": qsoData["no_s"], "ownNo": qsoData["no_s"],
"otherNo": None, "otherNo": None,
"refStr": qsoData["exc_r"], "refStr": qsoData["exc_r"],
"remarks": "", "remarks": "",
} }
qsoForm = QSOFormWithTime(user, data=qsoFormData) qsoForm = QSOFormWithTime(user, data=qsoFormData)
qsoForm.is_valid() qsoForm.is_valid()
qsoForm.instance.owner = user qsoForm.instance.owner = user
print(qsoForm.errors) print(qsoForm.errors)
qsos.append((qsoForm.instance, qsoForm)) qsos.append((qsoForm.instance, qsoForm))
return qsos, errors return qsos, errors
@login_required @login_required
def uploadCBR(request): def uploadCBR(request):
if not request.user.ref: if not request.user.ref:
return HttpResponseRedirect(reverse("contest:index")) return HttpResponseRedirect(reverse("contest:index"))
contest = Contest.objects.get(id=1) contest = Contest.objects.get(id=1)
deadline = False deadline = False
form = None form = None
verifyData = [] verifyData = []
verifyErrors = [] verifyErrors = []
save = saved = False save = saved = False
if timezone.now() < contest.deadline: if timezone.now() < contest.deadline:
if request.method == "POST": if request.method == "POST":
form = CBRForm(data=request.POST) form = CBRForm(data=request.POST)
if form.is_valid(): if form.is_valid():
verifyData, verifyErrors = checkCBRConsistency(contest, request.user, form.cleaned_data["data"]) verifyData, verifyErrors = checkCBRConsistency(contest, request.user, form.cleaned_data["data"])
if request.POST.get("action") == "save": if request.POST.get("action") == "save":
save = True save = True
if not verifyErrors: if not verifyErrors:
cnt = 0 cnt = 0
for qso, qsoForm in verifyData: for qso, qsoForm in verifyData:
if qsoForm.is_valid(): if qsoForm.is_valid():
qso.save() qso.save()
cnt += 1 cnt += 1
if cnt > 0: if cnt > 0:
messages.success(request, "%d QSOs have been saved from the cbr file" % cnt) messages.success(request, "%d QSOs have been saved from the cbr file" % cnt)
else: else:
messages.warnnig(request, "CBR file was parsed, but no QSOs could be saved, as all cointained errors.") messages.warnnig(request, "CBR file was parsed, but no QSOs could be saved, as all cointained errors.")
return HttpResponseRedirect(reverse("contest:uploadCBR")) return HttpResponseRedirect(reverse("contest:uploadCBR"))
else: else:
form = CBRForm() form = CBRForm()
else: else:
deadline = True deadline = True
return render(request, "contest/uploadCBR.html", {"deadline": deadline, 'form': form, 'verifyData': verifyData, 'verifyErrors': verifyErrors, 'save': save, 'saved': saved}) return render(request, "contest/uploadCBR.html", {"deadline": deadline, 'form': form, 'verifyData': verifyData, 'verifyErrors': verifyErrors, 'save': save, 'saved': saved})

View File

@ -10,165 +10,165 @@ from .models import User, Reference, QSO, ShadowCall, EntryCategory, Contest
from .validators import CallUsernameValidator, CallLogValidator from .validators import CallUsernameValidator, CallLogValidator
class CustomUserCreationForm(UserCreationForm): class CustomUserCreationForm(UserCreationForm):
class Meta: class Meta:
model = User model = User
fields = ("username", "email", "dncall", "qrv2m", "qrv70cm", "extra2m70cm") fields = ("username", "email", "dncall", "qrv2m", "qrv70cm", "extra2m70cm")
username = forms.CharField(max_length=50, validators=[CallUsernameValidator()]) username = forms.CharField(max_length=50, validators=[CallUsernameValidator()])
email = forms.EmailField(required=True) email = forms.EmailField(required=True)
class UpdateRefForm(forms.Form): class UpdateRefForm(forms.Form):
existingRef = forms.ModelChoiceField(label="Existing Exchange", queryset=Reference.objects.all(), help_text="If exchange already exists, select it here.", required=False) existingRef = forms.ModelChoiceField(label="Existing Exchange", queryset=Reference.objects.all(), help_text="If exchange already exists, select it here.", required=False)
newRefName = forms.CharField(max_length=50, label="New Exchange", help_text="Enter name of new exchange, if we should create a new", required=False) newRefName = forms.CharField(max_length=50, label="New Exchange", help_text="Enter name of new exchange, if we should create a new", required=False)
location = forms.CharField(max_length=128, label='Exact Location', help_text="E.g. MAR bei den Fahrstuehlen, TEL 15. OG", required=False) location = forms.CharField(max_length=128, label='Exact Location', help_text="E.g. MAR bei den Fahrstuehlen, TEL 15. OG", required=False)
opName = forms.CharField(max_length=128, label='Operators', help_text="Name of operator(s)", required=False) opName = forms.CharField(max_length=128, label='Operators', help_text="Name of operator(s)", required=False)
regTime = forms.DateTimeField(label="Registration time", help_text="Time of Registration") regTime = forms.DateTimeField(label="Registration time", help_text="Time of Registration")
def clean_newRefName(self): def clean_newRefName(self):
data = self.cleaned_data["newRefName"].strip().upper() data = self.cleaned_data["newRefName"].strip().upper()
return data return data
def clean(self): def clean(self):
cleaned_data = super(UpdateRefForm, self).clean() cleaned_data = super(UpdateRefForm, self).clean()
existingRef = cleaned_data.get("existingRef") existingRef = cleaned_data.get("existingRef")
newRefName = cleaned_data.get("newRefName") newRefName = cleaned_data.get("newRefName")
if newRefName: if newRefName:
try: try:
ref = Reference.objects.get(name=newRefName) ref = Reference.objects.get(name=newRefName)
self.cleaned_data['newRefName'] = None self.cleaned_data['newRefName'] = None
self.cleaned_data['existingRef'] = ref self.cleaned_data['existingRef'] = ref
except Reference.DoesNotExist: except Reference.DoesNotExist:
pass pass
if existingRef and newRefName: if existingRef and newRefName:
raise forms.ValidationError("Select an existing exchange or create a new one, not both!") raise forms.ValidationError("Select an existing exchange or create a new one, not both!")
if not existingRef and not newRefName: if not existingRef and not newRefName:
raise forms.ValidationError("Select either an existing exchange or create a new one!") raise forms.ValidationError("Select either an existing exchange or create a new one!")
class UpdateCategoryForm(forms.Form): class UpdateCategoryForm(forms.Form):
entry = forms.ModelChoiceField(label="Entry category", queryset=EntryCategory.objects.all()) entry = forms.ModelChoiceField(label="Entry category", queryset=EntryCategory.objects.all())
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(UpdateCategoryForm, self).__init__(*args, **kwargs) super(UpdateCategoryForm, self).__init__(*args, **kwargs)
self.helper = FormHelper() self.helper = FormHelper()
self.helper.form_class = "form-inline " self.helper.form_class = "form-inline "
self.helper.form_style = 'inline' self.helper.form_style = 'inline'
self.helper.field_template = "bootstrap3/layout/inline_field.html" self.helper.field_template = "bootstrap3/layout/inline_field.html"
self.helper.action = reverse("profile") self.helper.action = reverse("profile")
self.helper.add_input(Submit('submit', 'Set category')) self.helper.add_input(Submit('submit', 'Set category'))
self.helper.layout = Layout('entry') self.helper.layout = Layout('entry')
def clean(self): def clean(self):
contest = Contest.objects.get(id=1) contest = Contest.objects.get(id=1)
if contest.deadline < timezone.now(): if contest.deadline < timezone.now():
raise forms.ValidationError("The deadline for setting your contest category has passed") raise forms.ValidationError("The deadline for setting your contest category has passed")
class QSOForm(forms.ModelForm): class QSOForm(forms.ModelForm):
class Meta: class Meta:
model = QSO model = QSO
#fields = ["ownNo", "band", "call", "reportTX", "reportRX", "refStr", "otherNo", "remarks"] #fields = ["ownNo", "band", "call", "reportTX", "reportRX", "refStr", "otherNo", "remarks"]
fields = ["ownNo", "band", "call", "reportTX", "reportRX", "refStr", "remarks"] fields = ["ownNo", "band", "call", "reportTX", "reportRX", "refStr", "remarks"]
def __init__(self, user, *args, **kwargs): def __init__(self, user, *args, **kwargs):
super(QSOForm, self).__init__(*args, **kwargs) super(QSOForm, self).__init__(*args, **kwargs)
self.user = user self.user = user
self.helper = FormHelper() self.helper = FormHelper()
self.helper.form_id = "qso-log-form" self.helper.form_id = "qso-log-form"
#self.helper.form_class = "form-inline " #self.helper.form_class = "form-inline "
#self.helper.form_class = "form-horizontal" #self.helper.form_class = "form-horizontal"
#self.helper.form_style = 'inline' #self.helper.form_style = 'inline'
#self.helper.field_template = "bootstrap3/layout/inline_field.html" #self.helper.field_template = "bootstrap3/layout/inline_field.html"
self.helper.action = reverse("contest:log") self.helper.action = reverse("contest:log")
self.helper.add_input(Submit('submit', 'Log')) self.helper.add_input(Submit('submit', 'Log'))
#self.helper.layout = Layout( #self.helper.layout = Layout(
# #*(QSOForm.Meta.fields + [ButtonHolder(Submit('submit', 'Submit', css_class='button white'))])) # #*(QSOForm.Meta.fields + [ButtonHolder(Submit('submit', 'Submit', css_class='button white'))]))
# *(QSOForm.Meta.fields + [FormActions(Submit('submit', 'Log!'))])) # *(QSOForm.Meta.fields + [FormActions(Submit('submit', 'Log!'))]))
def clean_call(self): def clean_call(self):
data = self.cleaned_data["call"].upper().strip() data = self.cleaned_data["call"].upper().strip()
if Reference.objects.filter(name=data).count() > 0: if Reference.objects.filter(name=data).count() > 0:
raise forms.ValidationError("Reference already exists") raise forms.ValidationError("Reference already exists")
try: try:
CallLogValidator()(data) CallLogValidator()(data)
except forms.ValidationError: except forms.ValidationError:
raise forms.ValidationError("Enter a valid callsign (1-2 chars, a number, 1-4 chars, maybe a /[A-Z])") raise forms.ValidationError("Enter a valid callsign (1-2 chars, a number, 1-4 chars, maybe a /[A-Z])")
if data == self.user.username: if data == self.user.username:
raise forms.ValidationError("You cannot log QSOs with yourself") raise forms.ValidationError("You cannot log QSOs with yourself")
return data return data
def clean_ownNo(self): def clean_ownNo(self):
data = self.cleaned_data["ownNo"] data = self.cleaned_data["ownNo"]
if data < 1 or data > 100000: if data < 1 or data > 100000:
raise forms.ValidationError("Number has to be in range of [1, 1000000]") raise forms.ValidationError("Number has to be in range of [1, 1000000]")
try: try:
o = QSO.objects.get(owner=self.user.id, ownNo=data) o = QSO.objects.get(owner=self.user.id, ownNo=data)
if not (self.instance and self.instance.id and self.instance.id == o.id): if not (self.instance and self.instance.id and self.instance.id == o.id):
raise forms.ValidationError("You already logged a QSO with the number %s" % data) raise forms.ValidationError("You already logged a QSO with the number %s" % data)
except QSO.DoesNotExist: except QSO.DoesNotExist:
pass pass
return data return data
def clean_otherNo(self): def clean_otherNo(self):
data = self.cleaned_data["otherNo"] data = self.cleaned_data["otherNo"]
if not data: if not data:
# empty value # empty value
return None return None
if data < 1 or data > 100000: if data < 1 or data > 100000:
raise forms.ValidationError("Number has to be in range of [1, 1000000]") raise forms.ValidationError("Number has to be in range of [1, 1000000]")
return data return data
def clean_refStr(self): def clean_refStr(self):
return self.cleaned_data["refStr"].upper() return self.cleaned_data["refStr"].upper()
def clean(self): def clean(self):
cleaned_data = super(QSOForm, self).clean() cleaned_data = super(QSOForm, self).clean()
band = cleaned_data.get("band") band = cleaned_data.get("band")
if band.contest.deadline < timezone.now(): if band.contest.deadline < timezone.now():
raise forms.ValidationError("The deadline for logging and editing QSOs has passed") raise forms.ValidationError("The deadline for logging and editing QSOs has passed")
class QSOFormWithTime(QSOForm): class QSOFormWithTime(QSOForm):
class Meta: class Meta:
model = QSO model = QSO
#fields = ["time", "ownNo", "band", "call", "reportTX", "reportRX", "otherNo", "refStr", "remarks"] #fields = ["time", "ownNo", "band", "call", "reportTX", "reportRX", "otherNo", "refStr", "remarks"]
fields = ["time", "ownNo", "band", "call", "reportTX", "reportRX", "refStr", "remarks"] fields = ["time", "ownNo", "band", "call", "reportTX", "reportRX", "refStr", "remarks"]
class ShadowCallAddForm(forms.ModelForm): class ShadowCallAddForm(forms.ModelForm):
class Meta: class Meta:
model = ShadowCall model = ShadowCall
fields = ['username'] fields = ['username']
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(ShadowCallAddForm, self).__init__(*args, **kwargs) super(ShadowCallAddForm, self).__init__(*args, **kwargs)
self.helper = FormHelper() self.helper = FormHelper()
self.helper.form_class = "form-inline " self.helper.form_class = "form-inline "
self.helper.form_style = 'inline' self.helper.form_style = 'inline'
self.helper.field_template = "bootstrap3/layout/inline_field.html" self.helper.field_template = "bootstrap3/layout/inline_field.html"
self.helper.action = reverse("contest:registerRefs") self.helper.action = reverse("contest:registerRefs")
self.helper.add_input(Submit('submit', 'Add shadow')) self.helper.add_input(Submit('submit', 'Add shadow'))
self.helper.layout = Layout('username') self.helper.layout = Layout('username')
def clean_username(self): def clean_username(self):
data = self.cleaned_data["username"] data = self.cleaned_data["username"]
if User.objects.filter(username=data).count() > 0: if User.objects.filter(username=data).count() > 0:
raise forms.ValidationError("A user with this call already exists, this is not a shadow!") raise forms.ValidationError("A user with this call already exists, this is not a shadow!")
return data return data

View File

@ -11,236 +11,236 @@ from .validators import CallUsernameValidator
from .signals import checkForShadowCall from .signals import checkForShadowCall
class Contest(models.Model): class Contest(models.Model):
name = models.CharField(max_length=20) name = models.CharField(max_length=20)
shortName = models.CharField(max_length=20, unique=True) shortName = models.CharField(max_length=20, unique=True)
callQrg = models.ForeignKey("Frequency", models.SET_NULL, null=True, blank=True) callQrg = models.ForeignKey("Frequency", models.SET_NULL, null=True, blank=True)
deadline = models.DateTimeField() deadline = models.DateTimeField()
qsoStartTime = models.DateTimeField() qsoStartTime = models.DateTimeField()
qsoEndTime = models.DateTimeField() qsoEndTime = models.DateTimeField()
def __str__(self): def __str__(self):
return self.name return self.name
class Reference(models.Model): class Reference(models.Model):
name = models.CharField(max_length=20, unique=True, db_index=True) name = models.CharField(max_length=20, unique=True, db_index=True)
description = models.TextField() description = models.TextField()
def __str__(self): def __str__(self):
return self.name return self.name
class EntryCategory(models.Model): class EntryCategory(models.Model):
name = models.CharField(max_length=64, unique=True) name = models.CharField(max_length=64, unique=True)
description = models.TextField(blank=True) description = models.TextField(blank=True)
def __str__(self): def __str__(self):
return self.name return self.name
class ShadowCall(models.Model): class ShadowCall(models.Model):
username = models.CharField(max_length=20, unique=True, db_index=True, validators=[CallUsernameValidator()]) username = models.CharField(max_length=20, unique=True, db_index=True, validators=[CallUsernameValidator()])
ref = models.ForeignKey(Reference, models.SET_NULL,null=True, blank=True) ref = models.ForeignKey(Reference, models.SET_NULL,null=True, blank=True)
location = models.CharField(max_length=128, default="", blank=True) location = models.CharField(max_length=128, default="", blank=True)
opName = models.CharField(max_length=128, default="", blank=True) opName = models.CharField(max_length=128, default="", blank=True)
regTime = models.DateTimeField(null=True, default=None) regTime = models.DateTimeField(null=True, default=None)
def __str__(self): def __str__(self):
return self.username return self.username
class User(AbstractUser): class User(AbstractUser):
ref = models.ForeignKey(Reference, models.SET_NULL, null=True, blank=True) ref = models.ForeignKey(Reference, models.SET_NULL, null=True, blank=True)
cat = models.ForeignKey(EntryCategory, models.SET_NULL, null=True, blank=True) cat = models.ForeignKey(EntryCategory, models.SET_NULL, null=True, blank=True)
location = models.CharField(max_length=128, default="", blank=True) location = models.CharField(max_length=128, default="", blank=True)
opName = models.CharField(max_length=128, default="", blank=True) opName = models.CharField(max_length=128, default="", blank=True)
regTime = models.DateTimeField(null=True, default=None) regTime = models.DateTimeField(null=True, default=None)
# because of cbr parsing bug, we sometimes have users who only have 70cm qsos # because of cbr parsing bug, we sometimes have users who only have 70cm qsos
# we ignore the band for them when checking QSOs # we ignore the band for them when checking QSOs
ignoreBand = models.BooleanField(default=False) ignoreBand = models.BooleanField(default=False)
# extra profile stuff so DL7BST can sleep well without his doodles # extra profile stuff so DL7BST can sleep well without his doodles
editedProfile = models.BooleanField(default=False) editedProfile = models.BooleanField(default=False)
dncall = models.CharField(max_length=16, default='', blank=True, dncall = models.CharField(max_length=16, default='', blank=True,
verbose_name="DN-Call", verbose_name="DN-Call",
help_text="If you have a DN call that you will offer to SWLs please enter it here") help_text="If you have a DN call that you will offer to SWLs please enter it here")
qrv2m = models.BooleanField(default=False, qrv2m = models.BooleanField(default=False,
verbose_name="QRV on 2m", verbose_name="QRV on 2m",
help_text="Will you be QRV on 2m during the contest?") help_text="Will you be QRV on 2m during the contest?")
qrv70cm = models.BooleanField(default=False, qrv70cm = models.BooleanField(default=False,
verbose_name="QRV on 70cm", verbose_name="QRV on 70cm",
help_text="Will you be QRV on 70cm during the contest?") help_text="Will you be QRV on 70cm during the contest?")
extra2m70cm = models.BooleanField(default=False, extra2m70cm = models.BooleanField(default=False,
verbose_name="Additional 2m/70cm TRX", verbose_name="Additional 2m/70cm TRX",
help_text="Will you bring an additional 2m/70cm TRX to lend to other participants?") help_text="Will you bring an additional 2m/70cm TRX to lend to other participants?")
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(User, self).__init__(*args, **kwargs) super(User, self).__init__(*args, **kwargs)
self._meta.get_field("username").validators = [CallUsernameValidator()] self._meta.get_field("username").validators = [CallUsernameValidator()]
def getQSOCount(self): def getQSOCount(self):
return self.qso_set.count() return self.qso_set.count()
def getCfmdQSOCount(self): def getCfmdQSOCount(self):
return self.qso_set.filter(~Q(cfmdQSO=None)).count() return self.qso_set.filter(~Q(cfmdQSO=None)).count()
def getCfmdRefCount(self): def getCfmdRefCount(self):
return len(set(map(lambda _x: _x["refStr"], self.qso_set.filter(ref__isnull=False).values("ref", "refStr")))) return len(set(map(lambda _x: _x["refStr"], self.qso_set.filter(ref__isnull=False).values("ref", "refStr"))))
def calcClaimedPoints(self): def calcClaimedPoints(self):
return self.calcPoints(cfmd=False) return self.calcPoints(cfmd=False)
def calcCfmdPoints(self): def calcCfmdPoints(self):
return self.calcPoints(cfmd=True) return self.calcPoints(cfmd=True)
def calcPoints(self, cfmd): def calcPoints(self, cfmd):
contest = Contest.objects.get(id=1) contest = Contest.objects.get(id=1)
result = {"refCount": 0, "qsoCount": 0} result = {"refCount": 0, "qsoCount": 0}
for band in contest.band_set.all(): for band in contest.band_set.all():
result[band.name] = self.calcBandPoints(band, cfmd) result[band.name] = self.calcBandPoints(band, cfmd)
result["refCount"] += result[band.name]["refCount"] result["refCount"] += result[band.name]["refCount"]
result["qsoCount"] += result[band.name]["qsoCount"] result["qsoCount"] += result[band.name]["qsoCount"]
result["points"] = result["qsoCount"] * result["refCount"] result["points"] = result["qsoCount"] * result["refCount"]
return result return result
def calcBandPoints(self, band, cfmd=False): def calcBandPoints(self, band, cfmd=False):
contest = band.contest contest = band.contest
qsos = self.qso_set.filter(band=band, time__gte=contest.qsoStartTime, time__lte=contest.qsoEndTime) qsos = self.qso_set.filter(band=band, time__gte=contest.qsoStartTime, time__lte=contest.qsoEndTime)
if cfmd: if cfmd:
qsos = qsos.filter(cfmdQSO__isnull=False) qsos = qsos.filter(cfmdQSO__isnull=False)
refs = set(map(lambda _x: _x["refStr"], qsos.values("refStr"))) refs = set(map(lambda _x: _x["refStr"], qsos.values("refStr")))
return { return {
"band": band, "band": band,
"refs": refs, "refs": refs,
"qsoCount": qsos.count(), "qsoCount": qsos.count(),
"refCount": len(refs) "refCount": len(refs)
} }
signals.post_save.connect(checkForShadowCall, sender=User) signals.post_save.connect(checkForShadowCall, sender=User)
class Band(models.Model): class Band(models.Model):
name = models.CharField(max_length=10) name = models.CharField(max_length=10)
contest = models.ForeignKey(Contest) contest = models.ForeignKey(Contest)
def __str__(self): def __str__(self):
return self.name return self.name
class Frequency(models.Model): class Frequency(models.Model):
# qrg # qrg
# band # band
channel = models.CharField(max_length=3) channel = models.CharField(max_length=3)
qrg = models.DecimalField(max_digits=7, decimal_places=3) qrg = models.DecimalField(max_digits=7, decimal_places=3)
band = models.ForeignKey(Band) band = models.ForeignKey(Band)
note = models.CharField(max_length=50, blank=True) note = models.CharField(max_length=50, blank=True)
def __str__(self): def __str__(self):
return "Channel %s: %s MHz" % (self.channel, self.qrg) return "Channel %s: %s MHz" % (self.channel, self.qrg)
class QSO(models.Model): class QSO(models.Model):
reportValidator = RegexValidator("[1-5][1-9]") reportValidator = RegexValidator("[1-5][1-9]")
class Meta: class Meta:
index_together = [ index_together = [
["owner", "call"], ["owner", "call"],
] ]
owner = models.ForeignKey(User, db_index=True) owner = models.ForeignKey(User, db_index=True)
time = models.DateTimeField(blank=True) time = models.DateTimeField(blank=True)
call = models.CharField(max_length=20, db_index=True) call = models.CharField(max_length=20, db_index=True)
callRef = models.ForeignKey(User, models.SET_NULL, related_name='qsoref', null=True, blank=True, default=None) callRef = models.ForeignKey(User, models.SET_NULL, related_name='qsoref', null=True, blank=True, default=None)
band = models.ForeignKey(Band) band = models.ForeignKey(Band)
reportTX = models.CharField(max_length=7, default=59, verbose_name='RS-S', validators=[reportValidator]) reportTX = models.CharField(max_length=7, default=59, verbose_name='RS-S', validators=[reportValidator])
reportRX = models.CharField(max_length=7, default=59, verbose_name='RS-R', validators=[reportValidator]) reportRX = models.CharField(max_length=7, default=59, verbose_name='RS-R', validators=[reportValidator])
ownNo = models.IntegerField(verbose_name='No') ownNo = models.IntegerField(verbose_name='No')
otherNo = models.IntegerField(verbose_name='No-R', null=True, blank=True) otherNo = models.IntegerField(verbose_name='No-R', null=True, blank=True)
refStr = models.CharField(max_length=20, verbose_name="EXC") refStr = models.CharField(max_length=20, verbose_name="EXC")
ref = models.ForeignKey(Reference, models.SET_NULL, null=True, blank=True) ref = models.ForeignKey(Reference, models.SET_NULL, null=True, blank=True)
remarks = models.CharField(max_length=50, blank=True, default=None) remarks = models.CharField(max_length=50, blank=True, default=None)
cfmdQSO = models.ForeignKey("QSO", models.SET_NULL, null=True, blank=True, default=None) cfmdQSO = models.ForeignKey("QSO", models.SET_NULL, null=True, blank=True, default=None)
CFMD_SEC = 5*60 CFMD_SEC = 5*60
def checkQSOData(self): def checkQSOData(self):
""" Match strdata to log rows. Only call, if you intent to save this object if we return True! """ """ Match strdata to log rows. Only call, if you intent to save this object if we return True! """
# find reference # find reference
changed = False changed = False
if self.refStr: if self.refStr:
refName = self.refStr.replace("-", "") refName = self.refStr.replace("-", "")
if refName == "GX": if refName == "GX":
refName = "DX" refName = "DX"
# Old reference exists? # Old reference exists?
if self.ref and self.ref.name != refName: if self.ref and self.ref.name != refName:
self.ref = None self.ref = None
changed = True changed = True
if not self.ref: if not self.ref:
# find matching ref # find matching ref
try: try:
self.ref = Reference.objects.get(name=refName) self.ref = Reference.objects.get(name=refName)
changed = True changed = True
except Reference.DoesNotExist: except Reference.DoesNotExist:
pass pass
# find call # find call
if not self.callRef or self.callRef.username != self.call: if not self.callRef or self.callRef.username != self.call:
try: try:
self.callRef = User.objects.get(username=self.call) self.callRef = User.objects.get(username=self.call)
changed = True changed = True
except User.DoesNotExist: except User.DoesNotExist:
if self.callRef: if self.callRef:
changed = True changed = True
self.callRef = None self.callRef = None
# find matching qso # find matching qso
if self.cfmdQSO: if self.cfmdQSO:
# check if this still checks out # check if this still checks out
q = self.cfmdQSO q = self.cfmdQSO
if abs((self.time - q.time).total_seconds()) <= self.CFMD_SEC and \ if abs((self.time - q.time).total_seconds()) <= self.CFMD_SEC and \
self.ref and self.owner.ref and self.callRef and q.callRef and \ self.ref and self.owner.ref and self.callRef and q.callRef and \
q.owner == self.callRef and q.callRef == self.owner and \ q.owner == self.callRef and q.callRef == self.owner and \
self.ref == q.owner.ref and self.owner.ref == q.ref and \ self.ref == q.owner.ref and self.owner.ref == q.ref and \
self.band == q.band: self.band == q.band:
# checks out # checks out
pass pass
else: else:
changed = True changed = True
self.cfmdQSO.cfmdQSO = None self.cfmdQSO.cfmdQSO = None
self.cfmdQSO.save(checkQSO=False) self.cfmdQSO.save(checkQSO=False)
self.cfmdQSO = None self.cfmdQSO = None
if self.ref and self.callRef and self.callRef.ref and not self.cfmdQSO: if self.ref and self.callRef and self.callRef.ref and not self.cfmdQSO:
# look for a matching line # look for a matching line
q = QSO.objects.filter( q = QSO.objects.filter(
(Q(time__lte=self.time + datetime.timedelta(seconds=self.CFMD_SEC)) & Q(time__gte=self.time - datetime.timedelta(seconds=self.CFMD_SEC))), (Q(time__lte=self.time + datetime.timedelta(seconds=self.CFMD_SEC)) & Q(time__gte=self.time - datetime.timedelta(seconds=self.CFMD_SEC))),
owner=self.callRef, owner=self.callRef,
callRef=self.owner, callRef=self.owner,
owner__ref=self.ref, owner__ref=self.ref,
ref=self.owner.ref, ref=self.owner.ref,
band=self.band) band=self.band)
if q.count() == 1: if q.count() == 1:
changed = True changed = True
q[0].cfmdQSO = self q[0].cfmdQSO = self
q[0].save(checkQSO=False) q[0].save(checkQSO=False)
self.cfmdQSO = q[0] self.cfmdQSO = q[0]
return changed return changed
def save(self, checkQSO=True, *args, **kwargs): def save(self, checkQSO=True, *args, **kwargs):
if checkQSO: if checkQSO:
self.checkQSOData() self.checkQSOData()
super(QSO, self).save(*args, **kwargs) super(QSO, self).save(*args, **kwargs)
def __str__(self): def __str__(self):
return "QSO no %s at %s on band %s from %s with %s@%s %s/%s" % (self.ownNo, self.time.strftime("%H:%M"), self.band, self.owner.username, self.call, self.refStr, self.reportTX, self.reportRX) return "QSO no %s at %s on band %s from %s with %s@%s %s/%s" % (self.ownNo, self.time.strftime("%H:%M"), self.band, self.owner.username, self.call, self.refStr, self.reportTX, self.reportRX)

View File

@ -1,18 +1,18 @@
def checkForShadowCall(sender, instance, created, raw, **kwargs): def checkForShadowCall(sender, instance, created, raw, **kwargs):
""" Check for existing shadow call. If present copy it's data and delete it. """ """ Check for existing shadow call. If present copy it's data and delete it. """
if created: if created:
# to prevent circular imports we import ShadowCall here # to prevent circular imports we import ShadowCall here
from .models import ShadowCall from .models import ShadowCall
try: try:
shadow = ShadowCall.objects.get(username=instance.username) shadow = ShadowCall.objects.get(username=instance.username)
instance.ref = shadow.ref instance.ref = shadow.ref
instance.location = shadow.location instance.location = shadow.location
instance.opName = shadow.opName instance.opName = shadow.opName
instance.regTime = shadow.regTime instance.regTime = shadow.regTime
instance.save() instance.save()
shadow.delete() shadow.delete()
except ShadowCall.DoesNotExist: except ShadowCall.DoesNotExist:
pass pass

View File

@ -20,16 +20,16 @@ import contest.views as contest_views
from contest.cbrparser import uploadCBR from contest.cbrparser import uploadCBR
urlpatterns = [ urlpatterns = [
url(r'^$', contest_views.contestIndex, name='index'), url(r'^$', contest_views.contestIndex, name='index'),
url(r'^regref/$', contest_views.registerRefs, name='registerRefs'), url(r'^regref/$', contest_views.registerRefs, name='registerRefs'),
url(r'^regref/edit/(?P<uid>\d+)/$', contest_views.updateRef, {"shadow": False}, name='updateRef'), url(r'^regref/edit/(?P<uid>\d+)/$', contest_views.updateRef, {"shadow": False}, name='updateRef'),
url(r'^regref/shadow/edit/(?P<uid>\d+)/$', contest_views.updateRef, {"shadow": True}, name='updateShadowRef'), url(r'^regref/shadow/edit/(?P<uid>\d+)/$', contest_views.updateRef, {"shadow": True}, name='updateShadowRef'),
url(r'^regref/qsos/all/$', contest_views.viewAllQSOs, name='viewAllQSOs'), url(r'^regref/qsos/all/$', contest_views.viewAllQSOs, name='viewAllQSOs'),
url(r'^regref/qsos/user/(?P<uid>\d+)/$', contest_views.viewUserQSOs, name='viewUserQSOs'), url(r'^regref/qsos/user/(?P<uid>\d+)/$', contest_views.viewUserQSOs, name='viewUserQSOs'),
url(r'^overview/$', contest_views.overview, name='overview'), url(r'^overview/$', contest_views.overview, name='overview'),
url(r'^log/$', contest_views.log, name='log'), url(r'^log/$', contest_views.log, name='log'),
url(r'^log/edit/(?P<qsoid>\d+)/$', contest_views.logEdit, name='logEdit'), url(r'^log/edit/(?P<qsoid>\d+)/$', contest_views.logEdit, name='logEdit'),
url(r'^log/delete/(?P<qsoid>\d+)/$', contest_views.logDelete, name='logDelete'), url(r'^log/delete/(?P<qsoid>\d+)/$', contest_views.logDelete, name='logDelete'),
url(r'^uploadcbr/$', uploadCBR, name='uploadCBR'), url(r'^uploadcbr/$', uploadCBR, name='uploadCBR'),
url(r'^regref/recheckqsos/$', contest_views.recheckAllQSOs, name='recheckAllQSOs'), url(r'^regref/recheckqsos/$', contest_views.recheckAllQSOs, name='recheckAllQSOs'),
] ]

View File

@ -19,251 +19,251 @@ from .models import User, Contest, Frequency, Reference, QSO, ShadowCall
from .forms import UpdateRefForm, QSOForm, QSOFormWithTime, CustomUserCreationForm, ShadowCallAddForm, UpdateCategoryForm from .forms import UpdateRefForm, QSOForm, QSOFormWithTime, CustomUserCreationForm, ShadowCallAddForm, UpdateCategoryForm
def index(request): def index(request):
if request.user.is_authenticated(): if request.user.is_authenticated():
return HttpResponseRedirect(reverse("contest:index")) return HttpResponseRedirect(reverse("contest:index"))
return render(request, "index.html", {"loginForm": AuthenticationForm()}) return render(request, "index.html", {"loginForm": AuthenticationForm()})
@login_required @login_required
def contestIndex(request): def contestIndex(request):
qsoform = QSOForm(request.user) qsoform = QSOForm(request.user)
contest = Contest.objects.get(id=1) contest = Contest.objects.get(id=1)
qrgs = Frequency.objects.filter(band__contest=contest).order_by("channel") qrgs = Frequency.objects.filter(band__contest=contest).order_by("channel")
return render(request, 'contest/index.html', {"qsoform": qsoform, "contest": contest, "qrgs": qrgs}) return render(request, 'contest/index.html', {"qsoform": qsoform, "contest": contest, "qrgs": qrgs})
@login_required @login_required
def log(request): def log(request):
if not request.user.ref: if not request.user.ref:
return HttpResponseRedirect(reverse("contest:index")) return HttpResponseRedirect(reverse("contest:index"))
form = None form = None
qsos = QSO.objects.filter(owner=request.user).order_by("-ownNo") qsos = QSO.objects.filter(owner=request.user).order_by("-ownNo")
if request.method == 'POST': if request.method == 'POST':
form = QSOForm(user=request.user, data=request.POST) form = QSOForm(user=request.user, data=request.POST)
form.helper.form_tag = False form.helper.form_tag = False
if form.is_valid(): if form.is_valid():
l = form.instance l = form.instance
if not l.time: if not l.time:
# set current time # set current time
l.time = datetime.datetime.now() l.time = datetime.datetime.now()
l.owner = request.user l.owner = request.user
l.save() l.save()
messages.success(request, "QSO saved!") messages.success(request, "QSO saved!")
return HttpResponseRedirect(reverse("contest:log")) return HttpResponseRedirect(reverse("contest:log"))
else: else:
data = { data = {
"ownNo": qsos[0].ownNo + 1 if len(qsos) > 0 else 1, "ownNo": qsos[0].ownNo + 1 if len(qsos) > 0 else 1,
"reportRX": "59", "reportRX": "59",
"reportTX": "59", "reportTX": "59",
} }
if qsos.count() > 0: if qsos.count() > 0:
data["band"] = qsos[0].band data["band"] = qsos[0].band
form = QSOForm(request.user, initial=data) form = QSOForm(request.user, initial=data)
form.helper.form_tag = False form.helper.form_tag = False
return render(request, 'contest/log.html', {'form': form, 'qsos': qsos}) return render(request, 'contest/log.html', {'form': form, 'qsos': qsos})
@login_required @login_required
def logEdit(request, qsoid): def logEdit(request, qsoid):
if not request.user.ref: if not request.user.ref:
return HttpResponseRedirect(reverse("contest:index")) return HttpResponseRedirect(reverse("contest:index"))
qso = QSO.objects.get(id=qsoid, owner=request.user) qso = QSO.objects.get(id=qsoid, owner=request.user)
form = None form = None
if request.method == 'POST': if request.method == 'POST':
form = QSOFormWithTime(user=request.user, instance=qso, data=request.POST) form = QSOFormWithTime(user=request.user, instance=qso, data=request.POST)
if form.is_valid(): if form.is_valid():
form.instance.save() form.instance.save()
messages.info(request, "QSO has been edited") messages.info(request, "QSO has been edited")
return HttpResponseRedirect(reverse("contest:log")) return HttpResponseRedirect(reverse("contest:log"))
else: else:
form = QSOFormWithTime(user=request.user, instance=qso) form = QSOFormWithTime(user=request.user, instance=qso)
return render(request, 'contest/logEdit.html', {'form': form, "qso": qso}) return render(request, 'contest/logEdit.html', {'form': form, "qso": qso})
def logDelete(request, qsoid): def logDelete(request, qsoid):
if not request.user.ref: if not request.user.ref:
return HttpResponseRedirect(reverse("contest:index")) return HttpResponseRedirect(reverse("contest:index"))
qso = QSO.objects.get(id=qsoid, owner=request.user) qso = QSO.objects.get(id=qsoid, owner=request.user)
if request.method == 'POST': if request.method == 'POST':
if "delete" in request.POST: if "delete" in request.POST:
if request.POST["delete"].lower() == "yes": if request.POST["delete"].lower() == "yes":
qso.delete() qso.delete()
messages.info(request, "QSO has been deleted") messages.info(request, "QSO has been deleted")
return HttpResponseRedirect(reverse("contest:log")) return HttpResponseRedirect(reverse("contest:log"))
elif request.POST["delete"].lower() == "no": elif request.POST["delete"].lower() == "no":
return HttpResponseRedirect(reverse("contest:log")) return HttpResponseRedirect(reverse("contest:log"))
return render(request, 'contest/logDelete.html', {"qso": qso}) return render(request, 'contest/logDelete.html', {"qso": qso})
@staff_member_required @staff_member_required
def registerRefs(request): def registerRefs(request):
allUser = User.objects.all() allUser = User.objects.all()
shadows = ShadowCall.objects.all() shadows = ShadowCall.objects.all()
qsos = QSO.objects.all().order_by("-time")[0:10] qsos = QSO.objects.all().order_by("-time")[0:10]
shadowForm = None shadowForm = None
if request.method == 'POST': if request.method == 'POST':
shadowForm = ShadowCallAddForm(data=request.POST) shadowForm = ShadowCallAddForm(data=request.POST)
if shadowForm.is_valid(): if shadowForm.is_valid():
shadowForm.instance.save() shadowForm.instance.save()
messages.success(request, "Successfully added shadow user %s" % (shadowForm.instance.username,)) messages.success(request, "Successfully added shadow user %s" % (shadowForm.instance.username,))
return HttpResponseRedirect(reverse("contest:registerRefs")) return HttpResponseRedirect(reverse("contest:registerRefs"))
else: else:
shadowForm = ShadowCallAddForm() shadowForm = ShadowCallAddForm()
return render(request, 'contest/registerRefs.html', {'alluser': allUser, "qsos": qsos, "shadowForm": shadowForm, "shadows": shadows}) return render(request, 'contest/registerRefs.html', {'alluser': allUser, "qsos": qsos, "shadowForm": shadowForm, "shadows": shadows})
def getPage(paginator, pageNo): def getPage(paginator, pageNo):
try: try:
return paginator.page(pageNo) return paginator.page(pageNo)
except PageNotAnInteger: except PageNotAnInteger:
return paginator.page(1) return paginator.page(1)
except EmptyPage: except EmptyPage:
return paginator.page(paginator.num_pages) return paginator.page(paginator.num_pages)
@staff_member_required @staff_member_required
def recheckAllQSOs(request): def recheckAllQSOs(request):
if request.method == "POST": if request.method == "POST":
cnt = 0 cnt = 0
for qso in QSO.objects.all(): for qso in QSO.objects.all():
if qso.checkQSOData(): if qso.checkQSOData():
print(qso) print(qso)
qso.save() qso.save()
cnt += 1 cnt += 1
messages.success(request, "Allo QSO have been checked against each other (%d QSOs modified)" % (cnt,)) messages.success(request, "Allo QSO have been checked against each other (%d QSOs modified)" % (cnt,))
return HttpResponseRedirect(reverse("contest:registerRefs")) return HttpResponseRedirect(reverse("contest:registerRefs"))
return render(request, "contest/checkAllQSOs.html", {}) return render(request, "contest/checkAllQSOs.html", {})
@staff_member_required @staff_member_required
def viewUserQSOs(request, uid, page=1): def viewUserQSOs(request, uid, page=1):
user = get_object_or_404(User, id=uid) user = get_object_or_404(User, id=uid)
qsos = QSO.objects.filter(owner=user).order_by("-time") qsos = QSO.objects.filter(owner=user).order_by("-time")
qsoPager = Paginator(qsos, 50) qsoPager = Paginator(qsos, 50)
qsoPage = getPage(qsoPager, request.GET.get('page')) qsoPage = getPage(qsoPager, request.GET.get('page'))
userRefs = set(map(lambda _x: _x["refStr"], user.qso_set.filter(ref__isnull=False).values("ref", "refStr"))) userRefs = set(map(lambda _x: _x["refStr"], user.qso_set.filter(ref__isnull=False).values("ref", "refStr")))
return render(request, "contest/viewUserQSOs.html", {'owner': user, 'qsos': qsos, 'qsoPage': qsoPage, 'userRefs': userRefs}) return render(request, "contest/viewUserQSOs.html", {'owner': user, 'qsos': qsos, 'qsoPage': qsoPage, 'userRefs': userRefs})
@staff_member_required @staff_member_required
def updateRef(request, shadow, uid): def updateRef(request, shadow, uid):
user = None user = None
form = None form = None
if shadow: if shadow:
user = get_object_or_404(ShadowCall, id=uid) user = get_object_or_404(ShadowCall, id=uid)
else: else:
user = get_object_or_404(User, id=uid) user = get_object_or_404(User, id=uid)
if request.method == 'POST': if request.method == 'POST':
form = UpdateRefForm(data=request.POST) form = UpdateRefForm(data=request.POST)
if form.is_valid(): if form.is_valid():
ref = None ref = None
if form.cleaned_data["existingRef"]: if form.cleaned_data["existingRef"]:
ref = form.cleaned_data["existingRef"] ref = form.cleaned_data["existingRef"]
else: else:
ref = Reference(name=form.cleaned_data["newRefName"]) ref = Reference(name=form.cleaned_data["newRefName"])
ref.save() ref.save()
messages.info(request, "New Ref '%s' created" % ref) messages.info(request, "New Ref '%s' created" % ref)
user.ref = ref user.ref = ref
user.regTime = form.cleaned_data["regTime"] user.regTime = form.cleaned_data["regTime"]
user.location = form.cleaned_data["location"] user.location = form.cleaned_data["location"]
user.opName = form.cleaned_data["opName"] user.opName = form.cleaned_data["opName"]
user.save() user.save()
messages.success(request, "%s%s ref set to %s" % ("(shadow) " if shadow else "", user, ref)) messages.success(request, "%s%s ref set to %s" % ("(shadow) " if shadow else "", user, ref))
return HttpResponseRedirect(reverse("contest:registerRefs")) return HttpResponseRedirect(reverse("contest:registerRefs"))
else: else:
data = {} data = {}
if user.ref: if user.ref:
data["existingRef"] = user.ref data["existingRef"] = user.ref
if user.regTime: if user.regTime:
data["regTime"] = user.regTime data["regTime"] = user.regTime
else: else:
data["regTime"] = timezone.now() data["regTime"] = timezone.now()
data["opName"] = user.opName data["opName"] = user.opName
data["location"] = user.location data["location"] = user.location
form = UpdateRefForm(initial=data) form = UpdateRefForm(initial=data)
return render(request, 'contest/updateRef.html', {'userobj': user, 'form': form, "shadow": shadow}) return render(request, 'contest/updateRef.html', {'userobj': user, 'form': form, "shadow": shadow})
@staff_member_required @staff_member_required
def viewAllQSOs(request, page=1): def viewAllQSOs(request, page=1):
qsos = QSO.objects.all().order_by("-time") qsos = QSO.objects.all().order_by("-time")
qsoPager = Paginator(qsos, 10) qsoPager = Paginator(qsos, 10)
qsoPage = getPage(qsoPager, request.GET.get('page')) qsoPage = getPage(qsoPager, request.GET.get('page'))
return render(request, 'contest/viewAllQSOs.html', {'qsoPage': qsoPage}) return render(request, 'contest/viewAllQSOs.html', {'qsoPage': qsoPage})
def overview(request): def overview(request):
# FIXME: Hardcoded for cqtu... everywhere # FIXME: Hardcoded for cqtu... everywhere
c = Contest.objects.get(id=1) c = Contest.objects.get(id=1)
qrgs = Frequency.objects.filter(band__contest=c).order_by("channel") qrgs = Frequency.objects.filter(band__contest=c).order_by("channel")
return render(request, 'contest/overview.html', {'contest': c, 'qrgs': qrgs}) return render(request, 'contest/overview.html', {'contest': c, 'qrgs': qrgs})
def register(request): def register(request):
form = None form = None
if request.method == 'POST': if request.method == 'POST':
form = CustomUserCreationForm(data=request.POST) form = CustomUserCreationForm(data=request.POST)
if form.is_valid(): if form.is_valid():
form.save() form.save()
auth_login(request, form.instance) auth_login(request, form.instance)
messages.info(request, "Registration as user %s successfull!" % form.instance.username) messages.info(request, "Registration as user %s successfull!" % form.instance.username)
return HttpResponseRedirect(reverse("contest:index")) return HttpResponseRedirect(reverse("contest:index"))
else: else:
form = CustomUserCreationForm() form = CustomUserCreationForm()
return render(request, 'registration/register.html', {"form": form}) return render(request, 'registration/register.html', {"form": form})
@login_required @login_required
def profile(request): def profile(request):
pwForm = None pwForm = None
catForm = None catForm = None
if request.method == 'POST': if request.method == 'POST':
if request.POST.get("submit", None) == "pwchange": if request.POST.get("submit", None) == "pwchange":
pwForm = PasswordChangeForm(user=request.user, data=request.POST) pwForm = PasswordChangeForm(user=request.user, data=request.POST)
if pwForm.is_valid(): if pwForm.is_valid():
pwForm.save() pwForm.save()
auth_login(request, pwForm.user) auth_login(request, pwForm.user)
messages.success(request, "Password changed") messages.success(request, "Password changed")
return HttpResponseRedirect(reverse("profile")) return HttpResponseRedirect(reverse("profile"))
else: else:
catForm = UpdateCategoryForm(data=request.POST) catForm = UpdateCategoryForm(data=request.POST)
if catForm.is_valid(): if catForm.is_valid():
request.user.cat = catForm.cleaned_data["entry"] request.user.cat = catForm.cleaned_data["entry"]
request.user.save() request.user.save()
messages.success(request, "Entry category set") messages.success(request, "Entry category set")
return HttpResponseRedirect(reverse("profile")) return HttpResponseRedirect(reverse("profile"))
if not pwForm: if not pwForm:
pwForm = PasswordChangeForm(user=request.user) pwForm = PasswordChangeForm(user=request.user)
if not catForm: if not catForm:
catForm = UpdateCategoryForm(initial={'entry': request.user.cat}) catForm = UpdateCategoryForm(initial={'entry': request.user.cat})
return render(request, 'registration/profile.html', {"pwForm": pwForm, "catForm": catForm}) return render(request, 'registration/profile.html', {"pwForm": pwForm, "catForm": catForm})

View File

@ -33,18 +33,17 @@ ALLOWED_HOSTS = []
# Application definition # Application definition
INSTALLED_APPS = [ INSTALLED_APPS = [
# default # default
'django.contrib.admin', 'django.contrib.admin',
'django.contrib.auth', 'django.contrib.auth',
'django.contrib.contenttypes', 'django.contrib.contenttypes',
'django.contrib.sessions', 'django.contrib.sessions',
'django.contrib.messages', 'django.contrib.messages',
'django.contrib.staticfiles', 'django.contrib.staticfiles',
'crispy_forms',
'crispy_forms', # local
'contest',
# local
'contest',
] ]
MIDDLEWARE = [ MIDDLEWARE = [
@ -140,6 +139,5 @@ STATICFILES_DIRS = [
CRISPY_TEMPLATE_PACK = 'bootstrap3' CRISPY_TEMPLATE_PACK = 'bootstrap3'
MESSAGE_TAGS = { MESSAGE_TAGS = {
messages.ERROR: 'danger', messages.ERROR: 'danger',
} }

View File

@ -26,17 +26,17 @@ from contest.views import index, register, profile
urlpatterns = [ urlpatterns = [
url('^$', index, name="index"), url('^$', index, name="index"),
url('^cqtufm2019/', include('contest.urls', namespace='contest')), url('^cqtufm2019/', include('contest.urls', namespace='contest')),
url(r'^admin/', admin.site.urls), url(r'^admin/', admin.site.urls),
url(r'^login/$', auth_views.login, name='login'), url(r'^login/$', auth_views.login, name='login'),
url(r'^logout/$', auth_views.logout, {'next_page': '/'}, name='logout'), url(r'^logout/$', auth_views.logout, {'next_page': '/'}, name='logout'),
url(r'^register/$', register, name='register'), url(r'^register/$', register, name='register'),
url(r'^profile/$', profile, name='profile'), url(r'^profile/$', profile, name='profile'),
#url(r'^register/$', CreateView.as_view( #url(r'^register/$', CreateView.as_view(
# template_name='registration/register.html', # template_name='registration/register.html',
# form_class=CustomUserCreationForm, # form_class=CustomUserCreationForm,
# success_url='/', # success_url='/',
#), name='register'), #), name='register'),
] ]