Пример #1
0
def rest_fact(request, fact_id):  #todo:refactor into facts
    if request.method == 'POST':
        # Update fact

        # Override the submitted deck ID with the ID from the URL.
        post_data = request.POST.copy()

        #todo: refactor this into model code

        # if this fact is a shared fact which the current subscribing user
        # hasn't copied yet, copy it first
        fact = Fact.objects.get_for_owner_or_subscriber(fact_id, request.user)

        #fact_form = FactForm(post_data, prefix='fact', instance=fact)
        FactFormset = modelformset_factory(Fact,
                                           fields=(
                                               'id',
                                               'fact_type',
                                           ),
                                           can_delete=True)
        fact_formset = FactFormset(post_data,
                                   prefix='fact',
                                   queryset=Fact.objects.filter(id=fact.id)
                                   | fact.subfacts)

        #TODO-OLD make from CardForm
        CardFormset = modelformset_factory(Card,
                                           exclude=(
                                               'fact',
                                               'ease_factor',
                                           ))
        card_formset = CardFormset(post_data,
                                   prefix='card',
                                   queryset=fact.card_set.get_query_set())

        FieldContentFormset = modelformset_factory(FieldContent,
                                                   form=FieldContentForm)
        field_content_queryset = (fact.fieldcontent_set.get_query_set()
                                  or None)
        field_content_formset = FieldContentFormset(post_data,
                                                    prefix='field_content')
        #, queryset=field_content_queryset)

        #fact_form = FactForm(post_data, prefix='fact', instance=fact)
        # ^^^^^^^ this isn't updated
        if (card_formset.is_valid() and field_content_formset.is_valid()
                and fact_formset.is_valid()):
            #fact = fact_form.save() #TODO-OLD needed in future?

            #update the fact's assigned deck
            #FIXME catch error if does not exist
            #deck_id = int(post_data['fact-deck'])
            #fact.deck = Deck.objects.get(id=deck_id)
            #fact.save()

            # maps subfact group numbers to the subfact object
            group_to_subfact = {}
            for field_content_form in field_content_formset.forms:
                field_content = field_content_form.save(commit=False)

                # is this a field of the parent fact, or a subfact?
                if field_content.field_type.fact_type == fact.fact_type:
                    # Parent fact.
                    field_content.fact = fact
                    field_content.save()
                else:
                    # Subfact.
                    # Does this subfact already belong to the user?
                    # If not, create it, only if anything's changed.
                    # Or, create it, if it's new.
                    if field_content_form.cleaned_data['id']:
                        # existing field content

                        # if it's part of a subfact that's being
                        # deleted in this form, ignore the field.
                        if field_content_form.cleaned_data['id'].fact in\
                            [fact_form.cleaned_data['id'] for fact_form
                             in fact_formset.deleted_forms]:
                            continue

                        if (field_content_form.cleaned_data['id'].fact.owner ==
                                request.user):
                            #TODO-OLD is this necessary? vvv
                            field_content.fact = \
                                    field_content_form.cleaned_data['id'].fact
                            field_content.save()
                        else:
                            original = field_content_form.cleaned_data['id']
                            if (field_content_form['content'] !=
                                    original.content):
                                # user updated subscribed subfact content
                                # - so create his own subscriber subfact to
                                # hold it.
                                new_subfact = original.fact.copy_to_parent_fact(
                                    fact, copy_field_contents=True)
                                new_field_content = new_subfact.fieldcontent_set.get(
                                    field_type=field_content_form.
                                    cleaned_data['field_type'])
                                new_field_content.content = \
                                        field_content_form.cleaned_data['content']
                                new_field_content.save()
                            else:
                                # not user's own, but he didn't update it anyway
                                pass
                    else:
                        # new field content
                        # this means new subfact.
                        # otherwise, this doesn't make sense unless the subfact
                        # model changed - which isn't supported yet.
                        # or subscriber fields are optimized to not copy over
                        # until modified
                        group = field_content_form.cleaned_data[
                            'subfact_group']
                        if group not in group_to_subfact.keys():
                            # create the new subfact
                            new_subfact = Fact(
                                fact_type=field_content.field_type.fact_type,
                                active=True,
                                parent_fact=fact)
                            new_subfact.save()
                            group_to_subfact[group] = new_subfact
                        field_content.fact = group_to_subfact[group]
                        field_content.save()

            # delete any subfacts as needed
            for subfact_form in fact_formset.deleted_forms:
                subfact = subfact_form.cleaned_data['id']
                # make sure it's a subfact
                if subfact.parent_fact:  # == fact:
                    if subfact.synchronized_with or subfact.parent_fact != fact:
                        # this is a subscriber fact
                        if subfact.synchronized_with:
                            subfact.active = False
                            subfact.save()
                        else:
                            # the user doesn't have his own copy of this
                            # subfact yet
                            new_subfact = subfact.copy_to_parent_fact(
                                fact, copy_field_contents=False)
                            new_subfact.active = False
                            new_subfact.save()
                    else:
                        subfact.delete()

            # disable any existing cards that weren't selected in the update,
            # or enable if selected and create if needed
            # do all this for subscribers too, if this is in a shared deck
            facts = Fact.objects.filter(id=fact.id)
            if fact.subscriber_facts.all():
                facts = facts | fact.subscriber_facts.all()
            for fact2 in facts.iterator():
                card_form_template_ids = dict(
                    (card_form.cleaned_data['template'].id, card_form)
                    for card_form in card_formset.forms)
                for card_template in fact.fact_type.cardtemplate_set.all():
                    if card_template.id in card_form_template_ids.keys():
                        try:
                            card = fact2.card_set.get(template=card_template)
                            card.activate()
                        except Card.DoesNotExist:
                            #card_form = card_form_template_ids
                            #[card_template.id]
                            #new_card = card_form.save(commit=False)
                            new_card = Card(template=card_template)
                            new_card.fact = fact2
                            new_card.active = True
                            new_card.randomize_new_order()
                            new_card.save()
                    else:
                        #card was not selected in update, so disable it
                        # if it exists
                        try:
                            card = fact2.card_set.get(template=card_template)
                            if not card.active:
                                continue
                            elif fact2.synchronized_with and card.review_count:
                                # don't disable subscriber cards which have
                                # already been reviewed
                                continue
                            card.deactivate()
                        except Card.DoesNotExist:
                            pass
        else:
            raise ApiException({
                'card': card_formset.errors,
                'fact': fact_formset.errors,
                'field_content': field_content_formset.errors,
            })
    elif request.method == 'DELETE':
        fact = Fact.objects.get_for_owner_or_subscriber(fact_id, request.user)
        deleted_fact = fact.delete_for_user(request.user)
        fact_deleted.send(deleted_fact)
