示例#1
0
def edit_queue(request, queue_id=None):

    template = 'admin/queues/form.html'

    if queue_id:
        queue = Queue.objects.get(pk=queue_id)
        queue_form = QueueForm(instance=queue, prefix='queue')
    else:
        queue = Queue()
        queue_form = QueueForm(prefix='queue')

    if request.method == 'POST':

        if queue_id is None:
            queue_form = QueueForm(request.POST, request.FILES, prefix='queue')
        else:
            queue = Queue.objects.get(pk=queue_id)
            queue_form = QueueForm(request.POST, request.FILES, instance=queue, prefix='queue')

        if not queue_form.is_valid():
            return render(request, template, {'queue_form': queue_form})

        queue_form.save()

        # process queue's statuses
        queue.queuestatus_set.all().delete()
        data = DotExpandedDict(request.POST)

        if data.get('status'):
            for s in data['status'].values():
                if s.get('status_id'): # status is selected...
                    qs = s
                    qs['queue'] = queue
                    QueueStatus.objects.create(**qs)

        messages.add_message(request, messages.INFO, _(u'Jono tallennettu'))
        return redirect('/admin/queues/')

    selected = list()

    for s in queue.queuestatus_set.all():
        selected.append(s.status.pk)

    statuses = list()

    for s in Status.objects.all():
        if s.id in selected:
            stat = queue.queuestatus_set.get(status_id=s.id)
            s.limit_green = stat.limit_green
            s.limit_yellow = stat.limit_yellow
            s.limit_factor = stat.limit_factor

        statuses.append(s)

    return render(request, template, {
        'queue_form': queue_form,
        'statuses': statuses,
        'selected': selected
    })
    def test_dotexpandeddict(self):

        d = DotExpandedDict({
            'person.1.firstname': ['Simon'],
            'person.1.lastname': ['Willison'],
            'person.2.firstname': ['Adrian'],
            'person.2.lastname': ['Holovaty']
        })

        self.assertEqual(d['person']['1']['lastname'], ['Willison'])
        self.assertEqual(d['person']['2']['lastname'], ['Holovaty'])
        self.assertEqual(d['person']['2']['firstname'], ['Adrian'])
示例#3
0
    def value_from_datadict(self, data, files, name, *args, **kwargs):
        reminder_events_raw = {}
        for key in data:
            if key[0:16] == "reminder_events.":
                reminder_events_raw[key] = data[key]

        event_dict = DotExpandedDict(reminder_events_raw)
        events = []
        if len(event_dict) > 0:
            for key in sorted(event_dict["reminder_events"].iterkeys()):
                events.append(event_dict["reminder_events"][key])

        return events
示例#4
0
    def value_from_datadict(self, data, files, name, *args, **kwargs):
        input_name = self.attrs["input_name"]
        raw = {}
        for key in data:
            if key.startswith(input_name + "."):
                raw[key] = data[key]

        data_dict = DotExpandedDict(raw)
        data_list = []
        if len(data_dict) > 0:
            for key in sorted(data_dict[input_name].iterkeys()):
                data_list.append(data_dict[input_name][key])

        return data_list
