Hi i have a registration form which contains username and email fields.After the registration is done,the user has an option to edit his profile which contains username,email and two other fields dob and photo(profile picture)..after clicking on the submit button all the fields are stored to the db except photo field.I checked the db the 'photo' column is empty. When i click on 'edit profile' for the second time i am getting data for all fields except photo. Can someone tell me why the photo fields is not stored to the db?
Most likely you forgot to add enctype atrribute to <form> tag. It should be like this:
<form method="POST" enctype="multipart/form-data">
...
</form>
Another possible reason is initiating of form instance without request.FILES argument. Correct form creation is:
form = MyForm(request.POST, request.FILES)
Related
I think this works, but I came across a couple of things before getting it to work that I want to understand better, so the question. It also looks like other people do this a variety of ways looking at other answers on stack overflow. What I am trying to avoid is having the user to have to select his username from the pulldown when creating a new search-profile. The search profile model is:
class Search_Profile(models.Model):
author_of_profile = models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.CASCADE,blank=True)
keyword_string = models.CharField(max_length=200)
other_stuff = models.CharField(max_length=200)
The form I ended up with was:
class Search_Profile_Form(ModelForm):
class Meta:
model = Search_Profile
fields = [ 'keyword_string', 'other_stuff']
Where I deliberately left out 'author_of_profile' so that it wouldn't be shown or need to be validated. I tried hiding it, but then the form would not save to the model because a field hadn't been entered. If I was o.k. with a pulldown I guess I could have left it in.
I didn't have any issues with the HTML while testing for completeness:
<form action="" method="POST">
{% csrf_token %}
{{ form.author_of_profile}}
{{ form.keyword_string }}
{{ form.other_stuff }}
<input type="submit" value="Save and Return to Home Page">
</form>
And the View is where I ended up treating the form and the model separated, saving the form first, then updating the model, which is where I think there might be some other way people do it.
def New_Profile(request):
if request.method=='POST':
form = Search_Profile_Form(request.POST)
if form.is_valid():
post=form.save(commit=False)
# here is where I thought I could update the author of profile field somehow with USER
# but If I include the author_of_profile field in the form it seems I can't.
post.save()
#So instead I tried to update the author_of profile directly in the model
current_profile=Search_Profile.objects.last()
current_profile.author_of_profile=request.user
current_profile.save()
return(redirect('home'))
else:
form=Search_Profile_Form()
return render(request, 'mainapp/New_Profile.html', {'form': form})
So a few questions:
For the Foreign Key in author_of_profile field, is it better to use blank=True, or null=True
I ended up using request.user rather than importing from django.contrib.auth.models import User is there any difference?
My real question though, is the above a reasonable way to get form data and update the database with that data and the user? Or am I missing some other way that is more build in?
post=form.save()
current_profile.author_of_profile=request.user
post.save()
return(redirect('home'))
try something like this. save the form to db then change the author again. save(commit=False) will not save the date to db immediately.
I'm trying to use FormModel to handle a file upload, but form.is_valid() is always returning false, and never shows any kind of error.Following is the code snippet from models.py,forms.py,views.py and my POST request.
models.py
class Pics(models.Model):
id = models.AutoField(primary_key=True,)
username = models.CharField(max_length=45)
path = models.ImageField(upload_to=img_path)
forms.py
class PicsForm(forms.ModelForm):
class Meta:
model = Pics
fields = ['username','path']
views.py
def uploads(request:HttpRequest):
form = PicsForm(request.POST,request.FILES)
if form.is_valid():
# instance = Pics(username=request.POST['username'],path=request.FILES['file'])
# instance.save()
form.save()
print('***')
else:
print('&&&&&&&&&&&&&')
return HttpResponse("succeed")
here is my postman set
I expect the output of '***', but the actual output is '&&&&&&&&&&&&&'
Be sure that your html form has 'enctype="multipart/form-data"' and your file upload input has name 'path', for example, your form should be like:
<form action="some_url" method="POST" enctype="multipart/form-data">
<input type='text' name='username'>
<input type="file" name="path">
</form>
I suspect Postman is not setting a CSRF token. Is there a reason that you are testing with Postman rather than creating an HTML form and submitting to it through your browser? I would do the latter, and if there is still a problem you could show us your template.
I'm learning Django Framework, and I have a question. To help you understand I will try and explain using the example below:
Suppose that we have some table in db as is:
CREATE TABLE names (id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, name VARCHAR(100));
And I have the form in Django Admin as is:
<form>
<textarea name="names"></textarea>
<input type="submit" name="sbt" value="Submit">
</form>
User entered something in the input names in the form and submitted it. Then a script catches this data and splits it into an array (str.split("\n")) and in cycle adding to table names!
And I many quetion:
How i can add form to Django Admin?
How i can catch form data and add this data to somethink table in database?
Thanks.
First of all you must create a django model.
Put this code in models.py.
class Names(models.Model):
name = models.CharField(max_length = 100)
Then you must create the admin model.
Put this code in admin.py.
class NamesAdmin(admin.ModelAdmin):
list_display = ['name']
# whatever you want in your admin panel like filter, search and ...
admin.site.register(Names, NamesAdmin)
I think it meet your request. And for split the names you can override save model method and split the names in there. But if you want to have an extra form, you can easily create a django model form.
Put the code somewhere like admin.py, views.py or forms.py
class NamesForm(forms.ModelForm)
class Meta:
model = Names
That's your model and form. So, if your want to add the form to django admin panel you must create a view for it in django admin. For do this create a view as common.
Put the code in your admin.py or views.py.
def spliter(req):
if req.method == 'POST':
form = NamesForm(req.POST)
if form.is_valid():
for name in form.cleaned_data['names'].split(' '):
Names(name = name).save()
return HttpResponseRedirect('') # wherever you want to redirect
return render(req, 'names.html', {'form': form})
return render(req, 'names.html', {'form': NamesForm()})
Be aware you must create the names.html and put the below code in you html page.
{% extends 'admin/base_site.html' %}
{% block content %}
<!-- /admin/names/spliter/ is your url in admin panel (you can change it whatever you want) -->
<form action="/admin/names/spliter/" method="post" >{% csrf_token %}
{{ form }}
<input type="submit" value="'Send'" >
</form>
{% endblock %}
This is your view and your can use it everywhere. But if you want only the admin have permission to see this page you must add this method too your NamesAdmin class.
def get_urls(self):
return patterns(
'',
(r'^spliter/$', self.admin_site.admin_view(spliter)) # spliter is your view
) + super(NamesAdmin, self).get_urls()
That's It. I hope this can help you.
I have a web page where users can dynamically add and delete forms, to django formsets.
I have read Dynamically adding a form to a Django formset with Ajax, based on which I can add the forms to a formset dynamically. Now I want to delete the formset dynamically. I have looked at Dynamically Delete inline formsets in Django
The way I want to do it is when user clicks on delete, I have an ajax function that deletes the form instance record from the database. When my ajax function returns I keep the same total_form_count and initial_form_count and just the hide the form html so that even the deleted record is submitted in my POST.
Initially the formset renders its form elements as:
#form0
<input id="id_formprefix-0-id" type ="hidden "value="something" name="formprefix-0-id">
<input id="id_formprefix-0-field" value="something" type="text" name="formprefix-0-field">
#form1
<input id="id_formprefix-1-id" type ="hidden "value="something" name="formprefix-1-id">
<input id="id_formprefix-1-field" value="something" type="text" name="formprefix-1-field">
#form2
<input id="id_formprefix-2-id" type ="hidden "value="something" name="formprefix-2-id">
<input id="id_formprefix-2-field" value="something" type="text" name="formprefix-2-field">
Now suppose I dynamically delete form 0, using ajax, after my record is deleted, I do not change the form counts, so the total_form_count and initial_form_count are 3.
( If i reduce the total_form_count and initial_form_count in this case to 2, when I populate the formset in my view using POST data, it is expected to be ordered as form0 and form1. But in my case the valid forms are form1 and form2)
Now in my view, I am do something like the following to save my form.
myformset = modelformset_factory(ObjectElement,form=Object_Form, extra=0, can_delete=True)
for form in myformset.forms:
print(form.instance.id) #this does not print id of deleted record, but of the first existing record in the database.
print(form.instance.attribute)# this prints the correct element, which was submitted by POST even for a deleted record.
try:
objectInstance = ObjectElement.objects.get(id = form.instance.id)
objectInstance.save()
except ObjectElement.DoesNotExist:
print("Do not save as the record has already been deleted")
When I save my formset without deleting any record the saving works ok and the correct form.instance.id is printed.
However if I delete a form instance using ajax, and then try to save my formset, the
print(form.instance.id) for the deleted record seems to print the first available id in the database, but not the id that was submitted by post. (As the record is deleted , the id is not present in the database, but should it print what was submitted to it via POST right? )
If I do it without the try/catch loop I get the following error by form.errors:
<ul class="errorlist"><li>id<ul class="errorlist"><li>Select a valid choice. That choice is not one of the available choices.</li></ul></li></ul>
which seems to indicate that it is not accepting the correct form ID form the submitted post for the deleted record.
Any body has any idea as to what I am missing here? Or a better way to do this.
How to we go about dynamically deleting forms from formsets, as it seems that the order of the forms should be sequential..
Thanks in Advance!! Any help is appreciated.
For those who stumble across this issue this could be a possible solution
I am able to dynamically delete my form from formset as follows.
So the initial form html looks like
#form0
<input id="id_formprefix-0-id" type ="hidden "value="something" name="formprefix-0-id">
<input id="id_formprefix-0-field" value="something" type="text" name="formprefix-0-field">
#form1
<input id="id_formprefix-1-id" type ="hidden "value="something" name="formprefix-1-id">
<input id="id_formprefix-1-field" value="something" type="text" name="formprefix-1-field">
#form2
<input id="id_formprefix-2-id" type ="hidden "value="something" name="formprefix-2-id">
<input id="id_formprefix-2-field" value="something" type="text" name="formprefix-2-field">
Now suppose I delete form0 and form1 records from my database using ajax.
When I submit the form, the formset will not validate, because it expects the forms to be in order, and I only have form 2 remaining in the data base ( I deleted the top two). Formset errors with "Select a valid choice" as described in the question.
So after I delete the forms dynamically, when my ajax returns, I do not change the total_form_count,(https://docs.djangoproject.com/en/1.4/topics/forms/formsets/#understanding-the-managementform) but mark the form as deleted in my html, and just hide the form. Now when the formset is submitted using POST, it also submits the deleted form, but marked as deleted (https://docs.djangoproject.com/en/1.4/topics/forms/formsets/#can-delete)
Now in the view, I first filter out the forms that have been deleted, and only process the forms that still remain as follows
marked_for_delete = formset.deleted_forms
for form in formset.forms:
#Filtering out the deleted records, as the formset will not validate, for deleted records
# if we use form.instance.id or form.initial['id'] below it does not work.
#for some reason it returns the id of the first available record in the data base.
#form['id'].value(), gives us the id of the deleted element we are looking for
if form['id'].value() not in [deleted_record['id'].value() for deleted_record in marked_for_delete]:
if form.is_valid():
pass
# save the form
else:
pass
# error message
I have a page which displays a form that a logged-in user can use to edit their profile.
The first time the user loads the corresponding view, with a GET request, the form should display the values of the users existing profile record.
Because I'd like to have granular control over the markup used for the form fields, I'd like to retrieve the field values only, and manually write the necessary input element markup inserting the retrieved field values as the input elements' 'value' attribute (rather than have django render the entire input elements).
So far I've been trying to use directives like {{ form.myfield.data }} in my template to access the field data, but this is returning "None", instead of the profile details as i expected.
If the user has just posted a valid form though, the form fields do contain the expected profile details.
I hope someone can help me understand what i'm doing wrong here:
Here's my view:
#login_required
def edit(request):
# get logged-in user's profile
obj=Profile.objects.get(user=request.user)
if request.method == 'POST': # If the form has been submitted...
form = ProfileForm(request.POST, request.FILES, instance=obj)
if form.is_valid(): # All validation rules pass
form.save()
request.flash['success'] = "Your profile has been updated." # Puts a string to the flash scope
else:
request.flash['error'] = 'Please correct the problems below and try again' # Puts a string to the flash scope
else:
# if no form was submitted
# derive the form data from the logged-in users existing profile
form = ProfileForm(instance=obj)
return render_to_response('app_profile/edit.html',
{
'form': form,
'user': request.user,
'ancestor_urls': ['app_profile.views.edit',],
},context_instance=RequestContext(request)
)
And here's an excerpt from the corresponding template. This input element deals with a field called 'display_name'.
<input type="text"
class="textInput large {% if form.display_name.errors %}error{% endif %}"
maxlength="50"
size="35"
value="{{ form.display_name.data }}"
id="id_display_name"
name="display_name">
The way to do what you want to do is to write custom form widgets, instead of doing that in the template.
You can either create an entirely custom widget, or you can just add/change the attributes on the form level when you init the ModelForm
I guess you can solve some of your problems without making a custom widget using the widgets attrs argument: http://docs.djangoproject.com/en/dev/ref/forms/widgets/#django.forms.Widget.attrs, also you have some styling options using the input's id!