Currently both of these print statements either log 'None' or just do not show at all. Even if I just print("hello') in the form.is_valid conditional I do not see it. Not sure what I have done wrong but the data was saving into the django admin but now it is not...
def create_user_account(request, *args, **kwargs):
form = UserAccountForm(request.POST or None)
print(request.POST.get('account_email'))
if form.is_valid():
print(form['account_email'].value())
form.save()
form = UserAccountForm()
context = {
'form': form
}
return render(request, 'registration/register_user.html', context)
and the html:
{% block content %}
<form action="{% url 'home' %}" method='POST'> {% csrf_token %}
{{form.as_p}}
<input type='submit' value='Submit'/>
</form>
{% endblock %}}
edit: i do get "POST / HTTP/1.1" 200 when I send the request which is weird. I don't see a 201 or 302 like I would expect.
forms.py:
class UserAccountForm(forms.ModelForm):
class Meta:
model = UserAccount
fields = [
'first_name',
'last_name',
'account_email',
'country'
]
class UserAccount(models.Model):
first_name = models.CharField(max_length=30, null=False)
last_name = models.CharField(max_length=30, null=False)
account_email = models.EmailField(max_length = 254, null=False)
country = models.CharField(choices=COUNTRY_CHOICES, null=False,
max_length=75)
activated = models.BooleanField(default=False)
CONTINUED:
So I dropped the database, migrated and the table appeared like normal. I tried to save data and the same problem? BUT I also tried to add information manually through the admin site and got this error:
OperationalError at /admin/profiles/useraccount/add/
no such table: main.auth_user__old
So I updated to Django 3.0.6 and this solved the problem - can now add manually but still cannot add through the form.
This was the solution. I don't know why it stopped working but it did. I feel I got finessed by indentation.
def register(request):
if request.method == 'POST':
form = UserAccountForm(request.POST)
if form.is_valid():
form.save()
return redirect('/')
else:
form = UserAccountForm()
context = {
'form': form
}
return render(request, 'registration/register_user.html', context)
Related
I am creating a form with all sorts of headers and question before each field.
I initially create a form in Forms.py, but it seems quite difficult to customise it the way I want it.
I resorted to build the form in the html template.
I am struggling to create a drop down menu.
In this example, when selecting the colour, users would have 4 choices listed in the choices in models.py. I am clearly not linking the form in the template to the actual form.
What am I doing wrong?
(I should say, I saw a couple of things on here about fieldsets, but I dont understand the actual solutions explained)
Here is the code
Models.py
LOOKCOLOUR=(
(1,'Straw'),
(2,'Yellow'),
(3,'Gold'),
(4,'Amber'),
)
class ChampageRating(models.Model):
user = models.ForeignKey(User,blank=True, on_delete=models.CASCADE)
product=models.ForeignKey(Product,related_name="champcomments", on_delete=models.CASCADE)
look_colour=models.IntegerField(choices=LOOKCOLOUR, default=0)
..
def __str__(self):
return '%s - %s - %s'%(self.user, self.product, self.date_added)
forms.py
class ElderFlowerChampForm(ModelForm):
class Meta:
model = ChampageRating
fields = ('look_colour', )
labels ={
'look_colour': 'Colour',
}
widgets = {
'look_colour':forms.Select(attrs={'class':'form-control'}),
}
views.py
def elderflowerchamp(request, product_id):
global ChampageRating
product = Product.objects.get(pk=product_id)
url = request.META.get('HTTP_REFERER')
submitted = False
try:
if request.method == "POST":
reviews = ChampageRating.objects.get(pk=product_id)
if request.user.is_superuser:
form = ElderFlowerChampFormAdmin(request.POST, instance=reviews)
if form.is_valid():
form.save()
return redirect('home')
else:
form = ElderFlowerChampForm(request.POST, instance=reviews)
if form.is_valid():
ChampageRating = form.save(commit=False)
ChampageRating.user = request.user
ChampageRating.save()
return redirect('home')
else:
#This part goes to the page, but doesnt submit
reviews = ChampageRating.objects.get(pk=product_id)
if request.user.is_superuser:
form = ElderFlowerChampFormAdmin
else:
form = ElderFlowerChampForm
if 'submitted' in request.GET:
submitted = True
except:
reviews = None
if request.user.is_superuser:
form = ElderFlowerChampFormAdmin(request.POST)
if form.is_valid():
data = ChampageRating()
data.rating = form.cleaned_data['rating']
data.look_colour = form.cleaned_data['look_colour']
data.ip = request.META.get('REMOTE_ADDR')
data.product_id = product_id
data.user_id = request.user.id
data.save()
messages.success(request, 'Thank you! Your review has been submitted.')
return redirect('home')
else:
form = ElderFlowerChampForm(request.POST)
if form.is_valid():
data = ChampageRating()
data.rating = form.cleaned_data['rating']
data.look_colour = form.cleaned_data['look_colour']
data.ip = request.META.get('REMOTE_ADDR')
data.product_id = product_id
data.user_id = request.user.id
data.save()
messages.success(request, 'Thank you! Your review has been submitted.')
return redirect('home')
template
<form action="{% url 'ElderFlowerReview' product.id%}" method="POST">
{%csrf_token%}
<h4>Look</h4>
<h5>Colour</h5>
<select name="look_colour" rows="4" class="form-control"></select>
</form>
Just in case someone comes across the same problem, I kinda found the solution. (it creates new problems, but it's a start).
Source here: https://github.com/hadpro24/django-forms-fieldset
Here is what I did.
I installed fieldsets (thats the part I was missing on other posts)
pip install django-forms-fieldset
I added fieldsets in the installed apps (in setting.py)
INSTALLED_APPS = [
,
'forms_fieldset']
in forms.py Fieldsets need to be added before Meta
class ElderFlowerChampFormAdmin(ModelForm):
fieldsets=[
("Look",{'fields':[
('look_colour','look_clarity','look_effervescence')]}),
]
class Meta:
model = ChampageRating
fields = ('user','look_colour', ..)
labels ={
'user': '',
'product': '',
'look_colour': '',
}
widgets = {
'user': forms.Select(attrs={'class':'form-control'}),
'look_colour':forms.Select(attrs={'class':'form-control'}),
}
then in the template
{% load forms_fieldset static %}
<link rel="stylesheet" type="text/css" href="{% static 'forms_fieldset/css/main.css' %}">
<form action="{% url '#' product.id%}"method = POST>
{%csrf_token%}
{{ form|fieldset}}
<button class="btn btn-secondary">Add Review</button>
</form>
Account is my AUTH_USER_MODEL and AccountDisplayInfo consists of all the additional display info of every account. So they can input and submit, and subsequently update their information. These are my codes, but I'm unsure why it isn't working. First of all, I am receiving this error:
DoesNotExist at /account/5/displayinfo/ AccountDisplayInfo matching query does not exist.
Secondly, the "update" function isn't working.
models.py
class Account(AbstractBaseUser):
email = models.EmailField(verbose_name="email", max_length=60, unique=True)
username = models.CharField(max_length=30, unique=True)
class AccountDisplayInfo(models.Model):
account = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
instagram = models.CharField(max_length=50, unique=True, blank=True, null=True) #instagram
.html
<form method="POST" enctype="multipart/form-data">{% csrf_token %}
{{ form.as_p }}
<div class="d-flex justify-content-center">
<button type="submit" class="btn btn-primary btn-sm col-lg-5">Update</button>
</div>
</form>
views.py
def display_information_view(request, *args, **kwargs):
user_id = kwargs.get("user_id")
account = Account.objects.get(pk=user_id)
context = {}
displayinfo = AccountDisplayInfo.objects.get(account=account)
if request.POST:
form = DisplayInformationForm(request.POST, request.FILES, instance=request.user)
if form.is_valid():
info = form.save(commit=False)
info.account = request.user
info.save()
messages.success(request, 'Your profile display information have been updated', extra_tags='editdisplayinfo')
return redirect("account:view", user_id=account.pk)
else:
form = DisplayInformationForm(request.POST, instance=request.user,
initial={
"instagram": displayinfo.instagram,
}
)
context['form'] = form
else:
form = DisplayInformationForm(
initial={
"instagram": displayinfo.instagram,
}
)
context['form'] = form
return render(request, "account/displayinfo.html", context)
forms.py
class DisplayInformationForm(forms.ModelForm):
class Meta:
model = AccountDisplayInfo
fields = ('instagram')
Also, would be great if you can advise on this::
If I have 2 tables. Table 1 and Table 2. Table 2 has a foreign key to table 1 but table 1 dont have a foreign key to table 2. How can I query table 2's data from table 1? Thanks
By default .get() will return a DoesNotExist exception if no object matches the query you executed and stop the code from running, so if you want to input it manually on the same page use filter instead:
displayinfo = AccountDisplayInfo.objects.filter(account=account).first()
Then in your template do something like this:
{% if displayinfo %}
... show display info...
{% else %}
<p> No info yet </p> <!-- (or show some form) -->
{% endif %}
To answer your other question:
You have to use the related_name or related models attribute to access the ForeignKey data or use the model name with the _set suffix, for example:
class Post(models.Model):
title = models.CharField(max_lenght=10)
class Comment(models.Model):
body = models.CharField(max_lenght=200)
post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='comments')
then you would get the Post and its comments:
post = Post.objects.get(pk=1)
comments = post.comments.all()
if you didn't have the related_name attribute in your model field you would do this instead:
comments = post.comment_set.all()
UPDATE
Maybe the issue is in your Form class, try removing the save method from it and instead do this in your view:
if request.POST:
form = DisplayInformationForm(request.POST, request.FILES, instance=request.user)
if form.is_valid():
info = form.save(commit=False)
info.account = request.user
messages.success(request, 'Your profile display information have been updated', extra_tags='editdisplayinfo')
info.save()
return redirect("account:view", user_id=account.pk)
this might be a pretty stupid question. Also I am new to django. But I was trying to create a basic file upload approach with django where user uploads a file and it gets stored into the defined media path (or whatever that it's called) and that the file size, name, and some other attributes that are needed can be stored into the database. So I have the model ready which will help you understand the question better.
class Document(models.Model):
file_uid = models.CharField(max_length = 16)
file_name = models.CharField(max_length = 255)
file_size = models.CharField(max_length = 255)
file_document = models.FileField(upload_to='uploaded_files/')
uploaded_on = models.DateTimeField(auto_now_add=True)
uploaded_by = models.CharField(max_length=16)
Now it's clearly plain that we don't need to create all the fields in the form and that most them can be received from the file itself (like the name, size). for other attrs like uid and uploaded by those also will be added by the backend. So that's where I am stuck. I have searched for 2 days straight and still couldn't find a proper solution.
As of now this is my views.py
def uploadView(request):
if(request.method == 'POST'):
form = FileUploadForm(request.POST, request.FILES)
uploaded_file = request.FILES['uploaded_file']
file_dict = {
'file_uid' : get_random_string(length=10),
'file_name' :uploaded_file.name,
'file_size' : uploaded_file.size,
'file_document' : request.FILES['uploaded_file'],
'uploaded_by' : get_random_string(length=10)
}
form = FileUploadForm(data=file_dict)
if form.is_valid():
form.save()
return HttpResponse("You reached here")
else:
return HttpResponse("Your form is invalid")
else:
form = FileUploadForm(request.POST, request.FILES)
return render(request, 'function/upload.html', {
'form':form
})
I don't know if this is correct but as of know the form.isvalid() is false.
here's my forms.py
class FileUploadForm(forms.ModelForm):
file_document = forms.FileField(widget=forms.FileInput(attrs={'name':'uploaded_file'}))
class Meta:
model = Document
fields = ('file_uid', 'file_name', 'file_size', 'file_document', 'uploaded_by')
and my upload page section looks like this
<body>
<h1>Upload a file</h1>
<form action="" method="POST" enctype="multipart/form-data">
{% csrf_token %}
<input type="file" name="uploaded_file">
<button type="submit">Upload</button>
</form>
</body>
If you can mercifully guide me into a proper way of doing this i'll be really gratefull.
Before solution, Here are few issues i found in your code
Major issue is how you tried to update the name of your file_document input, it doesn't work this way. confirm this by inspecting in devtools.
Checkout my answer here to update name attribute of django input form field.
Without updating this, you are not getting file from form.
Not issues just something i would like to point out
def uploadView(request):
if(request.method == 'POST'):
form = FileUploadForm(request.POST, request.FILES)
# your code in between, here the above form is never used and the overridden by the form in next line so why assigning it
form = FileUploadForm(data=file_dict)
# your form.is_valid() code start here
else:
form = FileUploadForm(request.POST, request.FILES)
# This block will only run for GET request, why using request.POST, request.FILES
return render(request, 'function/upload.html', {
'form':form
})
Here is how i got your code working
update FileUploadForm like this
class FileUploadForm(forms.ModelForm):
class Meta:
model = Document
fields = ('file_uid', 'file_name', 'file_size', 'file_document', 'uploaded_by')
# below code is only used to change the name of file_document to uploaded_file
custom_names = {'file_document': 'uploaded_file'}
def add_prefix(self, field_name):
field_name = self.custom_names.get(field_name, field_name)
return super(FileUploadForm, self).add_prefix(field_name)
use form in html like this
<form method="POST" action="" enctype="multipart/form-data">
{% csrf_token %}
{{form.file_document}}
<input type="submit" value="send"/>
</form>
Update view as
def uploadView(request):
if(request.method == 'POST'):
uploaded_file = request.FILES['uploaded_file']
file_dict = {
'file_uid' : 'test1',
'file_name' :uploaded_file.name,
'file_size' : uploaded_file.size,
'uploaded_by' : 'hemant'
}
form = FileUploadForm(file_dict, request.FILES)
if form.is_valid():
form.save()
return HttpResponse("You reached here")
else:
return HttpResponse("Your form is invalid")
else:
form = FileUploadForm()
return render(request, 'function/upload.html', {
'form':form
})
I need to tie the user to their post but 'author' is not included in the fields of the video upload form so I can't access the field when I save the form.
When I add 'author' to the fields it gives a drop down box. (users shouldn't be able to post as anyone but themselves) I tried just listing the fields individually like so {{form.title}} to keep the author field but not show it to the user, it showed anyway.
In the 'author' field of the VideoPost model I've tried changing out the null=True for these variants on default default=None, default=0, default='None', default=User, default=User.id where User = get_user_model()
When I used default='None' the author dropdown box had the current users name in it, but still allowed a choice, when I tried to post it I got
ValueError: invalid literal for int() with base 10: 'None'
Also, in the views.py, I tried form = VideoPostForm(request.user,request.POST or None, request.FILES or None)
and got CustomUser object has no .get() attribute and that was caused by form.save()
I feel like this might be obvious to someone else but I've been staring at this code for a while now to figure it out.(a couple hours a day doing research and gaining better understanding as to how all of the things I'm doing actually work 'under the hood', I worked on other parts while trying to figure this out because, development speed matters and I could actually figure the other stuff out)
forms.py
class VideoPostForm(forms.ModelForm):
class Meta:
model = VideoPost
fields = ['author','title', 'description', 'file']
views.py
def upload_video(request):
form = VideoPostForm(request.POST or None, request.FILES or None)
if form.is_valid():
form.save(commit=False)
VideoPost.author = request.user
form.save()
return redirect('home')
else:
form = VideoPostForm()
return render(request, 'upload_video.html', {'form': form})
models.py
class VideoPost(models.Model):
objects = models.Manager()
author = models.ForeignKey(User, related_name='video_post', on_delete=models.CASCADE, null=True)
title = models.CharField(max_length=50, null=True, blank=True)
published_date = models.DateTimeField(auto_now_add=True)
description = models.TextField()
validate_file = FileValidator(max_size=52428800)
file = models.FileField(upload_to='videos/', validators=[validate_file])
def __str__(self):
return 'Post by {}'.format(self.author)
template (excluding author field)
<h1>Create Post Page</h1>
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
<p> <!-- Normally the fields would be form.as_p -->
{{ form.title }}
{{ form.description }}
{{ form.file }}</p>
<button type="submit">Submit New Post</button>
</form>
The views.py is very close. The form.save() method returns an instance of VideoPost. You can then set the author to the current user directly to the new video post object that was created by the form. See code sample below.
views.py
def upload_video(request):
if request.method == "POST":
form = VideoPostForm(request.POST, request.FILES or None)
if form.is_valid():
new_videopost = form.save()
new_videopost.author = request.user
new_videopost.save()
return redirect('home')
else:
form = VideoPostForm()
return render(request, 'upload_video.html', {'form': form})
I am trying to save simple form add_product, I don't have any error but the new product doesn't appear in admin or on a page. I really not sure what I am doing wrong. Any suggestion would be great! Thank you.
my views.py
def add_product(request):
author = request.user
product_form = ProductForm(request.POST, request.FILES, instance=author)
if product_form.is_valid():
form = product_form.save(commit=False)
form.save()
return HttpResponseRedirect('/products/')
else:
product_form = ProductForm()
return render(request, 'products/add_product.html', {'product_form': product_form})
my forms.py
class ProductForm(forms.ModelForm):
class Meta:
model = Product
fields = ('title', 'content', 'picture',)
urls.py
urlpatterns = patterns('',
url(r'^$', views.all, name='all'),
url(r'^add/$', views.add_product, name='add_product'),
url(r'^(?P<slug>[\w-]+)/$', views.single_product, name='single_product'),
)
template: products/add_product.html
<h1>Add Product</h1>
<form method="post" action="" enctype="multipart/form-data"> {% csrf_token %}
{{ product_form.as_p }}
<input type="submit" value="Add">
</form>
models.py
class Product(models.Model):
title = models.CharField(max_length=100)
author = models.ForeignKey(User)
content = models.CharField(max_length=300)
slug = models.SlugField(unique=True)
picture = models.ImageField(upload_to='products/picture/', blank=True)
def __unicode__(self):
return self.title
def get_absolute_url(self):
return reverse('single_product', kwargs={'slug': self.slug})
I fixed my view.py by adding following line :
form.author = request.user
and I removed the first line : author = request.user plus the instance as well.
So now works fine :)
Your code doesn't seem to be valid. And there should be errors.
The first thing that is notice is following:
author = request.user
product_form = ProductForm(request.POST, request.FILES, instance=author)
You are passing user instance as a instance to author form. That doesnt make any sense. For product form instance should a product, not a user. If you want to set a author field you can do following :
form = product_form.save(commit=False)
form.author = author
form.save()
Also its not good to call this variable form, because its not a form anymore, its a product object that is returned by save function.