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)
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)