示例#5
0
    def save(self, new_data):
        # TODO: big cleanup when core fields go -> use recursive manipulators.
        params = {}
        for f in self.opts.fields:
            # Fields with auto_now_add should keep their original value in the change stage.
            auto_now_add = self.change and getattr(f, 'auto_now_add', False)
            if self.follow.get(f.name, None) and not auto_now_add:
                param = f.get_manipulator_new_data(new_data)
            else:
                if self.change:
                    param = getattr(self.original_object, f.attname)
                else:
                    param = f.get_default()
            params[f.attname] = param

        if self.change:
            params[self.opts.pk.attname] = self.obj_key

        # First, create the basic object itself.
        new_object = self.model(**params)

        # Now that the object's been created, save any uploaded files.
        for f in self.opts.fields:
            if isinstance(f, FileField):
                f.save_file(new_data,
                            new_object,
                            self.change and self.original_object or None,
                            self.change,
                            rel=False,
                            save=False)

        # Now save the object
        new_object.save()

        # Calculate which primary fields have changed.
        if self.change:
            self.fields_added, self.fields_changed, self.fields_deleted = [], [], []
            for f in self.opts.fields:
                if not f.primary_key and smart_str(
                        getattr(self.original_object, f.attname)) != smart_str(
                            getattr(new_object, f.attname)):
                    self.fields_changed.append(f.verbose_name)

        # Save many-to-many objects. Example: Set sites for a poll.
        for f in self.opts.many_to_many:
            if self.follow.get(f.name, None):
                if not f.rel.edit_inline:
                    new_vals = new_data.getlist(f.name)
                    # First, clear the existing values.
                    rel_manager = getattr(new_object, f.name)
                    rel_manager.clear()
                    # Then, set the new values.
                    for n in new_vals:
                        rel_manager.add(f.rel.to._default_manager.get(pk=n))
                    # TODO: Add to 'fields_changed'

        expanded_data = DotExpandedDict(dict(new_data))
        # Save many-to-one objects. Example: Add the Choice objects for a Poll.
        for related in self.opts.get_all_related_objects():
            # Create obj_list, which is a DotExpandedDict such as this:
            # [('0', {'id': ['940'], 'choice': ['This is the first choice']}),
            #  ('1', {'id': ['941'], 'choice': ['This is the second choice']}),
            #  ('2', {'id': [''], 'choice': ['']})]
            child_follow = self.follow.get(related.name, None)

            if child_follow:
                obj_list = expanded_data.get(related.var_name, {}).items()
                if not obj_list:
                    continue

                obj_list.sort(lambda x, y: cmp(int(x[0]), int(y[0])))

                # For each related item...
                for _, rel_new_data in obj_list:

                    params = {}

                    # Keep track of which core=True fields were provided.
                    # If all core fields were given, the related object will be saved.
                    # If none of the core fields were given, the object will be deleted.
                    # If some, but not all, of the fields were given, the validator would
                    # have caught that.
                    all_cores_given, all_cores_blank = True, True

                    # Get a reference to the old object. We'll use it to compare the
                    # old to the new, to see which fields have changed.
                    old_rel_obj = None
                    if self.change:
                        if rel_new_data[related.opts.pk.name][0]:
                            try:
                                old_rel_obj = getattr(
                                    self.original_object,
                                    related.get_accessor_name()).get(
                                        **{
                                            '%s__exact' % related.opts.pk.name:
                                            rel_new_data[
                                                related.opts.pk.attname][0]
                                        })
                            except ObjectDoesNotExist:
                                pass

                    for f in related.opts.fields:
                        if f.core and not isinstance(
                                f, FileField) and f.get_manipulator_new_data(
                                    rel_new_data, rel=True) in (None, ''):
                            all_cores_given = False
                        elif f.core and not isinstance(
                                f, FileField) and f.get_manipulator_new_data(
                                    rel_new_data, rel=True) not in (None, ''):
                            all_cores_blank = False
                        # If this field isn't editable, give it the same value it had
                        # previously, according to the given ID. If the ID wasn't
                        # given, use a default value. FileFields are also a special
                        # case, because they'll be dealt with later.

                        if f == related.field:
                            param = getattr(
                                new_object,
                                related.field.rel.get_related_field().attname)
                        elif (not self.change) and isinstance(f, AutoField):
                            param = None
                        elif self.change and (
                                isinstance(f, FileField)
                                or not child_follow.get(f.name, None)):
                            if old_rel_obj:
                                param = getattr(old_rel_obj, f.column)
                            else:
                                param = f.get_default()
                        else:
                            param = f.get_manipulator_new_data(rel_new_data,
                                                               rel=True)
                        if param != None:
                            params[f.attname] = param

                    # Create the related item.
                    new_rel_obj = related.model(**params)

                    # If all the core fields were provided (non-empty), save the item.
                    if all_cores_given:
                        new_rel_obj.save()

                        # Save any uploaded files.
                        for f in related.opts.fields:
                            if child_follow.get(f.name, None):
                                if isinstance(f,
                                              FileField) and rel_new_data.get(
                                                  f.name, False):
                                    f.save_file(rel_new_data,
                                                new_rel_obj,
                                                self.change and old_rel_obj
                                                or None,
                                                old_rel_obj is not None,
                                                rel=True)

                        # Calculate whether any fields have changed.
                        if self.change:
                            if not old_rel_obj:  # This object didn't exist before.
                                self.fields_added.append(
                                    '%s "%s"' %
                                    (related.opts.verbose_name, new_rel_obj))
                            else:
                                for f in related.opts.fields:
                                    if not f.primary_key and f != related.field and smart_str(
                                            getattr(old_rel_obj, f.attname)
                                    ) != smart_str(
                                            getattr(new_rel_obj, f.attname)):
                                        self.fields_changed.append(
                                            '%s for %s "%s"' %
                                            (f.verbose_name,
                                             related.opts.verbose_name,
                                             new_rel_obj))

                        # Save many-to-many objects.
                        for f in related.opts.many_to_many:
                            if child_follow.get(
                                    f.name, None) and not f.rel.edit_inline:
                                new_value = rel_new_data[f.attname]
                                setattr(
                                    new_rel_obj, f.name,
                                    f.rel.to.objects.filter(pk__in=new_value))
                                if self.change:
                                    self.fields_changed.append(
                                        '%s for %s "%s"' %
                                        (f.verbose_name,
                                         related.opts.verbose_name,
                                         new_rel_obj))

                    # If, in the change stage, all of the core fields were blank and
                    # the primary key (ID) was provided, delete the item.
                    if self.change and all_cores_blank and old_rel_obj:
                        new_rel_obj.delete()
                        self.fields_deleted.append(
                            '%s "%s"' %
                            (related.opts.verbose_name, old_rel_obj))

        # Save the order, if applicable.
        if self.change and self.opts.get_ordered_objects():
            order = new_data['order_'] and map(
                int, new_data['order_'].split(',')) or []
            for rel_opts in self.opts.get_ordered_objects():
                getattr(new_object,
                        'set_%s_order' % rel_opts.object_name.lower())(order)
        return new_object
