示例#1
0
文件: views.py 项目: simensma/sherpa
def edit(request, aktivitet):
    if request.method == 'GET':
        aktivitet = Aktivitet.objects.prefetch_related('municipalities', 'counties').get(id=aktivitet)
        context = {
            'aktivitet': aktivitet,
            'difficulties': Aktivitet.DIFFICULTY_CHOICES,
            'audiences': AktivitetAudience.AUDIENCE_CHOICES,
            'categories': Aktivitet.CATEGORY_CHOICES,
            'all_foreninger': Forening.get_all_sorted(),
            'cabins': Cabin.objects.order_by('name'),
            'admin_user_search_char_length': settings.ADMIN_USER_SEARCH_CHAR_LENGTH,
            'counties': County.typical_objects().order_by('name'),
            'municipalities': Municipality.objects.order_by('name'),
            'omrader': sorted(Omrade.lookup(), key=lambda o: o.navn),
            'now': datetime.now()
        }
        return render(request, 'common/admin/aktiviteter/edit/edit.html', context)
    elif request.method == 'POST':
        errors = False

        aktivitet = Aktivitet.objects.get(id=aktivitet)

        if aktivitet.is_imported():
            # Should only be possible by circumventing client-side restrictions
            return redirect('admin.aktiviteter.views.edit', aktivitet.id)

        if 'code' in request.POST:
            aktivitet.code = request.POST['code']

        if 'title' in request.POST:
            aktivitet.title = request.POST['title']

        if 'description' in request.POST:
            aktivitet.description = request.POST['description']

        if 'difficulty' in request.POST:
            aktivitet.difficulty = request.POST['difficulty']

        if 'audiences' in request.POST:
            aktivitet.audiences = [
                AktivitetAudience.objects.get(name=audience)
                for audience in request.POST.getlist('audiences')
            ]

        if 'category' in request.POST:
            aktivitet.category = request.POST['category']

        if 'category_type' in request.POST:
            aktivitet.category_type = request.POST['category_type']

        if 'publish' in request.POST:
            aktivitet.published = request.POST.get('publish') == 'publish'

        if 'getting_there' in request.POST:
            aktivitet.getting_there = request.POST['getting_there']

        if 'omrader' in request.POST:
            aktivitet.omrader = request.POST.getlist('omrader')

        if 'ntb_id' not in request.POST or request.POST['ntb_id'] == '':
            aktivitet.turforslag = None
        else:
            aktivitet.turforslag = request.POST['ntb_id']

        if aktivitet.published:
            # If published, set the extra relevant fields (otherwise ignore them)
            aktivitet.private = request.POST['private'] == 'private'
            try:
                aktivitet.pub_date = datetime.strptime(request.POST['pub_date'], "%d.%m.%Y").date()
            except ValueError:
                errors = True
                messages.error(request, 'invalid_date_format')

        forening_type, forening_id = request.POST['forening'].split(':')
        if forening_type == 'forening':
            forening = Forening.objects.get(id=forening_id)
            if not forening in request.user.children_foreninger():
                raise PermissionDenied
            aktivitet.forening = forening
        elif forening_type == 'cabin':
            aktivitet.forening_cabin = Cabin.objects.get(id=forening_id)
        else:
            raise PermissionDenied

        if 'co_foreninger[]' in request.POST and request.POST['co_foreninger[]'] != '':
            co_foreninger = []
            co_foreninger_cabin = []
            for co_forening in request.POST.getlist('co_foreninger[]'):
                type, id = co_forening.split(':')
                if type == 'forening':
                    co_foreninger.append(id)
                elif type == 'cabin':
                    co_foreninger_cabin.append(id)
                else:
                    raise PermissionDenied

            aktivitet.co_foreninger = co_foreninger
            aktivitet.co_foreninger_cabin = co_foreninger_cabin
        else:
            aktivitet.co_foreninger = []
            aktivitet.co_foreninger_cabin = []

        if 'latlng' in request.POST:
            latlng = request.POST['latlng'].split(',')
            if len(latlng) == 2:
                aktivitet.start_point = Point(float(latlng[0]), float(latlng[1]))

        aktivitet.save()

        aktivitet.counties = request.POST.getlist('counties')
        aktivitet.municipalities = request.POST.getlist('municipalities')

        aktivitet.category_tags.clear()
        if 'category_tags' in request.POST and request.POST['category_tags'] != '':
            for tag in request.POST.getlist('category_tags'):
                obj, created = Tag.objects.get_or_create(name=tag)
                aktivitet.category_tags.add(obj)

        aktivitet.images.all().delete()
        for i, image in parse_html_array(request.POST, 'images').items():
            AktivitetImage(
                aktivitet=aktivitet,
                url=image['url'],
                text=image['description'],
                photographer=image['photographer'],
                order=i
            ).save()

        dates = parse_html_array(request.POST, 'dates').items()

        # Remove the date objects that were explicitly deleted (checks and verifications are done
        # client-side). Verify that those that would be implicitly deleted (by not being POSTed for
        # editing) match those explicitly POSTed.
        date_ids = [int(d['id']) for k, d in dates if d['id'] != '']
        implicit_del = set([date.id for date in aktivitet.dates.all() if date.id not in date_ids])

        if len(implicit_del) > 0:
            # Better to raise an exception and not delete anything. The user will be confused and
            # lose edits, but we'll get a report and hopefully be able to fix this, if it ever
            # happens.
            raise Exception("Implicit delete of AktivitetDate is strictly forbidden!")

        for i, date in dates:
            if date['id'] != '':
                # @TODO Check if this can be exploited. Can you hijack another trip's date by
                # setting an arbitrary ID in the date['id'] field?
                model = AktivitetDate.objects.get(id=date['id'])
            else:
                model = AktivitetDate(aktivitet=aktivitet)

            # @TODO for existing dates; if model.start_date > now; dissalow editing.

            # Explicit delete of dates
            if date['status'] == 'delete':
                if date['id'] != '':
                    if model.participant_count() > 0:
                        raise Exception("Date with participants can not be deleted!")
                    model.delete()
                continue

            try:
                if not date['start_time']: date['start_time'] = '08:00'
                if not date['end_time']: date['end_time'] = '16:00'

                # @TODO check start_time > now
                model.start_date = datetime.strptime(
                    "%s %s" % (date['start_date'], date['start_time']),
                    "%d.%m.%Y %H:%M"
                )

                # @TODO check end_time > start_time
                model.end_date = datetime.strptime(
                    "%s %s" % (date['end_date'], date['end_time']),
                    "%d.%m.%Y %H:%M"
                )

                # @TODO check start_date > meeting_time
                if date['start_date'] and date['meeting_time']:
                    model.meeting_time = datetime.strptime(
                        "%s %s" % (date['start_date'], date['meeting_time']),
                        "%d.%m.%Y %H:%M"
                    )

                if not date['signup_method'] or date['signup_method'] == 'none':
                    # To the next maintainer. This block indicates that a date does not allow
                    # signup. However, keep in mind that this might be an existing date with
                    # participants. Hence, do not set model.participant to None event though it
                    # might be tempting!

                    model.signup_enabled = False
                    model.signup_start = None
                    model.signup_deadline = None
                    model.cancel_deadline = None

                elif date['signup_method'] == 'normal' or date['signup_method'] == 'simple':
                    model.signup_enabled = True

                    if date.get('max_participants_limited'):
                        model.max_participants = date['max_participants']
                    else:
                        model.max_participants = None

                    if date.get('no_signup_start') == '1':
                        model.signup_start = None
                    else:
                        model.signup_start = datetime.strptime(
                            date['signup_start'],
                            "%d.%m.%Y",
                        ).date()

                    if 'no_signup_deadline' in date and date['no_signup_deadline'] == '1':
                        model.signup_deadline = None
                    elif 'signup_deadline' in date and date['signup_deadline'] != '':
                        model.signup_deadline = datetime.strptime(
                            date['signup_deadline'],
                            "%d.%m.%Y",
                        ).date()

                    if 'no_cancel_deadline' in date and date['no_cancel_deadline'] == '1':
                        model.cancel_deadline = None
                    elif 'cancel_deadline' in date and date['cancel_deadline'] != '':
                        model.cancel_deadline = datetime.strptime(
                            date['cancel_deadline'], "%d.%m.%Y"
                        ).date()

                else:
                    raise Exception("Unrecognized POST value for signup_method field")

            except ValueError:
                errors = True
                messages.error(request, 'invalid_date_format')
                return redirect('admin.aktiviteter.views.edit', aktivitet.id)

            # Note that simple signup is currently disabled and due to be removed
            model.signup_simple_allowed = False
            model.meeting_place = date['meeting_place']
            model.contact_type = date['contact_type']
            model.contact_custom_name = date['contact_custom_name']
            model.contact_custom_phone = date['contact_custom_phone']
            model.contact_custom_email = date['contact_custom_email']
            model.should_have_turleder = date.get('should_have_turleder') == '1'
            model.save()

            if date.get('should_have_turleder') == '1':
                # We need to specify the key for this particular field because the parse_html_array
                # function does not properly parse multidimensional arrays.
                key = 'dates[%s][turleder][]' % i
                if key in request.POST and request.POST[key] != '':
                    model.turledere = request.POST.getlist(key)
            else:
                model.turledere = []

        if not errors:
            messages.info(request, 'save_success')

        if json.loads(request.POST['preview']):
            return redirect('admin.aktiviteter.views.preview', aktivitet.id)
        else:
            return redirect('admin.aktiviteter.views.edit', aktivitet.id)