diff --git a/contest/cbrparser.py b/contest/cbrparser.py index f574ddc..887c6f2 100644 --- a/contest/cbrparser.py +++ b/contest/cbrparser.py @@ -13,148 +13,148 @@ from .forms import QSOFormWithTime import re def parseCBR(raw): - """ Parse a CBR file for the CQTU - - 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 - inside them. - """ - kvlinere = re.compile(r"^(?P[A-Z-]+):(?: (?P.*))?$") - qsore = re.compile(r"^(?P144|432)\s+(?P[A-Z]{2})\s+(?P\d{4}-\d{2}-\d{2} \d{4}) (?P[A-Z0-9/-]+)\s+(?P\d{2,3})\s+(?P[A-Z0-9-]+)\s+(?P[A-Z0-9/-]+)\s+(?P\d{2,3})\s+(?P[A-Z0-9-]+)\s+0$") - - - qsoNo = 1 - info = { - "call": None, - "location": None, - "qsos": [], - } - - for n, line in enumerate(raw.split("\n"), 1): - line = line.strip() - # ignore empty lines - if line == "": - continue - - m = kvlinere.match(line) - if m: - k = m.group("key") - if k == "CALLSIGN": - info["call"] = m.group("value").strip().upper() - elif k == "LOCATION": - info["location"] = m.group("value").strip().upper() - elif k == "QSO": - q = m.group("value").strip() - # 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 - qm = qsore.search(q) - if qm: - qsoData = qm.groupdict() - qsoTime = timezone.datetime.strptime(qsoData["datetime"], "%Y-%m-%d %H%M") - qsoData["datetime"] = timezone.get_current_timezone().localize(qsoTime) - qsoData["no_s"] = qsoNo - - if qsoData["band"] == "144": - qsoData["band"] = "2m" - elif qsoData["band"] == "432": - qsoData["band"] = "70cm" - else: - 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) - - if info["call"] != qsoData["call_s"]: - raise forms.ValidationError("Error in line %d: qso was not made by you? (callsigns do not match)" % n) - if info["location"] != qsoData["exc_s"]: - raise forms.ValidationError("Error in line %d: exchange does not match your location? (callsigns do not match)" % n) - else: - raise forms.ValidationError("Error in line %d: qso was broken, regex did not match" % n) - - qsoNo += 1 - elif k == "X-QSO": - qsoNo += 1 - - else: - raise forms.ValidationError("Error in line %d: could not parse \"KEY: value\" pair" % n) - - return info + """ Parse a CBR file for the CQTU + + 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 + inside them. + """ + kvlinere = re.compile(r"^(?P[A-Z-]+):(?: (?P.*))?$") + qsore = re.compile(r"^(?P144|432)\s+(?P[A-Z]{2})\s+(?P\d{4}-\d{2}-\d{2} \d{4}) (?P[A-Z0-9/-]+)\s+(?P\d{2,3})\s+(?P[A-Z0-9-]+)\s+(?P[A-Z0-9/-]+)\s+(?P\d{2,3})\s+(?P[A-Z0-9-]+)\s+0$") + + + qsoNo = 1 + info = { + "call": None, + "location": None, + "qsos": [], + } + + for n, line in enumerate(raw.split("\n"), 1): + line = line.strip() + # ignore empty lines + if line == "": + continue + + m = kvlinere.match(line) + if m: + k = m.group("key") + if k == "CALLSIGN": + info["call"] = m.group("value").strip().upper() + elif k == "LOCATION": + info["location"] = m.group("value").strip().upper() + elif k == "QSO": + q = m.group("value").strip() + # 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 + qm = qsore.search(q) + if qm: + qsoData = qm.groupdict() + qsoTime = timezone.datetime.strptime(qsoData["datetime"], "%Y-%m-%d %H%M") + qsoData["datetime"] = timezone.get_current_timezone().localize(qsoTime) + qsoData["no_s"] = qsoNo + + if qsoData["band"] == "144": + qsoData["band"] = "2m" + elif qsoData["band"] == "432": + qsoData["band"] = "70cm" + else: + 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) + + if info["call"] != qsoData["call_s"]: + raise forms.ValidationError("Error in line %d: qso was not made by you? (callsigns do not match)" % n) + if info["location"] != qsoData["exc_s"]: + raise forms.ValidationError("Error in line %d: exchange does not match your location? (callsigns do not match)" % n) + else: + raise forms.ValidationError("Error in line %d: qso was broken, regex did not match" % n) + + qsoNo += 1 + elif k == "X-QSO": + qsoNo += 1 + + else: + raise forms.ValidationError("Error in line %d: could not parse \"KEY: value\" pair" % n) + + return info 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): - rawData = self.cleaned_data["data"] - parsedData = parseCBR(rawData) + def clean_data(self): + rawData = self.cleaned_data["data"] + parsedData = parseCBR(rawData) - return parsedData + return parsedData def checkCBRConsistency(contest, user, info): - errors = [] - qsos = [] - if 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"]: - 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): - qsoFormData = { - #"owner": user, - "time": qsoData["datetime"], - "call": qsoData["call_r"], - "band": Band.objects.get(contest=contest, name=qsoData["band"]).id, - "reportTX": qsoData["rst_s"], - "reportRX": qsoData["rst_r"], - "ownNo": qsoData["no_s"], - "otherNo": None, - "refStr": qsoData["exc_r"], - "remarks": "", - } - - qsoForm = QSOFormWithTime(user, data=qsoFormData) - qsoForm.is_valid() - qsoForm.instance.owner = user - print(qsoForm.errors) - qsos.append((qsoForm.instance, qsoForm)) - - return qsos, errors + errors = [] + qsos = [] + if 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"]: + 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): + qsoFormData = { + #"owner": user, + "time": qsoData["datetime"], + "call": qsoData["call_r"], + "band": Band.objects.get(contest=contest, name=qsoData["band"]).id, + "reportTX": qsoData["rst_s"], + "reportRX": qsoData["rst_r"], + "ownNo": qsoData["no_s"], + "otherNo": None, + "refStr": qsoData["exc_r"], + "remarks": "", + } + + qsoForm = QSOFormWithTime(user, data=qsoFormData) + qsoForm.is_valid() + qsoForm.instance.owner = user + print(qsoForm.errors) + qsos.append((qsoForm.instance, qsoForm)) + + return qsos, errors @login_required def uploadCBR(request): - if not request.user.ref: - return HttpResponseRedirect(reverse("contest:index")) - - contest = Contest.objects.get(id=1) - deadline = False - form = None - verifyData = [] - verifyErrors = [] - save = saved = False - - if timezone.now() < contest.deadline: - if request.method == "POST": - form = CBRForm(data=request.POST) - if form.is_valid(): - verifyData, verifyErrors = checkCBRConsistency(contest, request.user, form.cleaned_data["data"]) - - if request.POST.get("action") == "save": - save = True - if not verifyErrors: - cnt = 0 - for qso, qsoForm in verifyData: - if qsoForm.is_valid(): - qso.save() - cnt += 1 - - if cnt > 0: - messages.success(request, "%d QSOs have been saved from the cbr file" % cnt) - else: - messages.warnnig(request, "CBR file was parsed, but no QSOs could be saved, as all cointained errors.") - - return HttpResponseRedirect(reverse("contest:uploadCBR")) - else: - form = CBRForm() - else: - deadline = True - - return render(request, "contest/uploadCBR.html", {"deadline": deadline, 'form': form, 'verifyData': verifyData, 'verifyErrors': verifyErrors, 'save': save, 'saved': saved}) + if not request.user.ref: + return HttpResponseRedirect(reverse("contest:index")) + + contest = Contest.objects.get(id=1) + deadline = False + form = None + verifyData = [] + verifyErrors = [] + save = saved = False + + if timezone.now() < contest.deadline: + if request.method == "POST": + form = CBRForm(data=request.POST) + if form.is_valid(): + verifyData, verifyErrors = checkCBRConsistency(contest, request.user, form.cleaned_data["data"]) + + if request.POST.get("action") == "save": + save = True + if not verifyErrors: + cnt = 0 + for qso, qsoForm in verifyData: + if qsoForm.is_valid(): + qso.save() + cnt += 1 + + if cnt > 0: + messages.success(request, "%d QSOs have been saved from the cbr file" % cnt) + else: + messages.warnnig(request, "CBR file was parsed, but no QSOs could be saved, as all cointained errors.") + + return HttpResponseRedirect(reverse("contest:uploadCBR")) + else: + form = CBRForm() + else: + deadline = True + + return render(request, "contest/uploadCBR.html", {"deadline": deadline, 'form': form, 'verifyData': verifyData, 'verifyErrors': verifyErrors, 'save': save, 'saved': saved}) diff --git a/contest/forms.py b/contest/forms.py index e8a68fb..329ae86 100644 --- a/contest/forms.py +++ b/contest/forms.py @@ -10,165 +10,165 @@ from .models import User, Reference, QSO, ShadowCall, EntryCategory, Contest from .validators import CallUsernameValidator, CallLogValidator class CustomUserCreationForm(UserCreationForm): - class Meta: - model = User - fields = ("username", "email", "dncall", "qrv2m", "qrv70cm", "extra2m70cm") + class Meta: + model = User + fields = ("username", "email", "dncall", "qrv2m", "qrv70cm", "extra2m70cm") - username = forms.CharField(max_length=50, validators=[CallUsernameValidator()]) - email = forms.EmailField(required=True) + username = forms.CharField(max_length=50, validators=[CallUsernameValidator()]) + email = forms.EmailField(required=True) 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) - newRefName = forms.CharField(max_length=50, label="New Exchange", help_text="Enter name of new exchange, if we should create a new", 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) - 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) - regTime = forms.DateTimeField(label="Registration time", help_text="Time of Registration") + 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) + regTime = forms.DateTimeField(label="Registration time", help_text="Time of Registration") - def clean_newRefName(self): - data = self.cleaned_data["newRefName"].strip().upper() + def clean_newRefName(self): + data = self.cleaned_data["newRefName"].strip().upper() - return data + return data - def clean(self): - cleaned_data = super(UpdateRefForm, self).clean() + def clean(self): + cleaned_data = super(UpdateRefForm, self).clean() - existingRef = cleaned_data.get("existingRef") - newRefName = cleaned_data.get("newRefName") + existingRef = cleaned_data.get("existingRef") + newRefName = cleaned_data.get("newRefName") - if newRefName: - try: - ref = Reference.objects.get(name=newRefName) - self.cleaned_data['newRefName'] = None - self.cleaned_data['existingRef'] = ref - except Reference.DoesNotExist: - pass + if newRefName: + try: + ref = Reference.objects.get(name=newRefName) + self.cleaned_data['newRefName'] = None + self.cleaned_data['existingRef'] = ref + except Reference.DoesNotExist: + pass - if existingRef and newRefName: - raise forms.ValidationError("Select an existing exchange or create a new one, not both!") - if not existingRef and not newRefName: - raise forms.ValidationError("Select either an existing exchange or create a new one!") + if existingRef and newRefName: + raise forms.ValidationError("Select an existing exchange or create a new one, not both!") + if not existingRef and not newRefName: + raise forms.ValidationError("Select either an existing exchange or create a new one!") class UpdateCategoryForm(forms.Form): - entry = forms.ModelChoiceField(label="Entry category", queryset=EntryCategory.objects.all()) - def __init__(self, *args, **kwargs): - super(UpdateCategoryForm, self).__init__(*args, **kwargs) + entry = forms.ModelChoiceField(label="Entry category", queryset=EntryCategory.objects.all()) + def __init__(self, *args, **kwargs): + super(UpdateCategoryForm, self).__init__(*args, **kwargs) - self.helper = FormHelper() - self.helper.form_class = "form-inline " - self.helper.form_style = 'inline' - self.helper.field_template = "bootstrap3/layout/inline_field.html" - self.helper.action = reverse("profile") - self.helper.add_input(Submit('submit', 'Set category')) - self.helper.layout = Layout('entry') + self.helper = FormHelper() + self.helper.form_class = "form-inline " + self.helper.form_style = 'inline' + self.helper.field_template = "bootstrap3/layout/inline_field.html" + self.helper.action = reverse("profile") + self.helper.add_input(Submit('submit', 'Set category')) + self.helper.layout = Layout('entry') - def clean(self): - contest = Contest.objects.get(id=1) + def clean(self): + contest = Contest.objects.get(id=1) - if contest.deadline < timezone.now(): - raise forms.ValidationError("The deadline for setting your contest category has passed") + if contest.deadline < timezone.now(): + raise forms.ValidationError("The deadline for setting your contest category has passed") class QSOForm(forms.ModelForm): - class Meta: - model = QSO - #fields = ["ownNo", "band", "call", "reportTX", "reportRX", "refStr", "otherNo", "remarks"] - fields = ["ownNo", "band", "call", "reportTX", "reportRX", "refStr", "remarks"] + class Meta: + model = QSO + #fields = ["ownNo", "band", "call", "reportTX", "reportRX", "refStr", "otherNo", "remarks"] + fields = ["ownNo", "band", "call", "reportTX", "reportRX", "refStr", "remarks"] - def __init__(self, user, *args, **kwargs): - super(QSOForm, self).__init__(*args, **kwargs) - self.user = user + def __init__(self, user, *args, **kwargs): + super(QSOForm, self).__init__(*args, **kwargs) + self.user = user - self.helper = FormHelper() - self.helper.form_id = "qso-log-form" - #self.helper.form_class = "form-inline " - #self.helper.form_class = "form-horizontal" - #self.helper.form_style = 'inline' - #self.helper.field_template = "bootstrap3/layout/inline_field.html" - self.helper.action = reverse("contest:log") - self.helper.add_input(Submit('submit', 'Log')) - #self.helper.layout = Layout( - # #*(QSOForm.Meta.fields + [ButtonHolder(Submit('submit', 'Submit', css_class='button white'))])) - # *(QSOForm.Meta.fields + [FormActions(Submit('submit', 'Log!'))])) + self.helper = FormHelper() + self.helper.form_id = "qso-log-form" + #self.helper.form_class = "form-inline " + #self.helper.form_class = "form-horizontal" + #self.helper.form_style = 'inline' + #self.helper.field_template = "bootstrap3/layout/inline_field.html" + self.helper.action = reverse("contest:log") + self.helper.add_input(Submit('submit', 'Log')) + #self.helper.layout = Layout( + # #*(QSOForm.Meta.fields + [ButtonHolder(Submit('submit', 'Submit', css_class='button white'))])) + # *(QSOForm.Meta.fields + [FormActions(Submit('submit', 'Log!'))])) - def clean_call(self): - data = self.cleaned_data["call"].upper().strip() - if Reference.objects.filter(name=data).count() > 0: - raise forms.ValidationError("Reference already exists") + def clean_call(self): + data = self.cleaned_data["call"].upper().strip() + if Reference.objects.filter(name=data).count() > 0: + raise forms.ValidationError("Reference already exists") - try: - CallLogValidator()(data) - except forms.ValidationError: - raise forms.ValidationError("Enter a valid callsign (1-2 chars, a number, 1-4 chars, maybe a /[A-Z])") + try: + CallLogValidator()(data) + except forms.ValidationError: + raise forms.ValidationError("Enter a valid callsign (1-2 chars, a number, 1-4 chars, maybe a /[A-Z])") - if data == self.user.username: - raise forms.ValidationError("You cannot log QSOs with yourself") + if data == self.user.username: + raise forms.ValidationError("You cannot log QSOs with yourself") - return data + return data - def clean_ownNo(self): - data = self.cleaned_data["ownNo"] + def clean_ownNo(self): + data = self.cleaned_data["ownNo"] - if data < 1 or data > 100000: - raise forms.ValidationError("Number has to be in range of [1, 1000000]") + if data < 1 or data > 100000: + raise forms.ValidationError("Number has to be in range of [1, 1000000]") - try: - o = QSO.objects.get(owner=self.user.id, ownNo=data) - 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) - except QSO.DoesNotExist: - pass + try: + o = QSO.objects.get(owner=self.user.id, ownNo=data) + 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) + except QSO.DoesNotExist: + pass - return data + return data - def clean_otherNo(self): - data = self.cleaned_data["otherNo"] + def clean_otherNo(self): + data = self.cleaned_data["otherNo"] - if not data: - # empty value - return None + if not data: + # empty value + return None - if data < 1 or data > 100000: - raise forms.ValidationError("Number has to be in range of [1, 1000000]") + if data < 1 or data > 100000: + raise forms.ValidationError("Number has to be in range of [1, 1000000]") - return data + return data - def clean_refStr(self): - return self.cleaned_data["refStr"].upper() + def clean_refStr(self): + return self.cleaned_data["refStr"].upper() - def clean(self): - cleaned_data = super(QSOForm, self).clean() - band = cleaned_data.get("band") + def clean(self): + cleaned_data = super(QSOForm, self).clean() + band = cleaned_data.get("band") - if band.contest.deadline < timezone.now(): - raise forms.ValidationError("The deadline for logging and editing QSOs has passed") + if band.contest.deadline < timezone.now(): + raise forms.ValidationError("The deadline for logging and editing QSOs has passed") class QSOFormWithTime(QSOForm): - class Meta: - model = QSO - #fields = ["time", "ownNo", "band", "call", "reportTX", "reportRX", "otherNo", "refStr", "remarks"] - fields = ["time", "ownNo", "band", "call", "reportTX", "reportRX", "refStr", "remarks"] + class Meta: + model = QSO + #fields = ["time", "ownNo", "band", "call", "reportTX", "reportRX", "otherNo", "refStr", "remarks"] + fields = ["time", "ownNo", "band", "call", "reportTX", "reportRX", "refStr", "remarks"] class ShadowCallAddForm(forms.ModelForm): - class Meta: - model = ShadowCall - fields = ['username'] + class Meta: + model = ShadowCall + fields = ['username'] - def __init__(self, *args, **kwargs): - super(ShadowCallAddForm, self).__init__(*args, **kwargs) + def __init__(self, *args, **kwargs): + super(ShadowCallAddForm, self).__init__(*args, **kwargs) - self.helper = FormHelper() - self.helper.form_class = "form-inline " - self.helper.form_style = 'inline' - self.helper.field_template = "bootstrap3/layout/inline_field.html" - self.helper.action = reverse("contest:registerRefs") - self.helper.add_input(Submit('submit', 'Add shadow')) - self.helper.layout = Layout('username') + self.helper = FormHelper() + self.helper.form_class = "form-inline " + self.helper.form_style = 'inline' + self.helper.field_template = "bootstrap3/layout/inline_field.html" + self.helper.action = reverse("contest:registerRefs") + self.helper.add_input(Submit('submit', 'Add shadow')) + self.helper.layout = Layout('username') - def clean_username(self): - data = self.cleaned_data["username"] - if User.objects.filter(username=data).count() > 0: - raise forms.ValidationError("A user with this call already exists, this is not a shadow!") + def clean_username(self): + data = self.cleaned_data["username"] + if User.objects.filter(username=data).count() > 0: + raise forms.ValidationError("A user with this call already exists, this is not a shadow!") - return data + return data diff --git a/contest/models.py b/contest/models.py index 2e8eb6f..db38a56 100644 --- a/contest/models.py +++ b/contest/models.py @@ -11,236 +11,236 @@ from .validators import CallUsernameValidator from .signals import checkForShadowCall class Contest(models.Model): - name = models.CharField(max_length=20) - shortName = models.CharField(max_length=20, unique=True) - callQrg = models.ForeignKey("Frequency", models.SET_NULL, null=True, blank=True) - deadline = models.DateTimeField() + name = models.CharField(max_length=20) + shortName = models.CharField(max_length=20, unique=True) + callQrg = models.ForeignKey("Frequency", models.SET_NULL, null=True, blank=True) + deadline = models.DateTimeField() - qsoStartTime = models.DateTimeField() - qsoEndTime = models.DateTimeField() + qsoStartTime = models.DateTimeField() + qsoEndTime = models.DateTimeField() - def __str__(self): - return self.name + def __str__(self): + return self.name class Reference(models.Model): - name = models.CharField(max_length=20, unique=True, db_index=True) - description = models.TextField() + name = models.CharField(max_length=20, unique=True, db_index=True) + description = models.TextField() - def __str__(self): - return self.name + def __str__(self): + return self.name class EntryCategory(models.Model): - name = models.CharField(max_length=64, unique=True) - description = models.TextField(blank=True) + name = models.CharField(max_length=64, unique=True) + description = models.TextField(blank=True) - def __str__(self): - return self.name + def __str__(self): + return self.name class ShadowCall(models.Model): - username = models.CharField(max_length=20, unique=True, db_index=True, validators=[CallUsernameValidator()]) - ref = models.ForeignKey(Reference, models.SET_NULL,null=True, blank=True) + username = models.CharField(max_length=20, unique=True, db_index=True, validators=[CallUsernameValidator()]) + ref = models.ForeignKey(Reference, models.SET_NULL,null=True, blank=True) - location = models.CharField(max_length=128, default="", blank=True) - opName = models.CharField(max_length=128, default="", blank=True) - regTime = models.DateTimeField(null=True, default=None) + location = models.CharField(max_length=128, default="", blank=True) + opName = models.CharField(max_length=128, default="", blank=True) + regTime = models.DateTimeField(null=True, default=None) - def __str__(self): - return self.username + def __str__(self): + return self.username class User(AbstractUser): - ref = models.ForeignKey(Reference, 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) - opName = models.CharField(max_length=128, default="", blank=True) - regTime = models.DateTimeField(null=True, default=None) - - # because of cbr parsing bug, we sometimes have users who only have 70cm qsos - # we ignore the band for them when checking QSOs - ignoreBand = models.BooleanField(default=False) - - # extra profile stuff so DL7BST can sleep well without his doodles - editedProfile = models.BooleanField(default=False) - dncall = models.CharField(max_length=16, default='', blank=True, - verbose_name="DN-Call", - help_text="If you have a DN call that you will offer to SWLs please enter it here") - qrv2m = models.BooleanField(default=False, - verbose_name="QRV on 2m", - help_text="Will you be QRV on 2m during the contest?") - qrv70cm = models.BooleanField(default=False, - verbose_name="QRV on 70cm", - help_text="Will you be QRV on 70cm during the contest?") - extra2m70cm = models.BooleanField(default=False, + ref = models.ForeignKey(Reference, 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) + opName = models.CharField(max_length=128, default="", blank=True) + regTime = models.DateTimeField(null=True, default=None) + + # because of cbr parsing bug, we sometimes have users who only have 70cm qsos + # we ignore the band for them when checking QSOs + ignoreBand = models.BooleanField(default=False) + + # extra profile stuff so DL7BST can sleep well without his doodles + editedProfile = models.BooleanField(default=False) + dncall = models.CharField(max_length=16, default='', blank=True, + verbose_name="DN-Call", + help_text="If you have a DN call that you will offer to SWLs please enter it here") + qrv2m = models.BooleanField(default=False, + verbose_name="QRV on 2m", + help_text="Will you be QRV on 2m during the contest?") + qrv70cm = models.BooleanField(default=False, + verbose_name="QRV on 70cm", + help_text="Will you be QRV on 70cm during the contest?") + extra2m70cm = models.BooleanField(default=False, verbose_name="Additional 2m/70cm TRX", help_text="Will you bring an additional 2m/70cm TRX to lend to other participants?") - def __init__(self, *args, **kwargs): - super(User, self).__init__(*args, **kwargs) - self._meta.get_field("username").validators = [CallUsernameValidator()] + def __init__(self, *args, **kwargs): + super(User, self).__init__(*args, **kwargs) + self._meta.get_field("username").validators = [CallUsernameValidator()] - def getQSOCount(self): - return self.qso_set.count() + def getQSOCount(self): + return self.qso_set.count() - def getCfmdQSOCount(self): - return self.qso_set.filter(~Q(cfmdQSO=None)).count() + def getCfmdQSOCount(self): + return self.qso_set.filter(~Q(cfmdQSO=None)).count() - def getCfmdRefCount(self): - return len(set(map(lambda _x: _x["refStr"], self.qso_set.filter(ref__isnull=False).values("ref", "refStr")))) + def getCfmdRefCount(self): + return len(set(map(lambda _x: _x["refStr"], self.qso_set.filter(ref__isnull=False).values("ref", "refStr")))) - def calcClaimedPoints(self): - return self.calcPoints(cfmd=False) + def calcClaimedPoints(self): + return self.calcPoints(cfmd=False) - def calcCfmdPoints(self): - return self.calcPoints(cfmd=True) + def calcCfmdPoints(self): + return self.calcPoints(cfmd=True) - def calcPoints(self, cfmd): - contest = Contest.objects.get(id=1) + def calcPoints(self, cfmd): + contest = Contest.objects.get(id=1) - result = {"refCount": 0, "qsoCount": 0} - for band in contest.band_set.all(): - result[band.name] = self.calcBandPoints(band, cfmd) - result["refCount"] += result[band.name]["refCount"] - result["qsoCount"] += result[band.name]["qsoCount"] + result = {"refCount": 0, "qsoCount": 0} + for band in contest.band_set.all(): + result[band.name] = self.calcBandPoints(band, cfmd) + result["refCount"] += result[band.name]["refCount"] + 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): - contest = band.contest - qsos = self.qso_set.filter(band=band, time__gte=contest.qsoStartTime, time__lte=contest.qsoEndTime) - if cfmd: - qsos = qsos.filter(cfmdQSO__isnull=False) - refs = set(map(lambda _x: _x["refStr"], qsos.values("refStr"))) + def calcBandPoints(self, band, cfmd=False): + contest = band.contest + qsos = self.qso_set.filter(band=band, time__gte=contest.qsoStartTime, time__lte=contest.qsoEndTime) + if cfmd: + qsos = qsos.filter(cfmdQSO__isnull=False) + refs = set(map(lambda _x: _x["refStr"], qsos.values("refStr"))) - return { - "band": band, - "refs": refs, - "qsoCount": qsos.count(), - "refCount": len(refs) - } + return { + "band": band, + "refs": refs, + "qsoCount": qsos.count(), + "refCount": len(refs) + } signals.post_save.connect(checkForShadowCall, sender=User) class Band(models.Model): - name = models.CharField(max_length=10) - contest = models.ForeignKey(Contest) + name = models.CharField(max_length=10) + contest = models.ForeignKey(Contest) - def __str__(self): - return self.name + def __str__(self): + return self.name class Frequency(models.Model): - # qrg - # band - channel = models.CharField(max_length=3) - qrg = models.DecimalField(max_digits=7, decimal_places=3) - band = models.ForeignKey(Band) + # qrg + # band + channel = models.CharField(max_length=3) + qrg = models.DecimalField(max_digits=7, decimal_places=3) + band = models.ForeignKey(Band) - note = models.CharField(max_length=50, blank=True) + note = models.CharField(max_length=50, blank=True) - def __str__(self): - return "Channel %s: %s MHz" % (self.channel, self.qrg) + def __str__(self): + return "Channel %s: %s MHz" % (self.channel, self.qrg) class QSO(models.Model): - reportValidator = RegexValidator("[1-5][1-9]") - - class Meta: - index_together = [ - ["owner", "call"], - ] - - owner = models.ForeignKey(User, db_index=True) - time = models.DateTimeField(blank=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) - band = models.ForeignKey(Band) - - 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]) - - ownNo = models.IntegerField(verbose_name='No') - otherNo = models.IntegerField(verbose_name='No-R', null=True, blank=True) - - refStr = models.CharField(max_length=20, verbose_name="EXC") - ref = models.ForeignKey(Reference, models.SET_NULL, null=True, blank=True) - - remarks = models.CharField(max_length=50, blank=True, default=None) - - cfmdQSO = models.ForeignKey("QSO", models.SET_NULL, null=True, blank=True, default=None) - - CFMD_SEC = 5*60 - - def checkQSOData(self): - """ Match strdata to log rows. Only call, if you intent to save this object if we return True! """ - # find reference - changed = False - if self.refStr: - refName = self.refStr.replace("-", "") - if refName == "GX": - refName = "DX" - - # Old reference exists? - if self.ref and self.ref.name != refName: - self.ref = None - changed = True - - if not self.ref: - # find matching ref - try: - self.ref = Reference.objects.get(name=refName) - changed = True - except Reference.DoesNotExist: - pass - - # find call - if not self.callRef or self.callRef.username != self.call: - try: - self.callRef = User.objects.get(username=self.call) - changed = True - except User.DoesNotExist: - if self.callRef: - changed = True - self.callRef = None - - # find matching qso - if self.cfmdQSO: - # check if this still checks out - q = self.cfmdQSO - 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 \ - q.owner == self.callRef and q.callRef == self.owner and \ - self.ref == q.owner.ref and self.owner.ref == q.ref and \ - self.band == q.band: - # checks out - pass - else: - changed = True - self.cfmdQSO.cfmdQSO = None - self.cfmdQSO.save(checkQSO=False) - self.cfmdQSO = None - - if self.ref and self.callRef and self.callRef.ref and not self.cfmdQSO: - # look for a matching line - 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))), - owner=self.callRef, - callRef=self.owner, - owner__ref=self.ref, - ref=self.owner.ref, - band=self.band) - - if q.count() == 1: - changed = True - q[0].cfmdQSO = self - q[0].save(checkQSO=False) - self.cfmdQSO = q[0] - - return changed - - def save(self, checkQSO=True, *args, **kwargs): - if checkQSO: - self.checkQSOData() - - super(QSO, self).save(*args, **kwargs) - - 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) + reportValidator = RegexValidator("[1-5][1-9]") + + class Meta: + index_together = [ + ["owner", "call"], + ] + + owner = models.ForeignKey(User, db_index=True) + time = models.DateTimeField(blank=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) + band = models.ForeignKey(Band) + + 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]) + + ownNo = models.IntegerField(verbose_name='No') + otherNo = models.IntegerField(verbose_name='No-R', null=True, blank=True) + + refStr = models.CharField(max_length=20, verbose_name="EXC") + ref = models.ForeignKey(Reference, models.SET_NULL, null=True, blank=True) + + remarks = models.CharField(max_length=50, blank=True, default=None) + + cfmdQSO = models.ForeignKey("QSO", models.SET_NULL, null=True, blank=True, default=None) + + CFMD_SEC = 5*60 + + def checkQSOData(self): + """ Match strdata to log rows. Only call, if you intent to save this object if we return True! """ + # find reference + changed = False + if self.refStr: + refName = self.refStr.replace("-", "") + if refName == "GX": + refName = "DX" + + # Old reference exists? + if self.ref and self.ref.name != refName: + self.ref = None + changed = True + + if not self.ref: + # find matching ref + try: + self.ref = Reference.objects.get(name=refName) + changed = True + except Reference.DoesNotExist: + pass + + # find call + if not self.callRef or self.callRef.username != self.call: + try: + self.callRef = User.objects.get(username=self.call) + changed = True + except User.DoesNotExist: + if self.callRef: + changed = True + self.callRef = None + + # find matching qso + if self.cfmdQSO: + # check if this still checks out + q = self.cfmdQSO + 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 \ + q.owner == self.callRef and q.callRef == self.owner and \ + self.ref == q.owner.ref and self.owner.ref == q.ref and \ + self.band == q.band: + # checks out + pass + else: + changed = True + self.cfmdQSO.cfmdQSO = None + self.cfmdQSO.save(checkQSO=False) + self.cfmdQSO = None + + if self.ref and self.callRef and self.callRef.ref and not self.cfmdQSO: + # look for a matching line + 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))), + owner=self.callRef, + callRef=self.owner, + owner__ref=self.ref, + ref=self.owner.ref, + band=self.band) + + if q.count() == 1: + changed = True + q[0].cfmdQSO = self + q[0].save(checkQSO=False) + self.cfmdQSO = q[0] + + return changed + + def save(self, checkQSO=True, *args, **kwargs): + if checkQSO: + self.checkQSOData() + + super(QSO, self).save(*args, **kwargs) + + 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) diff --git a/contest/signals.py b/contest/signals.py index 2de050a..378998d 100644 --- a/contest/signals.py +++ b/contest/signals.py @@ -1,18 +1,18 @@ def checkForShadowCall(sender, instance, created, raw, **kwargs): - """ Check for existing shadow call. If present copy it's data and delete it. """ - if created: - # to prevent circular imports we import ShadowCall here - from .models import ShadowCall + """ Check for existing shadow call. If present copy it's data and delete it. """ + if created: + # to prevent circular imports we import ShadowCall here + from .models import ShadowCall - try: - shadow = ShadowCall.objects.get(username=instance.username) - instance.ref = shadow.ref - instance.location = shadow.location - instance.opName = shadow.opName - instance.regTime = shadow.regTime + try: + shadow = ShadowCall.objects.get(username=instance.username) + instance.ref = shadow.ref + instance.location = shadow.location + instance.opName = shadow.opName + instance.regTime = shadow.regTime - instance.save() - shadow.delete() - except ShadowCall.DoesNotExist: - pass + instance.save() + shadow.delete() + except ShadowCall.DoesNotExist: + pass diff --git a/contest/urls.py b/contest/urls.py index ff69b01..0ce817a 100644 --- a/contest/urls.py +++ b/contest/urls.py @@ -20,16 +20,16 @@ import contest.views as contest_views from contest.cbrparser import uploadCBR urlpatterns = [ - url(r'^$', contest_views.contestIndex, name='index'), - url(r'^regref/$', contest_views.registerRefs, name='registerRefs'), - url(r'^regref/edit/(?P\d+)/$', contest_views.updateRef, {"shadow": False}, name='updateRef'), - url(r'^regref/shadow/edit/(?P\d+)/$', contest_views.updateRef, {"shadow": True}, name='updateShadowRef'), - url(r'^regref/qsos/all/$', contest_views.viewAllQSOs, name='viewAllQSOs'), - url(r'^regref/qsos/user/(?P\d+)/$', contest_views.viewUserQSOs, name='viewUserQSOs'), - url(r'^overview/$', contest_views.overview, name='overview'), - url(r'^log/$', contest_views.log, name='log'), - url(r'^log/edit/(?P\d+)/$', contest_views.logEdit, name='logEdit'), - url(r'^log/delete/(?P\d+)/$', contest_views.logDelete, name='logDelete'), - url(r'^uploadcbr/$', uploadCBR, name='uploadCBR'), - url(r'^regref/recheckqsos/$', contest_views.recheckAllQSOs, name='recheckAllQSOs'), + url(r'^$', contest_views.contestIndex, name='index'), + url(r'^regref/$', contest_views.registerRefs, name='registerRefs'), + url(r'^regref/edit/(?P\d+)/$', contest_views.updateRef, {"shadow": False}, name='updateRef'), + url(r'^regref/shadow/edit/(?P\d+)/$', contest_views.updateRef, {"shadow": True}, name='updateShadowRef'), + url(r'^regref/qsos/all/$', contest_views.viewAllQSOs, name='viewAllQSOs'), + url(r'^regref/qsos/user/(?P\d+)/$', contest_views.viewUserQSOs, name='viewUserQSOs'), + url(r'^overview/$', contest_views.overview, name='overview'), + url(r'^log/$', contest_views.log, name='log'), + url(r'^log/edit/(?P\d+)/$', contest_views.logEdit, name='logEdit'), + url(r'^log/delete/(?P\d+)/$', contest_views.logDelete, name='logDelete'), + url(r'^uploadcbr/$', uploadCBR, name='uploadCBR'), + url(r'^regref/recheckqsos/$', contest_views.recheckAllQSOs, name='recheckAllQSOs'), ] diff --git a/contest/views.py b/contest/views.py index 6a4fa6c..462e25f 100644 --- a/contest/views.py +++ b/contest/views.py @@ -19,251 +19,251 @@ from .models import User, Contest, Frequency, Reference, QSO, ShadowCall from .forms import UpdateRefForm, QSOForm, QSOFormWithTime, CustomUserCreationForm, ShadowCallAddForm, UpdateCategoryForm def index(request): - if request.user.is_authenticated(): - return HttpResponseRedirect(reverse("contest:index")) + if request.user.is_authenticated(): + return HttpResponseRedirect(reverse("contest:index")) - return render(request, "index.html", {"loginForm": AuthenticationForm()}) + return render(request, "index.html", {"loginForm": AuthenticationForm()}) @login_required def contestIndex(request): - qsoform = QSOForm(request.user) - contest = Contest.objects.get(id=1) - qrgs = Frequency.objects.filter(band__contest=contest).order_by("channel") + qsoform = QSOForm(request.user) + contest = Contest.objects.get(id=1) + 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 def log(request): - if not request.user.ref: - return HttpResponseRedirect(reverse("contest:index")) + if not request.user.ref: + 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': - form = QSOForm(user=request.user, data=request.POST) - form.helper.form_tag = False - if form.is_valid(): - l = form.instance - if not l.time: - # set current time - l.time = datetime.datetime.now() + if request.method == 'POST': + form = QSOForm(user=request.user, data=request.POST) + form.helper.form_tag = False + if form.is_valid(): + l = form.instance + if not l.time: + # set current time + l.time = datetime.datetime.now() - l.owner = request.user - l.save() + l.owner = request.user + l.save() - messages.success(request, "QSO saved!") + messages.success(request, "QSO saved!") - return HttpResponseRedirect(reverse("contest:log")) - else: - data = { - "ownNo": qsos[0].ownNo + 1 if len(qsos) > 0 else 1, - "reportRX": "59", - "reportTX": "59", - } - if qsos.count() > 0: - data["band"] = qsos[0].band + return HttpResponseRedirect(reverse("contest:log")) + else: + data = { + "ownNo": qsos[0].ownNo + 1 if len(qsos) > 0 else 1, + "reportRX": "59", + "reportTX": "59", + } + if qsos.count() > 0: + data["band"] = qsos[0].band - form = QSOForm(request.user, initial=data) - form.helper.form_tag = False + form = QSOForm(request.user, initial=data) + 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 def logEdit(request, qsoid): - if not request.user.ref: - return HttpResponseRedirect(reverse("contest:index")) + if not request.user.ref: + return HttpResponseRedirect(reverse("contest:index")) - qso = QSO.objects.get(id=qsoid, owner=request.user) - form = None + qso = QSO.objects.get(id=qsoid, owner=request.user) + form = None - if request.method == 'POST': - form = QSOFormWithTime(user=request.user, instance=qso, data=request.POST) - if form.is_valid(): - form.instance.save() + if request.method == 'POST': + form = QSOFormWithTime(user=request.user, instance=qso, data=request.POST) + if form.is_valid(): + form.instance.save() - messages.info(request, "QSO has been edited") - return HttpResponseRedirect(reverse("contest:log")) - else: - form = QSOFormWithTime(user=request.user, instance=qso) + messages.info(request, "QSO has been edited") + return HttpResponseRedirect(reverse("contest:log")) + else: + 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): - if not request.user.ref: - return HttpResponseRedirect(reverse("contest:index")) + if not request.user.ref: + 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 "delete" in request.POST: - if request.POST["delete"].lower() == "yes": - qso.delete() - messages.info(request, "QSO has been deleted") - return HttpResponseRedirect(reverse("contest:log")) - elif request.POST["delete"].lower() == "no": - return HttpResponseRedirect(reverse("contest:log")) + if request.method == 'POST': + if "delete" in request.POST: + if request.POST["delete"].lower() == "yes": + qso.delete() + messages.info(request, "QSO has been deleted") + return HttpResponseRedirect(reverse("contest:log")) + elif request.POST["delete"].lower() == "no": + return HttpResponseRedirect(reverse("contest:log")) - return render(request, 'contest/logDelete.html', {"qso": qso}) + return render(request, 'contest/logDelete.html', {"qso": qso}) @staff_member_required def registerRefs(request): - allUser = User.objects.all() - shadows = ShadowCall.objects.all() + allUser = User.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 - if request.method == 'POST': - shadowForm = ShadowCallAddForm(data=request.POST) - if shadowForm.is_valid(): - shadowForm.instance.save() - messages.success(request, "Successfully added shadow user %s" % (shadowForm.instance.username,)) - return HttpResponseRedirect(reverse("contest:registerRefs")) - else: - shadowForm = ShadowCallAddForm() + shadowForm = None + if request.method == 'POST': + shadowForm = ShadowCallAddForm(data=request.POST) + if shadowForm.is_valid(): + shadowForm.instance.save() + messages.success(request, "Successfully added shadow user %s" % (shadowForm.instance.username,)) + return HttpResponseRedirect(reverse("contest:registerRefs")) + else: + 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): - try: - return paginator.page(pageNo) - except PageNotAnInteger: - return paginator.page(1) - except EmptyPage: - return paginator.page(paginator.num_pages) + try: + return paginator.page(pageNo) + except PageNotAnInteger: + return paginator.page(1) + except EmptyPage: + return paginator.page(paginator.num_pages) @staff_member_required def recheckAllQSOs(request): - if request.method == "POST": - cnt = 0 - for qso in QSO.objects.all(): - if qso.checkQSOData(): - print(qso) - qso.save() - cnt += 1 + if request.method == "POST": + cnt = 0 + for qso in QSO.objects.all(): + if qso.checkQSOData(): + print(qso) + qso.save() + cnt += 1 - messages.success(request, "Allo QSO have been checked against each other (%d QSOs modified)" % (cnt,)) - return HttpResponseRedirect(reverse("contest:registerRefs")) + messages.success(request, "Allo QSO have been checked against each other (%d QSOs modified)" % (cnt,)) + return HttpResponseRedirect(reverse("contest:registerRefs")) - return render(request, "contest/checkAllQSOs.html", {}) + return render(request, "contest/checkAllQSOs.html", {}) @staff_member_required def viewUserQSOs(request, uid, page=1): - user = get_object_or_404(User, id=uid) - qsos = QSO.objects.filter(owner=user).order_by("-time") - qsoPager = Paginator(qsos, 50) - qsoPage = getPage(qsoPager, request.GET.get('page')) + user = get_object_or_404(User, id=uid) + qsos = QSO.objects.filter(owner=user).order_by("-time") + qsoPager = Paginator(qsos, 50) + 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 def updateRef(request, shadow, uid): - user = None - form = None - - if shadow: - user = get_object_or_404(ShadowCall, id=uid) - else: - user = get_object_or_404(User, id=uid) - - if request.method == 'POST': - form = UpdateRefForm(data=request.POST) - if form.is_valid(): - ref = None - if form.cleaned_data["existingRef"]: - ref = form.cleaned_data["existingRef"] - else: - ref = Reference(name=form.cleaned_data["newRefName"]) - ref.save() - messages.info(request, "New Ref '%s' created" % ref) - - user.ref = ref - user.regTime = form.cleaned_data["regTime"] - user.location = form.cleaned_data["location"] - user.opName = form.cleaned_data["opName"] - user.save() - messages.success(request, "%s%s ref set to %s" % ("(shadow) " if shadow else "", user, ref)) - return HttpResponseRedirect(reverse("contest:registerRefs")) - else: - data = {} - if user.ref: - data["existingRef"] = user.ref - - if user.regTime: - data["regTime"] = user.regTime - else: - data["regTime"] = timezone.now() - data["opName"] = user.opName - data["location"] = user.location - - form = UpdateRefForm(initial=data) - - return render(request, 'contest/updateRef.html', {'userobj': user, 'form': form, "shadow": shadow}) + user = None + form = None + + if shadow: + user = get_object_or_404(ShadowCall, id=uid) + else: + user = get_object_or_404(User, id=uid) + + if request.method == 'POST': + form = UpdateRefForm(data=request.POST) + if form.is_valid(): + ref = None + if form.cleaned_data["existingRef"]: + ref = form.cleaned_data["existingRef"] + else: + ref = Reference(name=form.cleaned_data["newRefName"]) + ref.save() + messages.info(request, "New Ref '%s' created" % ref) + + user.ref = ref + user.regTime = form.cleaned_data["regTime"] + user.location = form.cleaned_data["location"] + user.opName = form.cleaned_data["opName"] + user.save() + messages.success(request, "%s%s ref set to %s" % ("(shadow) " if shadow else "", user, ref)) + return HttpResponseRedirect(reverse("contest:registerRefs")) + else: + data = {} + if user.ref: + data["existingRef"] = user.ref + + if user.regTime: + data["regTime"] = user.regTime + else: + data["regTime"] = timezone.now() + data["opName"] = user.opName + data["location"] = user.location + + form = UpdateRefForm(initial=data) + + return render(request, 'contest/updateRef.html', {'userobj': user, 'form': form, "shadow": shadow}) @staff_member_required def viewAllQSOs(request, page=1): - qsos = QSO.objects.all().order_by("-time") - qsoPager = Paginator(qsos, 10) - qsoPage = getPage(qsoPager, request.GET.get('page')) + qsos = QSO.objects.all().order_by("-time") + qsoPager = Paginator(qsos, 10) + 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): - # FIXME: Hardcoded for cqtu... everywhere - c = Contest.objects.get(id=1) - qrgs = Frequency.objects.filter(band__contest=c).order_by("channel") - return render(request, 'contest/overview.html', {'contest': c, 'qrgs': qrgs}) + # FIXME: Hardcoded for cqtu... everywhere + c = Contest.objects.get(id=1) + qrgs = Frequency.objects.filter(band__contest=c).order_by("channel") + return render(request, 'contest/overview.html', {'contest': c, 'qrgs': qrgs}) def register(request): - form = None - if request.method == 'POST': - form = CustomUserCreationForm(data=request.POST) - if form.is_valid(): - form.save() - auth_login(request, form.instance) - messages.info(request, "Registration as user %s successfull!" % form.instance.username) + form = None + if request.method == 'POST': + form = CustomUserCreationForm(data=request.POST) + if form.is_valid(): + form.save() + auth_login(request, form.instance) + messages.info(request, "Registration as user %s successfull!" % form.instance.username) - return HttpResponseRedirect(reverse("contest:index")) - else: - form = CustomUserCreationForm() + return HttpResponseRedirect(reverse("contest:index")) + else: + form = CustomUserCreationForm() - return render(request, 'registration/register.html', {"form": form}) + return render(request, 'registration/register.html', {"form": form}) @login_required def profile(request): - pwForm = None - catForm = None - - if request.method == 'POST': - if request.POST.get("submit", None) == "pwchange": - pwForm = PasswordChangeForm(user=request.user, data=request.POST) - if pwForm.is_valid(): - pwForm.save() - auth_login(request, pwForm.user) - messages.success(request, "Password changed") - - return HttpResponseRedirect(reverse("profile")) - else: - catForm = UpdateCategoryForm(data=request.POST) - if catForm.is_valid(): - request.user.cat = catForm.cleaned_data["entry"] - request.user.save() - messages.success(request, "Entry category set") - - return HttpResponseRedirect(reverse("profile")) - - if not pwForm: - pwForm = PasswordChangeForm(user=request.user) - - if not catForm: - catForm = UpdateCategoryForm(initial={'entry': request.user.cat}) - - return render(request, 'registration/profile.html', {"pwForm": pwForm, "catForm": catForm}) + pwForm = None + catForm = None + + if request.method == 'POST': + if request.POST.get("submit", None) == "pwchange": + pwForm = PasswordChangeForm(user=request.user, data=request.POST) + if pwForm.is_valid(): + pwForm.save() + auth_login(request, pwForm.user) + messages.success(request, "Password changed") + + return HttpResponseRedirect(reverse("profile")) + else: + catForm = UpdateCategoryForm(data=request.POST) + if catForm.is_valid(): + request.user.cat = catForm.cleaned_data["entry"] + request.user.save() + messages.success(request, "Entry category set") + + return HttpResponseRedirect(reverse("profile")) + + if not pwForm: + pwForm = PasswordChangeForm(user=request.user) + + if not catForm: + catForm = UpdateCategoryForm(initial={'entry': request.user.cat}) + + return render(request, 'registration/profile.html', {"pwForm": pwForm, "catForm": catForm}) diff --git a/cqtu/settings.py b/cqtu/settings.py index 3c691e3..f5eb3c6 100644 --- a/cqtu/settings.py +++ b/cqtu/settings.py @@ -33,18 +33,17 @@ ALLOWED_HOSTS = [] # Application definition INSTALLED_APPS = [ - # default + # default 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', - - 'crispy_forms', + 'crispy_forms', - # local - 'contest', + # local + 'contest', ] MIDDLEWARE = [ @@ -140,6 +139,5 @@ STATICFILES_DIRS = [ CRISPY_TEMPLATE_PACK = 'bootstrap3' MESSAGE_TAGS = { - messages.ERROR: 'danger', + messages.ERROR: 'danger', } - diff --git a/cqtu/urls.py b/cqtu/urls.py index e9bb349..b869c81 100644 --- a/cqtu/urls.py +++ b/cqtu/urls.py @@ -26,17 +26,17 @@ from contest.views import index, register, profile urlpatterns = [ - url('^$', index, name="index"), - url('^cqtufm2019/', include('contest.urls', namespace='contest')), + url('^$', index, name="index"), + url('^cqtufm2019/', include('contest.urls', namespace='contest')), url(r'^admin/', admin.site.urls), - url(r'^login/$', auth_views.login, name='login'), - url(r'^logout/$', auth_views.logout, {'next_page': '/'}, name='logout'), - url(r'^register/$', register, name='register'), - url(r'^profile/$', profile, name='profile'), - #url(r'^register/$', CreateView.as_view( - # template_name='registration/register.html', - # form_class=CustomUserCreationForm, - # success_url='/', - #), name='register'), + url(r'^login/$', auth_views.login, name='login'), + url(r'^logout/$', auth_views.logout, {'next_page': '/'}, name='logout'), + url(r'^register/$', register, name='register'), + url(r'^profile/$', profile, name='profile'), + #url(r'^register/$', CreateView.as_view( + # template_name='registration/register.html', + # form_class=CustomUserCreationForm, + # success_url='/', + #), name='register'), ]