示例#6
0
    def save(self, new_data):
        # TODO: big cleanup when core fields go -> use recursive manipulators.
        params = {}
        for f in self.opts.fields:
            # Fields with auto_now_add should keep their original value in the change stage.
            auto_now_add = self.change and getattr(f, 'auto_now_add', False)
            if self.follow.get(f.name, None) and not auto_now_add:
                param = f.get_manipulator_new_data(new_data)
            else:
                if self.change:
                    param = getattr(self.original_object, f.attname)
                else:
                    param = f.get_default()
            params[f.attname] = param

        if self.change:
            params[self.opts.pk.attname] = self.obj_key

        # First, create the basic object itself.
        new_object = self.model(**params)

        # Now that the object's been created, save any uploaded files.
        for f in self.opts.fields:
            if isinstance(f, FileField):
                f.save_file(new_data, new_object, self.change and self.original_object or None, self.change, rel=False, save=False)

        # Now save the object
        new_object.save()

        # Calculate which primary fields have changed.
        if self.change:
            self.fields_added, self.fields_changed, self.fields_deleted = [], [], []
            for f in self.opts.fields:
                if not f.primary_key and str(getattr(self.original_object, f.attname)) != str(getattr(new_object, f.attname)):
                    self.fields_changed.append(f.verbose_name)

        # Save many-to-many objects. Example: Set sites for a poll.
        for f in self.opts.many_to_many:
            if self.follow.get(f.name, None):
                if not f.rel.edit_inline:
                    if f.rel.raw_id_admin:
                        new_vals = new_data.get(f.name, ())
                    else:
                        new_vals = new_data.getlist(f.name)
                    # First, clear the existing values.
                    rel_manager = getattr(new_object, f.name)
                    rel_manager.clear()
                    # Then, set the new values.
                    for n in new_vals:
                        rel_manager.add(f.rel.to._default_manager.get(pk=n))
                    # TODO: Add to 'fields_changed'

        expanded_data = DotExpandedDict(dict(new_data))
        # Save many-to-one objects. Example: Add the Choice objects for a Poll.
        for related in self.opts.get_all_related_objects():
            # Create obj_list, which is a DotExpandedDict such as this:
            # [('0', {'id': ['940'], 'choice': ['This is the first choice']}),
            #  ('1', {'id': ['941'], 'choice': ['This is the second choice']}),
            #  ('2', {'id': [''], 'choice': ['']})]
            child_follow = self.follow.get(related.name, None)

            if child_follow:
                obj_list = expanded_data.get(related.var_name, {}).items()
                if not obj_list:
                    continue

                obj_list.sort(lambda x, y: cmp(int(x[0]), int(y[0])))

                # For each related item...
                for _, rel_new_data in obj_list:

                    params = {}

                    # Keep track of which core=True fields were provided.
                    # If all core fields were given, the related object will be saved.
                    # If none of the core fields were given, the object will be deleted.
                    # If some, but not all, of the fields were given, the validator would
                    # have caught that.
                    all_cores_given, all_cores_blank = True, True

                    # Get a reference to the old object. We'll use it to compare the
                    # old to the new, to see which fields have changed.
                    old_rel_obj = None
                    if self.change:
                        if rel_new_data[related.opts.pk.name][0]:
                            try:
                                old_rel_obj = getattr(self.original_object, related.get_accessor_name()).get(**{'%s__exact' % related.opts.pk.name: rel_new_data[related.opts.pk.attname][0]})
                            except ObjectDoesNotExist:
                                pass

                    for f in related.opts.fields:
                        if f.core and not isinstance(f, FileField) and f.get_manipulator_new_data(rel_new_data, rel=True) in (None, ''):
                            all_cores_given = False
                        elif f.core and not isinstance(f, FileField) and f.get_manipulator_new_data(rel_new_data, rel=True) not in (None, ''):
                            all_cores_blank = False
                        # If this field isn't editable, give it the same value it had
                        # previously, according to the given ID. If the ID wasn't
                        # given, use a default value. FileFields are also a special
                        # case, because they'll be dealt with later.

                        if f == related.field:
                            param = getattr(new_object, related.field.rel.get_related_field().attname)
                        elif (not self.change) and isinstance(f, AutoField):
                            param = None
                        elif self.change and (isinstance(f, FileField) or not child_follow.get(f.name, None)):
                            if old_rel_obj:
                                param = getattr(old_rel_obj, f.column)
                            else:
                                param = f.get_default()
                        else:
                            param = f.get_manipulator_new_data(rel_new_data, rel=True)
                        if param != None:
                            params[f.attname] = param

                    # Create the related item.
                    new_rel_obj = related.model(**params)

                    # If all the core fields were provided (non-empty), save the item.
                    if all_cores_given:
                        new_rel_obj.save()

                        # Save any uploaded files.
                        for f in related.opts.fields:
                            if child_follow.get(f.name, None):
                                if isinstance(f, FileField) and rel_new_data.get(f.name, False):
                                    f.save_file(rel_new_data, new_rel_obj, self.change and old_rel_obj or None, old_rel_obj is not None, rel=True)

                        # Calculate whether any fields have changed.
                        if self.change:
                            if not old_rel_obj: # This object didn't exist before.
                                self.fields_added.append('%s "%s"' % (related.opts.verbose_name, new_rel_obj))
                            else:
                                for f in related.opts.fields:
                                    if not f.primary_key and f != related.field and str(getattr(old_rel_obj, f.attname)) != str(getattr(new_rel_obj, f.attname)):
                                        self.fields_changed.append('%s for %s "%s"' % (f.verbose_name, related.opts.verbose_name, new_rel_obj))

                        # Save many-to-many objects.
                        for f in related.opts.many_to_many:
                            if child_follow.get(f.name, None) and not f.rel.edit_inline:
                                new_value = rel_new_data[f.attname]
                                if f.rel.raw_id_admin:
                                    new_value = new_value[0]
                                setattr(new_rel_obj, f.name, f.rel.to.objects.filter(pk__in=new_value))
                                if self.change:
                                    self.fields_changed.append('%s for %s "%s"' % (f.verbose_name, related.opts.verbose_name, new_rel_obj))

                    # If, in the change stage, all of the core fields were blank and
                    # the primary key (ID) was provided, delete the item.
                    if self.change and all_cores_blank and old_rel_obj:
                        new_rel_obj.delete()
                        self.fields_deleted.append('%s "%s"' % (related.opts.verbose_name, old_rel_obj))

        # Save the order, if applicable.
        if self.change and self.opts.get_ordered_objects():
            order = new_data['order_'] and map(int, new_data['order_'].split(',')) or []
            for rel_opts in self.opts.get_ordered_objects():
                getattr(new_object, 'set_%s_order' % rel_opts.object_name.lower())(order)
        return new_object
    def post(self, request, *args, **kwargs):
        error = False
        dotdict = DotExpandedDict(request.POST)

        self.object = self.get_object()

        if self.request.user.is_authenticated():
            if dotdict.has_key('assignment') and self.object.status == 'C':
                messages.error(self.request, 'You cannot change the assignment of a closed activity.')
                error = True
            elif dotdict.get('assignment', ''):
                user_id = dotdict['assignment'].get('user', '')
                priority = dotdict['assignment'].get('priority', '')
                escalation_status = dotdict['assignment'].get('escalation_status', '')
                user = None

                if user_id:
                    try:
                        user = User.objects.get(pk=int(user_id))
                    except (User.DoesNotExist, ValueError):
                        messages.error(self.request, 'User with id %s does not exist.' % user_id)
                        error = True


                if priority:
                    try:
                        priority = int(priority)
                    except ValueError:
                        messages.error(self.request, 'Priority must be an integer.')
                        error = True

                if not error:
                    error = not self.assign_user(user, priority, escalation_status)

            if dotdict.has_key('approved_id'):
                approved_id = dotdict.get('approved_id', '').strip()
                if self.object.status == 'C':
                    messages.error(self.request, 'You cannot approve a closed activity.')
                    error = True
                elif approved_id and not error:
                    error = not self.approve_activity(approved_id)
                else:
                    messages.error(self.request, 'You must provide an Approved ID.')
                    error = True

            if dotdict.has_key('task'):
                assigned_user_id = dotdict['task'].get('assigned_user', '')
                assigned_user = None
                id = dotdict['task'].get('id', '')
                task_id = dotdict['task'].get('task_id', '')
                task = None
                status = dotdict['task'].get('status', '')

                if assigned_user_id:
                    try:
                        assigned_user = User.objects.get(pk=int(assigned_user_id))
                    except (User.DoesNotExist, ValueError):
                        messages.error(self.request, 'User with id %s does not exist.' % user_id)
                        error = True
                elif not id:
                    messages.error(self.request, 'You must assign the task to a user.')
                    error = True

                if not id:
                    try:
                        task = Task.objects.get(pk=int(task_id))
                    except(Task.DoesNotExist, ValueError):
                        messages.error(self.request, 'Task with id %s is not a valid task.' % task_id)
                        error = True

                if not error:
                    error = not self.update_task(id, task, assigned_user, status)

            if dotdict.get('note', ''):
                message = dotdict['note'].get('message', '').strip()

                if not error:
                    error = not self.add_note(message, self.request.user)


            status = dotdict.get('status', '')
            if status == 'C':
                if not error:
                    error = not self.close_activity()
        else:
            messages.error(self.request, 'You must be logged in to edit an activity.')
            error = True

        if error:
            context = self.get_context_data()
            return self.render_to_response(context)
        else:
            return HttpResponseRedirect(self.request.get_full_path())