Пример #2
0
def rest_fact(request, fact_id): #todo:refactor into facts
    if request.method == 'POST':
        # Update fact

        # Override the submitted deck ID with the ID from the URL.
        post_data = request.POST.copy()

        #todo: refactor this into model code

        # if this fact is a shared fact which the current subscribing user
        # hasn't copied yet, copy it first
        fact = Fact.objects.get_for_owner_or_subscriber(fact_id, request.user)

        #fact_form = FactForm(post_data, prefix='fact', instance=fact)
        FactFormset = modelformset_factory(
                Fact, fields=('id', 'fact_type',), can_delete=True)
        fact_formset = FactFormset(
                post_data, prefix='fact',
                queryset=Fact.objects.filter(id=fact.id)|fact.subfacts)

        #TODO-OLD make from CardForm
        CardFormset = modelformset_factory(
                Card, exclude=('fact', 'ease_factor', ))
        card_formset = CardFormset(
                post_data, prefix='card',
                queryset=fact.card_set.get_query_set())

        FieldContentFormset = modelformset_factory(
                FieldContent, form=FieldContentForm)
        field_content_queryset = (fact.fieldcontent_set.get_query_set()
                                  or None)
        field_content_formset = FieldContentFormset(
                post_data, prefix='field_content')
                #, queryset=field_content_queryset)

        #fact_form = FactForm(post_data, prefix='fact', instance=fact)
        # ^^^^^^^ this isn't updated
        if (card_formset.is_valid()
                and field_content_formset.is_valid()
                and fact_formset.is_valid()):
            #fact = fact_form.save() #TODO-OLD needed in future?

            #update the fact's assigned deck
            #FIXME catch error if does not exist
            #deck_id = int(post_data['fact-deck'])
            #fact.deck = Deck.objects.get(id=deck_id)
            #fact.save()

            # maps subfact group numbers to the subfact object
            group_to_subfact = {}
            for field_content_form in field_content_formset.forms:
                field_content = field_content_form.save(commit=False)

                # is this a field of the parent fact, or a subfact?
                if field_content.field_type.fact_type == fact.fact_type:
                    # Parent fact.
                    field_content.fact = fact
                    field_content.save()
                else:
                    # Subfact.
                    # Does this subfact already belong to the user?
                    # If not, create it, only if anything's changed.
                    # Or, create it, if it's new.
                    if field_content_form.cleaned_data['id']:
                        # existing field content

                        # if it's part of a subfact that's being
                        # deleted in this form, ignore the field.
                        if field_content_form.cleaned_data['id'].fact in\
                            [fact_form.cleaned_data['id'] for fact_form
                             in fact_formset.deleted_forms]:
                            continue

                        if (field_content_form.cleaned_data['id'].fact.owner
                                == request.user):
                            #TODO-OLD is this necessary? vvv
                            field_content.fact = \
                                    field_content_form.cleaned_data['id'].fact
                            field_content.save()
                        else:
                            original = field_content_form.cleaned_data['id']
                            if (field_content_form['content']
                                    != original.content):
                                # user updated subscribed subfact content
                                # - so create his own subscriber subfact to
                                # hold it.
                                new_subfact = original.fact.copy_to_parent_fact(
                                        fact, copy_field_contents=True)
                                new_field_content = new_subfact.fieldcontent_set.get(
                                        field_type=field_content_form.cleaned_data['field_type'])
                                new_field_content.content = \
                                        field_content_form.cleaned_data['content']
                                new_field_content.save()
                            else:
                                # not user's own, but he didn't update it anyway
                                pass
                    else:
                        # new field content
                        # this means new subfact.
                        # otherwise, this doesn't make sense unless the subfact
                        # model changed - which isn't supported yet.
                        # or subscriber fields are optimized to not copy over
                        # until modified
                        group = field_content_form.cleaned_data['subfact_group']
                        if group not in group_to_subfact.keys():
                            # create the new subfact
                            new_subfact = Fact(
                                fact_type=field_content.field_type.fact_type,
                                active=True,
                                parent_fact=fact
                            )
                            new_subfact.save()
                            group_to_subfact[group] = new_subfact
                        field_content.fact = group_to_subfact[group]
                        field_content.save()


            # delete any subfacts as needed
            for subfact_form in fact_formset.deleted_forms:
                subfact = subfact_form.cleaned_data['id']
                # make sure it's a subfact
                if subfact.parent_fact:# == fact:
                    if subfact.synchronized_with or subfact.parent_fact != fact:
                        # this is a subscriber fact
                        if subfact.synchronized_with:
                            subfact.active = False
                            subfact.save()
                        else:
                            # the user doesn't have his own copy of this
                            # subfact yet
                            new_subfact = subfact.copy_to_parent_fact(
                                    fact, copy_field_contents=False)
                            new_subfact.active = False
                            new_subfact.save()
                    else:
                        subfact.delete()


            # disable any existing cards that weren't selected in the update,
            # or enable if selected and create if needed
            # do all this for subscribers too, if this is in a shared deck
            facts = Fact.objects.filter(id=fact.id)
            if fact.subscriber_facts.all():
                facts = facts | fact.subscriber_facts.all()
            for fact2 in facts.iterator():
                card_form_template_ids = dict(
                        (card_form.cleaned_data['template'].id, card_form)
                        for card_form in card_formset.forms)
                for card_template in fact.fact_type.cardtemplate_set.all():
                    if card_template.id in card_form_template_ids.keys():
                        try:
                            card = fact2.card_set.get(template=card_template)
                            card.activate()
                        except Card.DoesNotExist:
                            #card_form = card_form_template_ids
                            #[card_template.id]
                            #new_card = card_form.save(commit=False)
                            new_card = Card(template=card_template)
                            new_card.fact = fact2
                            new_card.active = True
                            new_card.randomize_new_order()
                            new_card.save()
                    else:
                        #card was not selected in update, so disable it
                        # if it exists
                        try:
                            card = fact2.card_set.get(template=card_template)
                            if not card.active:
                                continue
                            elif fact2.synchronized_with and card.review_count:
                                # don't disable subscriber cards which have
                                # already been reviewed
                                continue
                            card.deactivate()
                        except Card.DoesNotExist:
                            pass
        else:
            raise ApiException({
                'card': card_formset.errors,
                'fact': fact_formset.errors,
                'field_content': field_content_formset.errors,
            })
    elif request.method == 'DELETE':
        fact = Fact.objects.get_for_owner_or_subscriber(fact_id, request.user)
        deleted_fact = fact.delete_for_user(request.user)
        fact_deleted.send(deleted_fact)