trouselife
trouselife

Reputation: 969

Django modelform - make a modelform that provides a choice based on other models

I want a ModelForm called AddManualVariantForm which is a modelform of my model VariantAnnotationSampleRun.

This model is foreign key linked to VariantAnnotation and SampleRun models:

class VariantAnnotationSampleRun(models.Model):

    variant_annotation_id = models.ForeignKey(VariantAnnotation,
        on_delete=models.CASCADE, db_column='variant_annotation_id')

    sample_run_id = models.ForeignKey(SampleRun,
        on_delete=models.CASCADE, db_column='sample_run_id')

I want to make a modelform which will CREATE a VariantAnnotationSampleRun instance. Basically, I want to display 5 'VariantAnnotation' instances in relation to 1 SampleRun on my page, and if the user selects a checkbox, create a VariantAnnotationSampleRun instance.

Firstly - am i correct in doing this as a VariantAnnotationSampleRun modelform?

Here is what I am trying at the moment:

forms.py:

class AddManualVariantForm(forms.ModelForm):


    report = forms.ChoiceField(
                    choices =(
                        ("dontreport", '-'),
                        ("report" , 'Report'),
                        ("toconfirm", 'To confirm')
                        ),
                    label = 'report'
                    )


    class Meta:
        model = VariantAnnotationSampleRun
        fields = ('id', 'report')


    def __init__(self, *args, **kwargs):
        sample_obj = kwargs.pop('sample_obj', None)
        super(AddManualVariantForm, self).__init__(*args, **kwargs)

views.py:

class VariantSampleRunList(LoginRequiredMixin, View):

    addvariantform = AddManualVariantForm

    def get(self, request, *args, **kwargs):

        va_lst = [..list of VariantAnnotation IDs I want to include...]

        FormSet = modelformset_factory(
                VariantAnnotationSampleRun,
                form=self.addvariantform,
                extra=0
            )

        formset = FormSet(
                queryset = VariantAnnotation.objects.filter(id__in=va_lst),
                # form_kwargs={'sample_run_obj':sample_run_obj}
            )

This displays the VariantAnnotation instances I want on my page, in a formset, but the 'id' is that of a VariantAnnotation object - NOT a VariantAnnotationSampleRun object - therefore the formset is not valid.

However I am trying to CREATE a VariantAnnotationSampleRun object from scratch - there is not VariantAnnotationSampleRun id - that is what im trying to make, but using both sample_run_id and variant_annotation_id (foreign key links to these tables)

When I include variant_annotation_id in my fields list - the form generates ALL variant_annotation_ids in a drop down.

I am very confused - can someone help me better understand how to make an model instance from a model form, and if I'm going about it in completely the wrong way

thanks

Upvotes: 0

Views: 131

Answers (1)

Diego Vinícius
Diego Vinícius

Reputation: 2223

You question is a little bit confuse... so i'll be as specific as possible here...

1 - I want to make a modelform which will CREATE a VariantAnnotationSampleRun instance

Build some views at your app and call it by AJAX, and in your views create the stance that you want and give it back to your template as ajax response... so edit the HTML if you want to show anything diferent when model is created... (like mark the checkbox)

Obs.: Its kinda weird you persist one new object in your database when user just click a simple checkbox... so they can just click it and close the page and it will dirty you database....

2 - am i correct in doing this as a VariantAnnotationSampleRun modelform

Depends in what you trying to achieve, if you think it is necessary go ahead

3 - but the 'id' is that of a VariantAnnotation object - NOT a VariantAnnotationSampleRun object - therefore the formset is not valid.

You first must hit your backend to create this objects before you be able to acess the ID... so if the form isnt valid and not saved this do not exis in your database. (doing the ajax thing i said before fix this issue for you)

4 - there is not VariantAnnotationSampleRun id - that is what im trying to make

Make your foreign keys blank=True and null=True so that way you can pass in form is valid (and will be able to save without this variantannotaiton instance) but you handle this thing with getting the previous saved data from ajax (like i said before) or just making a new one when saving form... (that way you will need to make custom input in your models to identify what the user want to do, and then creating the model from scratch and saving, so you will be able to get the id)

variant, created = VariantAnnotationSampleRun.objects.get_or_created(...) # The ... means your fields
variant.id // Acessing the id

5 - can someone help me better understand how to make an model instance from a model form

Its a pretty simple thing to do

from django.forms import ModelForm
from myapp.models import Article

# Create the form class.
class ArticleForm(ModelForm):
    class Meta:
        model = Article
        fields = ['pub_date', 'headline', 'content', 'reporter']

# Creating a form to add an article.
form = ArticleForm()

# Creating a form to change an existing article.
article = Article.objects.get(pk=1)
form = ArticleForm(instance=article)

Source: https://docs.djangoproject.com/en/2.0/topics/forms/modelforms/

Suggestion: I guess you trying to do a little crazy thing with this Variant... maybe you should just put simple select in your html, and get the ID from this option selected and do your logic when you form is valid

from django.http import Http404
def new(request):  
    if request.method == 'POST': # If the form has been submitted...
        form = ArticleForm(request.POST) # A form bound to the POST data
        if form.is_valid():
            # Here you gonna do your logic...
            # Get your variant option selected id and create your Variant instance
            # Get this new variante instance and place at your model that depends on it              
        else:
            # Do something in case if form is not valid
            raise Http404 
    else: 
        # Your code without changes

Upvotes: 1

Related Questions