0

I am trying to have a user input a task from the frontend and have that data instantiate a new model and add this new field in the database associated with their account. I have tried the following;

Profile HTML

<form id="taskitem_form" method="post" action="/">
    {% csrf_token %}
    {% for hidden in form.hidden_fields %}
        {{ hidden }}
    {% endfor %}

    {% for field in form.visible_fields %}
        {{ field.errors }}
        {{ field.help_text }}
        {{ field }}
    {% endfor %}

    <input type="submit" name="submit" value="Add Task" class ="btn btn-primary" />
</form>

Model

class TaskItem(models.Model):
    taskn = models.CharField(max_length = 400)
    usern = models.ForeignKey(User)

    def __str__(self):
        return self.taskn

Views

  def add_task(request):
        # Get the context from the request.
        #context = RequestContext(request)

    # A HTTP POST?
    if request.method == 'POST':
        form = TaskItemForm(request.POST)

        # Have we been provided with a valid form?
        if form.is_valid():
            task = form.save(commit=False)
            task.usern = request.user
            task.save()
    # we should redirect after data modifying
            return redirect('/user/%s' %(request.user))
        else:
            # If the request was not a POST, display the form to enter details.
            return render(request, 'profile.html', {'form': form})

    # Bad form (or form details), no form supplied...
    # Render the form with error messages (if any).
    return render(request, 'profile.html', {'form': form})

Forms

from django import forms
from bkmks.models import TaskItem

class TaskItemForm(forms.ModelForm):
    taskn = forms.CharField(max_length = 300, help_text = "Please enter your task")

    # An inline class to provide additional information on the form.
    class Meta:
        fields = ('taskn', 'usern' )
        #This is the association between the model and the model form
        model = TaskItem
5
  • TaskItemForm shows only taskn in the fields parameter. What about the usern field? You should set it yourself in the form validation. Commented May 17, 2015 at 22:04
  • You haven't stated what the problem is. One obvious issue, which is nothing to do with forms, is that you haven't specified the template in your render_to_response calls (it should be the first parameter, for some reason you have a / there instead). Commented May 17, 2015 at 22:05
  • There isn't a text box visible on my html page whatsoever. The goal of adding '/' was for no redirect to happen or redirect to the main page. I was more just testing this to see if the data could be entered and shown up in the database. Commented May 17, 2015 at 22:07
  • Redirect and render are completely different things. The code as you have posted it would produce an error because the first param must be a template name. Please post the actual code. Commented May 17, 2015 at 22:18
  • return render_to_response("profile.html", {'form': form, }, context_instance = RequestContext(request)) would that work? Commented May 17, 2015 at 22:19

5 Answers 5

1

Lot's of Changes needed to your code.

I'm posting a working version so that you can try.

Put profile.html file as bkmks/templates/bkmks/profile.html

Get it working. Customize later.

profile.html

<form id="taskitem_form" method="post" action="">

    {% csrf_token %}
    {{form}}

    <input type="submit" name="submit" value="Add Task" class ="btn btn-primary" />
</form>

model as it is.

views.py

from django.contrib.auth.decorators import login_required
from django.shortcuts import render_to_response, RequestContext, redirect
from .forms import TaskItemForm

@login_required
def add_task(request):
    # Get the context from the request.
    context = RequestContext(request)

    # A HTTP POST?
    if request.method == 'POST':
        form = TaskItemForm(request.POST)

        # Have we been provided with a valid form?
        if form.is_valid():
            # Save the new category to the database.
            task = form.save(commit=False)
            task.usern = request.user
            task.save()


            # Redirect to home (/)
            return redirect('/')
        else:
            # The supplied form contained errors - just print them to the terminal.
            print form.errors
    else:
        # If the request was not a POST, display the form to enter details.
        form = TaskItemForm()

    # Bad form (or form details), no form supplied...
    # Render the form with error messages (if any).
    return render_to_response('bkmks/profile.html', {'form': form}, context)

forms.py

class TaskItemForm(forms.ModelForm):
    # task is changed to taskn
    taskn = forms.CharField(max_length = 300, help_text = "Please enter your task")

    # An inline class to provide additional information on the form.
    class Meta:
        fields = ('taskn',)
        #This is the association between the model and the model form
        model = TaskItem

If you get any error or data is not getting saved post here.

Going through Django tutorial will be an wise decision.

Sign up to request clarification or add additional context in comments.

11 Comments

No errors, but the form isn't showing on the html page.
Check update. Missed from .forms import TaskItemForm earlier.
Same issue still unfortunately
What's your profile.html path/location and Template settings in settings.py?
os.path.join(BASE_DIR, 'templates') for the template directory. Directly inside of that exists profile.html which I have changed to just profile.html in your code that you provided.
|
1

