0

I modified my code to use forms.ModelForm so that I can modify the width of the forms for the webpage. The problem I have now is that ForeignKeys is not available for forms.Form and I need to save the active user in the form, as well as the current time when the request is submitted.

Below are my files (I excluded all necessary imports) with the current workaround, and it gives me the following error: table chemrun_chemrun has no column named owner_id. I am happy for any help to solve this :)

from models.py

class ChemRun(models.Model):
    owner           =       models.ForeignKey('auth.User')

from forms.py

class ChemRunForm(forms.ModelForm):
    title           =       forms.CharField(max_length=50)
    status          =       forms.CharField(max_length=20, initial="In queue")
    created_date    =       forms.DateTimeField(initial=timezone.now, required=False)

    def __unicode__(self):
            return self.title

    class Meta:
            model   =       ChemRun
            exclude =       {'created_date', 'status', 'owner'}

from views.py

@verified_email_required
def create(request):
    if request.POST:
            form = ChemRunForm(request.POST)
            if form.is_valid():
                    m = form.save(commit=False)
                    m.created_date  =       timezone.now
                    m.owner         =       request.user
                    m.save()
                    return HttpResponseRedirect('/accounts/profile')
    else:
            form = ChemRunForm()

    args = {}
    args.update(csrf(request))
    args['form'] = form

    return render_to_response('interface/newrun.html', args, context_instance=RequestContext(request))

from urls.py

urlpatterns = [
    url(r'^create/$', 'chemrun.views.create', name='create'),
]
Frank
  • 619
  • 1
  • 6
  • 26
  • "I modified my code to use forms.Form so that I can modify the width of the forms" - does not follow at all. You can modify the width of fields for a ModelForm in exactly the same way. – Daniel Roseman Sep 08 '15 at 12:07
  • My mistake, I meant to write that I modified it to use `forms.ModelForm` – Frank Sep 08 '15 at 12:13
  • This seems to have nothing to do with forms though. The error message says there is a missing column; this means you have not created and run migrations. – Daniel Roseman Sep 08 '15 at 12:20
  • Ok, I tried a makemigrations call and I get the following message `You are trying to add a non-nullable field 'owner' to chemrun without a default; we can't do that (the database needs something to populate existing rows).` Before I made these changes, I had no problems with adding the current user into my form using the same command as I have now: `owner = models.ForeignKey('auth.User')`. In particular, I didn't need to add a default value for assigning the owner value, but now I need to for some reason. – Frank Sep 08 '15 at 13:23
  • No, that's not possible. Before you ran migrations, you would *simply not be able to add the user to the object*, because you had no foreign key. And that error message is telling you you need to supply a one-off default for the *existing* objects, not any new ones. – Daniel Roseman Sep 08 '15 at 13:24
  • About a bit of struggle I managed to fix it by clearing the migrations. The page runs now, but when I press submit for the form I see that data goes into it but it doesn't appear save it. When I go to the `admin` page, all the `chemrun` objects are empty. Is the reason that the form is not saved to the database, or that it is not reachable? – Frank Sep 08 '15 at 15:39

2 Answers2

1

I see two practical solutions to your problem:

  1. Since the field 'owner' is new to the model, you will have to add a default id in the migration to put that in the column to the already existent data.
  2. You could set 'blank=null' in the 'owner' field, in that way django it will not force the data in that column.

You said in the comments that before the command 'makemigrations' didn't ask you for anything and now it does, this is because now you have records in that table and if you add a new column, neither django or postgres know what to put in that column in the old records, perhaps you could 'flush' your database? Of course, only if it is a dev database.

diegueus9
  • 29,351
  • 16
  • 62
  • 74
  • Thank you, I had just tested this and after removing the database and all previous migrations, the page runs. The only remaining problem now is that the data collected by the form is not saved into the database, or else the database is not anymore able to be accessed. – Frank Sep 08 '15 at 15:45
  • did you run makemigrations again after you remove the data in the database? – diegueus9 Sep 08 '15 at 15:48
  • Yes, I have created a superuser to access the admin pages, and a normal user to run the script to create the form. `manage.py makemigrations` gives me `No changes detected` – Frank Sep 08 '15 at 15:54
  • did you run migrate after makemigrations? – diegueus9 Sep 08 '15 at 15:57
  • Yes, and I also ran collectstatic just in case. Nothing – Frank Sep 08 '15 at 16:00
  • How did you removed the database? when you use the form you lost all the fields or only the owner? – diegueus9 Sep 08 '15 at 16:04
  • I deleted the old sqlite3 database file, and also all files under `chemrun/migrations/`. Then I ran makemigrations and migrate, created a superuser and then a normal user. The user are there in the admin page...the chemrun objects that I create when I submit are there, but they contain none of the data from the forms. They are empty objects... – Frank Sep 08 '15 at 16:07
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/89087/discussion-between-diegueus9-and-tobias). – diegueus9 Sep 08 '15 at 16:14
0

After some more reading and experimenting I found some additional points to add for future readers of the question.

The first part of the error was caused by not being able to run successfully the commands makemigrations and subsequently migrate. By error I had removed __init__.py from the migrations directory. After restoring the file and rerun the commands, that part was corrected. For the future, I can recommend the following script to clean/reset migrations (taken from one of the answers to this question).

#!/bin/sh
echo "Starting ..."

echo ">> Deleting old migrations"
find . -path "*/migrations/*.py" -not -name "__init__.py" -delete

# Optional
echo ">> Deleting database"
find . -name "db.sqlite3" -delete

echo ">> Running manage.py makemigrations"
python manage.py makemigrations

echo ">> Running manage.py migrate"
python manage.py migrate

echo ">> Done"

The second part was to be able to adjust width of the fields. I have my fields defined in models.py, but by adding a widget call to the Meta class of the equivalent form class in forms.py I had power to adjust this, and more. Here is my forms.py:

class ChemRunForm(forms.ModelForm):
    class Meta:
        model = ChemRun
        widgets =       {'title': forms.TextInput(attrs={'style':'width: 500px;'})}
        exclude = ('owner')

NB: ChemRun is the models class, ChemRunForm is the forms class. title and owner are two of the fields for my model.

Hope this will help people in the future

Community
  • 1
  • 1
Frank
  • 619
  • 1
  • 6
  • 26