I have two models in my Django application, for the purposes of storing search parameters used for some homology search programs:
# models.py
class Search(models.Model):
"""A class to represent search runs."""
program = models.CharField(max_length=20)
results_file = models.FileField(
upload_to=(SEARCH_RESULTS_DIR)
)
timestamp = models.DateTimeField()
def __unicode__(self):
return u'%s %s' % (self.program, self.timestamp)
class FastaRun(models.Model):
search = models.OneToOneField('Search', primary_key=True)
# the user-input FASTA formatted protein sequence
query_seq = models.TextField()
# -b "Number of sequence scores to be shown on output."
number_sequences = models.PositiveIntegerField(blank=True)
# -E "Limit the number of scores and alignments shown based on the
# expected number of scores." Overrides the expectation value.
highest_e_value = models.FloatField(default=10.0,
blank=True)
# -F "Limit the number of scores and alignments shown based on the
# expected number of scores." Sets the highest E-value shown.
lowest_e_value = models.FloatField(blank=True)
mfoptions = [
('P250', 'PAM250'),
('P120', 'PAM120'),
('BL50', 'BLOSUM50'),
('BL62', 'BLOSUM62'),
('BL80', 'BLOSUM80')
]
matrix_file = models.CharField(
max_length=4,
choices=mfoptions,
default='BL50'
)
database_option = models.CharField(
max_length=25,
choices=BLAST_DBS,
default=INITIAL_DB_CHOICE
)
ktupoptions = [(1, 1), (2, 2)]
ktup = models.PositiveIntegerField(
choices=ktupoptions,
default=2,
blank=True
)
Note here that FastaRun
is a kind of Search
. FastaRun
extends search in that there are more parameters defined for a FastaRun
. A FastaRun
must have a Search
instance to which it is linked, and this Search
instance is the primary key of FastaRun
.
I have a ModelForm
for the FastaRun
class.
# views.py
class FastaForm(forms.ModelForm):
class Meta:
model = models.FastaRun
I have a view function which I need to use to populate a FastaForm
and save a new Search
instance and a new FastaRun
instance based on the user submitted form. The form does not include the option to choose a Search
instance. This is impossible to do because the Search
instance can only exist once the user actually submits this search.
Below is an outline of what the function needs to do:
# also in views.py
def fasta(request, ...):
# populate a FastaForm from the information POSTed by the user--but
# how to do this when there's no Search information coming in from
# the user's request. We need to create that Search instance, too,
# but we also have to...
# validate the FastaForm
# ... before we can ...
# create a Search instance and save() it
# use this saved Search instance and give it to the FastaForm [how?]
# save() the FastaForm [save the world]
pass
Because the Search
and FastaRun
(and therefore FastaForm
) are
intertwined, I feel like I'm getting into a Catch-22. I need to
save a Search
instance, whose parameters are stored in the POST
request, but whose parameters must be validated using the FastaForm
's
validation. However, I think the FastaForm
can't be instantiated until
I have instantiated a Search
instance. Yet, I can't instantiate a
Search
instance until I've validate using the FastaForm
... You get
the idea.
What am I missing here? There must be a fairly clean way to do this, but I lack the clarity to see it.
Also, correct me if I'm wrong, but this same dependency situation could occur any time you have some sort of relationship between models (e.g., also for ForeignKey
and ManyToMany
fields). Thus, someone's surely figured this out.