The below should do what you need. You really want to inherit 100% of everything from your model when you can. This insures all model validation trickles down to the form. I utilized verbose_name and help_text on the model to achieve this.

Models

from django.conf import settings

class TaskItem(models.Model):
    taskn = models.CharField(
        max_length=400,
        verbose_name="task",
        help_text="Please enter your task.",
    )
    usern = models.ForeignKey(
        to=settings.AUTH_USER_MODEL, 
        related_name="tasks",
    )

    def __str__(self):
        return self.taskn

For the forms, I have added a forms.HiddenInput widget to the user, assuming you want the user submitting the task to become the user.

Forms

from django import forms
from bkmks.models import TaskItem

class TaskItemForm(forms.ModelForm):
    widgets = {
        'user': forms.HiddenInput,
    }

    class Meta:
        model = TaskItem
        fields = ('taskn', 'usern')

I have used a CreateView to reduce code complexity, and overrode the form_valid to add the user instance to the form.

Views

from django.views.generic import CreateView
from bkmks.models import TaskItem
from bkmks.forms import TaskItemForm

class TaskCreateView(CreateView):
    model = TaskItem
    form_class = TaskItemForm
    template_name = "path/to/template.html"

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

Finally, in the template, we simply want to use {{ form }}. I see you are looking into bootstrap. I'll suggest django-crispy-forms for this, but that is beyond the scope of your question.

Template

<form id="taskitem_form" method="post" action="/">
    {% csrf_token %}
    {{ form }}
    <input type="submit" name="submit" value="Add Task" class ="btn btn-primary" />
</form>

2 Comments

Thanks for this! Getting an error: 'User' object has no attribute 'taskitem_set'
Did you add related_name="tasks" to the usern ForeignKey in the TaskItem model?
0

https://docs.djangoproject.com/en/1.8/topics/http/shortcuts/#render-to-response

render_to_response expects a template as the first argument, not a url.

I think in your second call to render_to_response should include the template name / path , while the first one should use a return HttpResponseRedirect("/") instead, though its not clear exactly what your problem is.

Comments

0

Add this line to imports in views.py

from django.contrib.auth.decorators import login_required

Decorate add_task view

@login_required
def add_task(request):

Then, edit part of your code

if form.is_valid():
    task = form.save(commit=False)
    task.usern = request.user
    task.save()
    # we should redirect after data modifying
    return redirect('/')
else:
    # etc.

Some notes. You may replace render_to_response to render.

Remove this line

context = RequestContext(request)

Replace

# Wrong usage, actually.
# Should be something like
# render_to_response(template_name, context, context_instance)
render_to_respone('/', {'form': form}, context)

with

# if template_name is "profile.html"
render(request, 'profile.html', {'form': form})

1 Comment

I have made the changes, but form is still not showing for some reason.
0

Why define a field called task in the form if you've already got a field in the model called taskn, wouldn't it be better to just use that? And like the guys have said, you need to specify a template to render (that's why you're not seeing anything).

It'd also be a good idea to pass the current user to the form's user field.

@login_required
def add_task(request):
    # Get the context from the request.
    context = {}

    # A HTTP POST?
    if request.method == 'POST':
        form = TaskItemForm(request.POST)

        # Have we been provided with a valid form?
        if form.is_valid():
            # Save the new category to the database.
            form.save()

            # Now call the index() view.
            # The user will be shown the homepage.
            return render_to_response(
                'profile.html',
                {'form': form},
                RequestContext(request, context)
            )
        else:
            # The supplied form contained errors - just print them to the terminal.
            print form.errors
    else:
        # If the request was not a POST, display the form to enter details.
        form = TaskItemForm(initial={'usern': request.user})

    # Bad form (or form details), no form supplied...
    # Render the form with error messages (if any).
    return render_to_response(
        'profile.html',
        {'form': form},
        RequestContext(
            request, context
        )
    )

Form;

from django import forms
from bkmks.models import TaskItem

class TaskItemForm(forms.ModelForm):
    taskn = forms.CharField(max_length = 300, help_text = "Please enter your task")

    # An inline class to provide additional information on the form.
    class Meta:
        fields = ('taskn', 'usern' )
        #This is the association between the model and the model form
        model = TaskItem

4 Comments

Appreciate your suggestions. I have made the change, but still not seeing any visible from on my page. How should I call it in my profile template?
Oh hang on, the rest of your render_to_response is wrong. You need to pass the form in the context. Check the docs link that @wobbily_col has posted & I'll edit this.
@ryan yeah you need to pass the template as the first arg and then request is passed to RequestContext() along with your context dictionary. Take a look at my edit.
i've literally copied your code into mine, but still can't get this textbox field to show up on the page.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.