1

I have a form that works perfectly fine
models.py:

class Location(models.Model):
    title = models.CharField(max_length=300)
    description = models.TextField(null=True, blank=True)
    address = models.TextField(null=True, blank=True)

class Review (models.Model):
    location = models.ForeignKey(Location)
    description = models.TextField(null=True, blank=True) 

views.py:

class Create(CreateView):
  model = coremodels.Review
  template_name = 'location/test.html'
  fields = '__all__'
  def form_valid(self, form):
    form.save()
    return HttpResponseRedirect('')

    return super(Create, self).form_valid(form)

html:

<form action="" method="post">{% csrf_token %}
    {{ form}} 
    <input type="submit" value="Create" />
</form>

When I open the site I can select a location and give a review over the create button. However, now I am dependent on the prefilled values in the Location class. What if I want that a user can directly create a description as well as a title of the location (I don't want the title to be in class Review) I already tried looking for this in the docs but couldn't find anything. Somewhere I read that I could create two different forms that handle to different things but I'm not sure how to merge that all in the class Create. Is there something like model = coremodels.Review & coremodels.Location and then in the html I could do

{{form.title}}
{{form.description}}  

Anyone any ideas or search terms I could look for?

Thanks !

EDIT Ok thanks to Ruddra and this post , here is the working solution. I had to edit it a little in order to get it working for me,

class SomeForm(forms.ModelForm):

   def __init__(self, *args, **kwargs):
      super(SomeForm, self).__init__(*args, **kwargs)
      self.fields['title'] = forms.CharField(label='Title', required = False)
      self.fields['description'] = forms.CharField(label='Description', required = False)
      self.fields['location'] = forms.ModelChoiceField(queryset= Location.objects.all(), required = False) # This line is for making location not required in form field for input

   class Meta:
        model = Review
        fields = '__all__'


   def save(self, commit=True):
       """
       It will save location from choice field or inputs of title and description
       """
       instance = super(SomeForm, self).save(commit=False)
       if instance.location_id:
           instance.save()
       else:
           new_location = Location.objects.create(title=self.cleaned_data['title'])
           instance.location = new_location
           instance.save()
      return instance

and the views.py

class Create(CreateView):
  model = coremodels.Review
  template_name = 'location/test.html'
  form_class = SomeForm
Community
  • 1
  • 1
Tom
  • 2,545
  • 5
  • 31
  • 71

1 Answers1

1

Unfortunately you can't use two models like this, you have to write a form and do the stuffs there. For example:

class SomeForm(forms.ModelForm):

   def __init__(self, *args, **kwargs):
      super().__init__(*args, **kwargs)
      self.fields['title'] = forms.CharField(label='Title', required = False)
      self.fields['description'] = forms.CharField(label='Description', required = False)
      self.fields['location'] = forms.ModelChoiceField(queryset= Location.objects.all(), required = False) # This line is for making location not required in form field for input

   class Meta:
        model = Review
        fields = '__all__'


   def save(self, commit=True):
       """
       It will save location from choice field or inputs of title and description
       """
       instance = super().save(commit=False)
       if instance.location:
           instance.save()
       else:
           new_location = Location.objects.create(title=self.cleaned_data['title'], description = self.cleaned_data['description']])
           instance.location = new_location
           instance.save()
      return instance

Use it in view:

class Create(CreateView):
  model = coremodels.Review
  template_name = 'location/test.html'
  form = SomeForm

And you have make sure that, location is nullable or not required in form (I have added that to the example)

ruddra
  • 50,746
  • 7
  • 78
  • 101
  • ok, so this gives me a form where you can select a title from a location and then add a description but it doesn't allow me to put in a new title of a location. Oh and also, putting in the location is required, so even if i leave it blank it won't submit the form – Tom Aug 14 '15 at 16:00
  • putting location is required will not let you put location blank, that is why you need to set it not required. And I wrote the code like this that, either user can choose a location or they can fill title and description which will be treated as new location. If I got the concept wrong, plz correct me – ruddra Aug 15 '15 at 06:20
  • no, no, the code works, however I don't have the option to fill in a new title. That's exactly what I want, that the user fills in title and description by himself and doesn't choose. So right now I don't have an input field for adding a new location – Tom Aug 15 '15 at 07:31
  • Um, I have tested the code and I got title, description fields in form rendered in html. Try using `{{ form.as_p }}` to render the form in html, or `{{form.title}}` `{{form.description}}` In template – ruddra Aug 15 '15 at 13:37
  • I did, I tried everything, but I think I know why, if I use your code it says "Using ModelFormMixin (base class of CreateTest) without the 'fields' attribute is prohibited." Did I miss something in the views? (Thanks btw, this brings me a lot closer!) – Tom Aug 16 '15 at 23:41
  • So in your code you can create a new title for a location and then add a new description for that location instead of just selecting a previously created location? – Tom Aug 17 '15 at 01:19
  • yes, you can either input title description or select a location. – ruddra Aug 17 '15 at 04:56
  • ok, doesn't work for me, is that all for the views or is there something missing ? Thanks again ! – Tom Aug 17 '15 at 06:10
  • ok, I know what it doesn't work. So I edited my code in the question, I'm not using pyhton3 which is why i have to run stuff a little differently. But the save method still doesn't work – Tom Aug 17 '15 at 18:08
  • Ok I got it to work, I had to edit it a little but now it's working ! Thank you so much ! – Tom Aug 17 '15 at 23:13
  • One more question, what do I do if I want to put in a second description field so you can add multiple descriptions at the same time? I tried copying the same line but didn't work – Tom Aug 21 '15 at 05:58
  • U can put two description fields with different names, but saving them to one single model field(db column) will be an issue, you have to append the inputs of both input fields and save it into single db column. – ruddra Aug 21 '15 at 16:04
  • how do I do that? with formsets? – Tom Aug 21 '15 at 16:05
  • No, coz formsets are useful for M2M relations, for example, if a review has multiple locations. But here I see one review has one location, so you can either add fields following the example code (i.e description_1, description_2) and save the inputs combined or change the relation in between review and location & use formsets. – ruddra Aug 21 '15 at 16:17
  • ahhh, I see what you are saying, you are a genius, thanks! – Tom Aug 21 '15 at 18:25