示例#8
0
def pick_sightings(request, redirect_to):
    """
    A replacement for the old add_sightings view. This one is designed to 
    sit in between two different parts of the interface. It narrows down
    the list of entered text to concrete species as before, then forwards 
    the user on to the redirect_to URL with concrete species IDs attached.
    
    For example, the resulting redirect may look like this:
    
    /gb/london-zoo/add-trip/?saw=x:2ab1&saw=s:123&saw=A+baby+tiger
    
    Note that there are now three types of saw IDs:
    
       x:* = a Xapian search ID
       s:* = an animals_species table ID
       *   = free text not matched in our database
    
    Our sightings recording mechanism is now expected to be able to deal with 
    free text, which will be recorded using species_inexact on a Sighting.
    
    The INPUT to this view should start off as something like this:
    
    ../pick-sightings/?saw.1.s=tiger&saw.2.s=pony
    
    If there are any ?saw= items, the view redirects straight away turning
    them in to that format. So, the easiest way to get started with the 
    process is to send someone to:
    
    ../pick-sightings/?saw=tiger&saw=pony
    
    If called with no arguments, starts off with an empty "I saw" form
    
    Additionally, if you include a `trip` parameter in the query string, that's
    the id of the trip we'll add to directly; this just gets passed through to
    
    (This is an ugly implementation in terms of URLs, but was the easiest.)
    
    """
    if request.GET.getlist('saw'):
        # Convert ?saw= arguments to ?saw.1.s= type things
        return Redirect(request.path + '?' + urllib.urlencode([
            ('saw.%d.s' % i, saw.strip())
            for i, saw in enumerate(request.GET.getlist('saw'))
            if saw.strip()
        ]))
    
    saw = DotExpandedDict(request.GET).get('saw')
    if request.GET and not saw:
        # Clear out the invalid query string
        return Redirect(request.path)
    
    if not saw:
        assert False, "Jump straight to showing the empty form"
    
    # saw should now of format {'0': {'s': 'tiger', 'o': 'x:ba3'}...}
    # Essentially a dictionary of key/dict pairs. The key doesn't actually 
    # matter, it's just used to group values. The dict looks like this:
    #     s = The text the user entered (required)
    #     o = The option they picked to fulfill it (optional)
    #     r = The replacement search they want to run (defaults to same as s)
    # The 'o' value comes from a radio select and can be of these formats:
    #     x_*    = a Xapian search ID they have selected
    #     s_*    = a Species ID they have selected
    #     cancel = don't save this at all (e.g. "I made a mistake")
    #     as-is  = save it using species_inexact
    #     search-again = run the replacement search instead
    
    # Are we done yet? The aim is for every key to have a valid option 
    # provided that isn't 'search-again'.
    if saw and is_valid_saw_list(saw.values()):
        next_vars = [
            urllib.urlencode({
                'saw': d['o'] == 'as-is' and d.get('s') or d['o']
            })
            for d in saw.values()
            if d.get('s') and (d['o'] != 'cancel')
        ]
        if request.GET.get('trip', None):
            next_vars.append(
                urllib.urlencode({
                    'trip': request.GET['trip']
                })
            )
        return Redirect(redirect_to + '?' + '&'.join(next_vars))
    
    # We aren't done, so we need to build up all of the information required
    # to construct our big form full of options, search results etc
    sections = []
    
    section_id = 0
    label_id = 0
    if saw:
        for key in sorted(saw.keys(), key = lambda k: int(k)):
            d = saw[key]
            search = d.get('r', d['s']).strip()
            if not search:
                continue
            results = list(search_species(search, 20))
            db_matches = list(Species.objects.filter(freebase_id__in = [
                r['freebase_id'] for r in results
            ]))
            choices = []
            is_first = True
            for row in results:
                try:
                    id = 's_%s' % [
                        s for s in db_matches 
                        if s.freebase_id == row['freebase_id']
                    ][0].id
                except IndexError:
                    id = 'x_%s' % row['search_id']
                choices.append({
                    'id': id,
                    'common_name': row['common_name'],
                    'scientific_name': row['scientific_name'],
                    'label_id': label_id,
                    'checked': (d.get('o') == id or (
                        is_first and d.get('o') != 'cancel'
                    )),
                })
                label_id += 1
                is_first = False
            
            sections.append({
                'id': section_id,
                'search': d.get('r', d['s']), # Pick up replacement search
                'options': choices,
                'o': d.get('o'),
            })
            section_id += 1
    
    return render(request, 'trips/pick_sightings.html', {
        'sections': sections,
        'redirect_to': redirect_to,
        'bonus_label_id': section_id,
        'trip_id': request.GET.get('trip', None),
    })