3

I'm trying to build a profile page, where a User can fill in the Teacher model.

My Teacher model, model.py

class Teacher(models.Model):
    user = models.OneToOneField(User, on_delete=models.PROTECT, related_name='Teacher')
    rate = models.CharField(max_length=200)
    availability = models.BooleanField(default=False)

forms.py

class TeacherCreate(CreateView):
    user_id = request.user.id #INCORRECT! Needs something to remember current user id.
    model = Teacher
    fields = ['rate','availability']

EDIT: I've also attempted adding:

def form_valid(self, form):
    form.instance.user = self.request.user
    return super(TeacherCreate, self).form_valid(form)

as suggested here.

We don't allow the user to change his ID in this create view. In fact, I believe this should be the current users id, user_id which is given by request.user.id.

teacher_form.html

    <form action="" method="post" enctype="multipart/form-data">
{% csrf_token %}
    {% for field in form %}
<div class="form-group">
    <span color="red">{{ field.errors }}</span>
    <label>
        {{ field.label_tag }}
    </label>
    <div>{{ field }}</div>
</div>
{%  endfor %}
     <button type="submit">Submit</button>
    </form>

Now the problem is that when I run it, I get the error:

NOT NULL constraint failed: users_teacher.user_id

which I believe is because I didn't specify the user_id.

How I'd like it to work:

First, check if the teacher already has a record in the database. E.G. if there is a row in the Teacher table, with user_id=current user.

If the teacher has a profile -> Call the update view.

If the teacher doesn't have a profile -> Use create view.

Roma
  • 449
  • 6
  • 23

1 Answers1

2

Try add LoginRequiredMixin to your view, if i understand, simple create or update view:

from django.contrib.auth.mixins import LoginRequiredMixin
from django.http import HttpResponseRedirect
from django.views.generic import CreateView


class TeacherCreate(LoginRequiredMixin, CreateView):
    model = Teacher
    fields = ['rate','availability']

    def get_success_url(self):
        # replace url name 'users' on your if need
        return reverse('users',args=(self.request.user.id,))

    def form_valid(self, form):
        user = self.request.user
        instance, _ = Teacher.objects.get_or_create(user=user)
        instance.rate = form.cleaned_data.get("rate", "")
        instance.availability = form.cleaned_data.get("availability", "")
        instance.save()
        # modify return
        return HttpResponseRedirect(self.get_success_url())
Brown Bear
  • 19,655
  • 10
  • 58
  • 76
  • I get the error: UNIQUE constraint failed: users_teacher.user_id when I click save button – Roma Aug 19 '17 at 17:16
  • may be you try add, profile with exists `Teacher.user`, if it is test db, try `Teacher.objects.all().delete()` – Brown Bear Aug 19 '17 at 17:39
  • I see, this infant does create a new row. Which leads me to the final part. How to have the same page in the browser, to be smart and decide whether it has to do a Update view or a Create View – Roma Aug 19 '17 at 18:00
  • I tried the above, but it seems to be redirecting me to /users/teacherprofile/None where None is not a valid URL. – Roma Aug 23 '17 at 12:34
  • /users/ is what I would like the redirect to be. I tried eturn HttpResponseRedirect('/users/%s/' % instance.id) but this also didn't work – Roma Aug 23 '17 at 12:35
  • add to the view `def get_success_url` as in example i adde to the answer – Brown Bear Aug 23 '17 at 12:44
  • Thank you, but it didn't work. Even if I put a static URL in HttpRepsonse, it always redirects me to teacherupdate/None after form submit. Maybe it's browser cache or something. As a note, it updates/creates correctly. Just doesn't redirect correctly. (I did add reverse to import) – Roma Aug 23 '17 at 13:06
  • sorry, but a fogot to edit `return HttpResponseRedirect(self.get_success_url())` try it now – Brown Bear Aug 23 '17 at 13:16
  • Interesting... After I edit the form and submit, now it says ''NoneType' object is not callable on the URL: /users/teacherprofile/ , but when I simply reload the same URL in the browser, it loads the form to edit. – Roma Aug 23 '17 at 13:21
  • i'm stupid), here simple solution use `self.request.user.id` instead of `self.object.id`, try it – Brown Bear Aug 23 '17 at 13:27
  • 1
    Thanks, but the issue remains. I think I will try to come up with something by mixing different solutions posted here. – Roma Aug 23 '17 at 17:15