I need two of the three form fields to be filled in automatically before submitting to the database. Slug is supposed to be filled based on test_name, and user have to be filled based on data about the current user.
Now I can submit the form, but the database entry will not be created.
models.py
class Test(models.Model):
test_name = models.CharField(max_length=100, db_index=True, verbose_name='Test name')
slug = models.SlugField(max_length=100, unique=True, verbose_name='URL')
author = models.ForeignKey(User, db_column="user", on_delete=models.PROTECT)
forms.py
class AddTestForm(forms.ModelForm):
class Meta:
model = Test
fields = ['test_name', 'slug', 'author']
views.py
def ask_test_name(request):
form = AddTestForm(request.POST)
if form.is_valid():
test = form.save(False)
test.slug = slugify(test.test_name)
test.author = request.user
test.save()
return render(request, 'app/ask_test_name.html', {'form': form})
ask_test_name.html
<form action="{% url 'ask_test_name' %}" method="post">
{% csrf_token %}
<p><input type="text" name="test_name" required></p>
<p><input type="hidden" name="slug"></p>
<p><input type="hidden" name="author"></p>
<p><button type="submit">Create</button></p>
</form>
Updated
It seems to me the problem is that the html does not see what model I want to use, but I don't know how to solve it here, I need two fields to be hidden
Remove slug and author from the fields in forms.py and don't include them in your HTML form. That should do the trick. You're only hitting the DB after already assigning values to slug and author, so that shouldn't throw an error.
Related
I have two object models, NewsObject and StockObject. The stock object is a foreign key in the news object.
class stockObject(models.Model):
stock_name = CharField(max_length=100, blank=True, null=True)
stock_tag = CharField(max_length=100, blank=True, null=True)
def __str__(self):
return self.stock_name
class newsObject(models.Model):
title = CharField(max_length=100, blank=True, null=True)
body = TextField(blank=True, null=True)
stock = ForeignKey(stockObject, on_delete=models.SET_NULL, blank=True, null=True)
I have used autocomplete_fields property in the ModelAdmin class as I want a searchable dropdown for stocks in news. I have also added search_fields in the stocks ModelAdmin as mentioned in the documentation.
This is what my admin.py looks like:
class stockAdmin(admin.ModelAdmin):
list_display = ['stock_name', 'stock_tag']
search_fields = ['stock_name']
class newsAdmin(admin.ModelAdmin):
list_display = ['title', 'body', 'stock']
search_fields = ['title', 'body', 'stock']
autocomplete_fields = ['stock']
Now, the issue is that I get a searchable dropdown on the Django Admin site for this field, but it is only a dropdown (not searchable) on the actual template screen. I have a basic view which calls the template, like so:
Views.py
def createNews(request):
form = NewsForm()
if request.method == 'POST':
form = NewsForm(request.POST)
if form.is_valid():
form.save()
return redirect('/backoffice/')
context = {'form' : form}
return render(request, 'NewsForm.html', context)
And NewsForm.html is:
{% extends "base.html" %}
{% load static %}
{% block content %}
<form action="" method="POST">
{% csrf_token %}
{{ form }}
<input type="submit" name="Submit">
</form>
{% endblock %}
I've been wondering what might be the cause of this behavior. Tried multiple things but none of them work. What might I be missing here?
Django Admin site image
Django Template Image
I think you have written all your models in camelCase so first changed them to PascalCase.
Second, you have missed models in all your models:
Write them like this add models before every datatype like:
from django.db import models
class Musician(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
instrument = models.CharField(max_length=100)
Not only datatype of fields.
So im trying to make this page where i add new category which only has name. But when i try it, i just get a "non-string type" as the name. So it works i guess just doesn't take whatever i give it in my input in html.
HTML:
<input type="text" class="form-control" placeholder="Name" id = "category-create-name" name=
"category_name">
<input type="submit" class="login-button" value="Post">
Model:
class Category(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
name = models.CharField(max_length=255, blank=True, null=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
Form:
class CategoryCreateForm(forms.ModelForm):
class Meta:
model = Category
fields = ('name',)
widgets = {
'category_name': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Name', 'id':'category-create-name'}),
}
View:
class CategoryCreateView(CreateView):
form_class = CategoryCreateForm
template_name = 'product/new_category.html'
success_url = '/dashboard/'
There are a couple of things I see here. First in your form. In the widgets attribute of class Meta, the keys in that dictionary need to be a field name that is in your fields attribute. In other words you need to change 'category_name' to 'name'. Second, in your template that is used for the view. You seem to be manually defining a separate input field rather than the one that your view and form are expecting. You should just define the form in your template like this:
<form method="POST">
{% csrf_token %}
{{ form_as_p }}
<input type="submit" class="login-button" value="Post">
</form>
In the template {{ form.as_p }} will take the form that you gave to your view, and automatically create it in the html when it is being rendered to the page.
I have a view which renders 2 forms to a template, but only one renders, the other doesnt display and it doesnt give me any error, but I can see that the form display when I print it in my console.
This is my model for the form not showing
class Organization(models.Model):
name = models.CharField(max_length=255, null=True)
This is the model for the admin, Im inheriting from AbstractUSer
class User(AbstractUser):
is_user = models.BooleanField(default=False)
is_admin = models.BooleanField(default=False)
This is the form for the model
class OrganizationForm(forms.ModelForm):
name = forms.CharField(max_length=255)
class Meta:
model = Organization
fields = ['name']
This is the form for the Admin
class AdminSignUpForm(UserCreationForm):
class Meta(UserCreationForm.Meta):
model = User
fields = ['username','email']
def save(self, commit=True):
user = super().save(commit=False)
user.is_admin = True
if commit:
user.save()
return user
This is the view which I am calling the multiple forms
def signup(request):
if request.method == 'POST':
adminForm = AdminSignUpForm(request.POST)
orgForm = OrganizationForm(request.POST)
if adminForm.is_valid() and orgForm.is_valid():
adminForm.save()
orgForm.save(commit=False)
username = adminForm.cleaned_data.get('username')
raw_password = adminForm.cleaned_data.get('password1')
user = authenticate(username=username, password=raw_password)
login(request, user)
return redirect('myapp:home')
else:
adminForm = AdminSignUpForm()
orgForm = OrganizationForm()
print(orgForm)
return render(request, 'registration/signup_form.html', {'OrgFrom': orgForm,'Adminform': adminForm})
And this is the template I am rendering the multiple forms
<form enctype="multipart/form-data" method="post" >
{% csrf_token %}
<input type="hidden" name="next" value="{{ next }}">
{{Adminform.as_p }}
{{ OrgForm.as_p }}
<button type="submit" class="btn btn-success">Sign up</button>
</form>
I expect both forms to be displayed but only the Adminform displays and it gives me no error to work with
There is one typo. You need to use {{ OrgFrom.as_p }} instead of {{ Orgform.as_p }}.
When I try to submit my form it says "This field is required."
for an image even though I provide the image and other details to it.
forms.py file
from django.forms import ModelForm
from .models import Status
class CreatePost(ModelForm):
class Meta:
model=Status
fields = ["username","text","privacy","image"]
models.py file
class Status(models.Model):
title=models.CharField(max_length=20,default="updated status")
username = models.ForeignKey('User',on_delete=models.CASCADE)
#username = models.CharField(max_length=20)
text = models.TextField(blank=True, null=True)
image = models.ImageField(upload_to="media/image",null=True)
time = models.DateTimeField(auto_now=True)
privacy = models.CharField(max_length=5, blank=True, null=True)
gid = models.IntegerField(blank=True, null=True)
dp = models.SmallIntegerField(blank=True, null=True)
class Meta:
#unique_together = (('username', 'dp'),)
#managed = False
db_table = 'status'
view.py
def create_post(request):
form=CreatePost(request.POST or None)
if request.method=="POST":
if form.is_valid():
instance=form.save(commit=False)
instance.time=time.time()
instance.save()
return redirect('post',)
return render(request,"uposts/createpost.html",{'form':form})
createpost.html
{% extends "friendsbook/structure.html" %}
{% block content %}
<form action="" method="post">
{%csrf_token %}
{{ form.as_p }}
<input type="submit" value="Save">
</form>
{% endblock %}
What it said after clicking on save button
I am only taking 4 fields in form because all other fields can be null. For time field I took care of that in views.py by giving the time there.
You have to modify the template like this adding multipart/form-data:
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
<input type="file" name="myfile">
<button type="submit">Upload</button>
</form>
and in views.py, you can access the uploaded file using request.FILES.
I am trying to let the user set which timezone they are in, however form validation .is_valid() is failing and cannot figure out why.
The timezone value for a user is stored in a Profile model.
Using ChoiceField and pytz.common_timezones to fill the form field
This would be appear to be quite simple to do, the only thing thats different to my usual way is that the data filling the combo/select box is the use of a ChoiceField and the data is coming from pytz.
I may switch to django-timezone-field to solve this, but I would like to understand why it is failing. I have included all relevant (I think) code below. Any suggestions?
models.py
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
bio = models.TextField(max_length=500, blank=True)
location = models.CharField(max_length=30, blank=True)
birth_date = models.DateField(null=True, blank=True)
timezone = models.CharField(
max_length=255,
blank=True,
)
forms.py
class ProfileEditForm(forms.Form):
profile_timezone = forms.ChoiceField(choices=[(x, x) for x in pytz.common_timezones])
views.py
#login_required
def userprofile_edit(request):
if request.method == "POST":
profile_edit_form = ProfileEditForm()
if profile_edit_form.is_valid():
cd = profile_edit_form.cleaned_data
user = User.objects.get(id=request.user.id)
user.profile.timezone = cd['timezone']
user.profile.save()
messages.success(request, "Profile updated successfully", fail_silently=True)
return redirect('coremgr:userprofile', request.user.id)
else:
messages.error(request, "Error occured. Contact your administrator", fail_silently=True)
print "error: form not valid"
else:
profile_edit_form = ProfileEditForm()
context = {
'profile_edit_form': profile_edit_form,
}
return render(request, 'apps/coremgr/userprofile_edit.html', context)
template
<form name="formprofile" method="POST" action="">
{% csrf_token %}
<p id="profile_timezone" class="form-inline">
{{ profile_edit_form.profile_timezone.errors }}
Timezone:
{{ profile_edit_form.profile_timezone }}
</p>
<button id="id_btn_profile_edit_save" type="submit" class="btn btn-default" tabindex=7>Save</button>
</form>
add request.POST in form
if request.method == "POST":
profile_edit_form = ProfileEditForm(request.POST)
I believe you would need to pass in request.POST when initializing the form in your if block.