Entered fields not saving to model - django

I'm trying to create a pastebin clone in Django. I've created a paste app, and a Paste class in my models.py
class Paste(models.Model):
SYNTAX_CHOICES = {
(0, "Plain"),
(1, "Python"),
(2, "HTML"),
(3, "SQL"),
(4, "Javascript"),
(5, "CSS"),
}
content = models.TextField()
title = models.CharField(blank=True, max_length=30)
syntax = models.IntegerField(choices=SYNTAX_CHOICES, default=0)
poster = models.CharField(blank=True, max_length=30)
timestamp = models.DateTimeField(default=datetime.datetime.now, blank=True)
class Meta:
ordering = ('-timestamp',)
def __unicode__(self):
return "%s (%s)" % (self.title or "#%s" % self.id,
self.get_syntax_display())
#permalink
def get_absolute_url(self):
return ('django.views.generic.list_detail.object_detail',
None, {'object_id': self.id})
class PasteAdmin(admin.ModelAdmin):
list_display = ('__unicode__', 'title', 'poster', 'syntax', 'timestamp')
list_filter = ('timestamp', 'syntax')
admin.site.register(Paste, PasteAdmin)
In one of my templates, I have a form that requires the user enter the required details(name of paste, syntax, paste itself).
{% extends "base.html" %}
{% block content %}
<h1>Your user is</h1>
{{ request.user }}
{{ request.user.is.authenticated }}
<form action="" method="POST">
{% csrf_token %}
Title: <textarea rows="1" cols="50" placeholder="Title of paste"></textarea><br>
Syntax: <textarea rows="1" cols="50" placeholder="Enter syntax"></textarea><br>
{{ form.content }}<br>
<textarea rows="4" cols="50" placeholder="Please enter the text you'd wish to paste..."></textarea>
<input type="submit" name="submit" value="Paste" id="submit">
{% endblock content %}
But when the information is entered, the data is not saved when checking the admin. What am I missing to save the entered information to that specific model?
As well, I have a registration form that creates new users, as well as a form that allows you to login/logout.
pastes/views.py
def signup(request):
if request.method == 'POST':
form = UserCreationForm(request.POST)
if form.is_valid():
form.save()
username = form.cleaned_data.get('username')
raw_password = form.cleaned_data.get('password1')
user = authenticate(username=username, password=raw_password)
login(request, user)
return redirect('/home')
else:
form = UserCreationForm()
return render(request, 'signup.html', {'form': form})
How would I go about linking the paste to the user? Or, allowing for it to remain anonymous?
Sorry for all the (dumb) questions, I'm quite lost in this and I've only been doing Django for 24 hours.

Related

Django - Passing the creator of a form to the form

I am making an auction site. I need to know per listing who the creator was (so the creators will have the possibility to delete the listing). It works for me to manually change the user in Django Admin, but I want it to be automatically saved when someone creates a new listing.
How do I pass the creator of a form to the form?
These are the relevant models:
class User(AbstractUser):
pass
class AuctionListing(models.Model):
title = models.CharField(max_length=64)
description = models.CharField(max_length=512, default="")
starting_bid = models.DecimalField(max_digits=6, decimal_places=2, default=0.01, validators=[MinValueValidator(Decimal('0.01'))])
url = models.URLField(max_length=200, blank=True)
category = models.CharField(max_length = 20)
user = models.ForeignKey(User, on_delete=models.CASCADE, db_constraint=False, related_name="items")
def __str__(self):
return self.title
Here is my forms.py:
class CreateListing(forms.ModelForm):
category = forms.ModelChoiceField(queryset=Category.objects.all(), empty_label="No category")
class Meta:
model = AuctionListing
fields = ('title', 'description', 'starting_bid', 'url', 'category', 'user')
widgets = {
'title': forms.TextInput(attrs={'placeholder':'Write your listing title here...'}),
'description': forms.Textarea(attrs={'placeholder':'Write your comment here...', 'rows':3}),
'user': forms.HiddenInput(),
}
def __init__(self, *args, **kwargs):
user = kwargs.pop('user')
super().__init__(*args, **kwargs)
self.fields['user'].initial = user.id
And here was my attempt for the view:
def create_listing(request):
form = CreateListing(request.POST, user=request.user)
if request.method == "POST":
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse("index"))
else:
print("RIP")
return render(request, "auctions/create_listing.html", {"form": form})
return render(request, "auctions/create_listing.html", {
"form" : CreateListing(user=request.user)
})
auctions/create_listing.html looks like this:
<h1> Create new listing </h1>
<form action="" method="POST">
{% csrf_token %}
<label>Name*</label>
<br>
{{ form.title }}
<br>
<label >Description*</label>
<br>
{{ form.description }}
<br>
<label >Starting bid*</label>
<br>
{{ form.starting_bid }}
<br>
<label > Image url (optional) </label>
<br>
{{ form.url }}
<br>
<label > Category (optional) </label>
<br>
{{ form.category }}
<br>
{{ form.user }}
<button type="submit" class="btn btn-primary save">Create your listing</button>
</form>
The error I get with this is: "BaseModelForm.init() got an unexpected keyword argument 'user'"
How can I fix this so the user will automatically be saved each time a listing is created?
Add user argument in the __init__ method of the form. You can set the user right there and there is no need for even displaying the user field. You can completely hide it.
class CreateListing(forms.ModelForm):
category = forms.ModelChoiceField(queryset=Category.objects.all(), empty_label="No category")
class Meta:
model = AuctionListing
fields = ('title', 'description', 'starting_bid', 'url', 'category', 'user')
widgets = {
'title': forms.TextInput(attrs={'placeholder':'Write your listing title here...'}),
'description': forms.Textarea(attrs={'placeholder':'Write your comment here...', 'rows':3}),
'user': forms.HiddenInput(),
}
def __init__(self, *args, **kwargs):
user = kwargs.pop('user')
super().__init__(*args, **kwargs)
self.fields['user'].initial = user.id
Remember to use the user kwarg in the view:
def create_listing(request):
form = CreateListing(request.POST, user=request.user)
if request.method == "POST":
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse("index"))
else:
print("RIP")
# If form is invalid you should render the same template again
# with the errors
return render(request, "auctions/create_listing.html", {"form": form})
return render(request, "auctions/create_listing.html", {
# For the empty form, this needs to be an instance of the form,
# and not a class
"form" : CreateListing(user=request.user)
})
Also, you can replace your HTML with:
{{ form.user }}
Replace {{ form.user }} by <input type="hidden" name="user" value="{{request.user}}">
User has to come automatically so you don't need to display user field in the front-end
by the above method you'll get logged in user but still hard to save as it is foreign key, what ever you get from front-end it'll be string type.
So best suggestion is the below code.
if form.is_valid():
form_data = form.save()
form_data.user = request.user
form_data.save()

UNIQUE constraint failed: user_profile.StudentID error

I am getting this error(IntegrityError at /register/) every time I try to create a new user. In user creation form I am creating both User and profile.
here is my models.py
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
StudentID = models.CharField(max_length=8,unique=True)
Branch = models.CharField(max_length=255,choices=Departments,default="CSE")
YearOfStudy = models.IntegerField(default=1)
ContactNumber = PhoneField(help_text='Contact phone number')
image = models.ImageField(default='default.jpeg' , upload_to='profile_pics')
parentsContactNumber = PhoneField(help_text="Parent's phone number")
def __str__(self):
return f'{self.user.username} Profile'
here is forms.py
class UserRegisterForm(UserCreationForm):
email = forms.EmailField()
first_name = forms.CharField()
last_name = forms.CharField()
class Meta:
model = User
fields = ['username','email','first_name','last_name','password1','password2']
class ProfileCreationForm(forms.ModelForm):
class Meta:
model = Profile
fields = ['StudentID','Branch','YearOfStudy','ContactNumber']
here is views.py
def register(request):
if request.method == 'POST':
form = UserRegisterForm(request.POST)
form1 = ProfileCreationForm(request.POST)
if form.is_valid() and form1.is_valid():
form.save()
form1.save()
username = form.cleaned_data.get('username')
messages.success(request, f'Your account has been created! You are now able to log in')
return redirect('login')
else:
form = UserRegisterForm()
form1 = ProfileCreationForm()
context = {
'form': form,
'form1': form1
}
return render(request, 'user/register.html', context)
here is register.html
{% block content %}
<div class="content-section">
<form method="POST">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4">JOIN TODAY</legend>
{{ form|crispy }}
{{ form1|crispy }}
</fieldset>
<div class="form-group">
<button class="btn btn-outline-info" type="submit">Sign Up</button>
</div>
</form>
</div>
{% endblock content %}
please help me with this error
You are set unique=True in...
StudentID = models.CharField(max_length=8,unique=True)
So, when you pass student_id from your form at that time you pass the same id in form which is already in your database thus this error is coming.

Why isn't this creating the models in batch?

I am trying to create the object blank in a batch but it is only creating one object after I fill in the form, could anyone help me with what I am doing wrong?
html
{% block content %}
<form class="box" method = "post">
{% csrf_token %}
<h1>Air Ticket Sales</h1>
{{ form }}
batch size:
<input type="number" name="batch" value="{{ batch }}">
<input type="submit" name="" value="Create Blank">
</form>
{% endblock %}
model
class blank(models.Model):
#an integer field that automatically increments by itself as the object are created
number = models.AutoField(primary_key=True)
type = models.CharField(max_length=50, choices=type_choices, default='green')
is_sold = models.BooleanField(default=False)
is_refunded = models.BooleanField(default=False)
date = models.DateField(auto_now_add=True)
date.editable = True
advisor = models.ForeignKey(
User,
models.SET_NULL,
blank=True,
null=True,
)
view
def create_blanks(request):
if request.method == 'POST':
#initializes the data from the form to the value form
form = blank_form(data=request.POST)
batch = request.POST.get("batch", "")
if form.is_valid():
for b in batch:
form.save()
return render(request, "create_blanks.html")
else:
return render(request, "create_blanks.html")
else:
form = blank_form
return render(request, "create_blanks.html", {'form':form})
Yep just found the solution with your help I don't think it is the most efficient or the cleanest one but here you go
for b in range(int(batch)):
form.save()
form.instance = None
form = blank_form(data=request.POST)

django - image isn't saving, all other fields are

When I update the user profile via the view everything is saving to the db except the image. The forms are validating but image isn't being saved. I can log in the admin portal and successfully add an image to an existing instance. I assume my problem lies in my html template but I can't figure out what it is.
**Btw I've read multiple similiar post but none I believe addresses my issue.
form.py
class EditUserForm(forms.ModelForm):
template_name='/something/else'
class Meta:
model = User
fields = (
'email',
'first_name',
'last_name',
)
class EditProfileForm(forms.ModelForm):
template_name='/something/else'
class Meta:
model = UserProfile
fields = (
'description',
'city',
'website',
'phone',
'image',
)
views.py
#transaction.atomic
def edit_profile(request):
if request.method == 'POST':
form = EditUserForm(request.POST, instance=request.user)
form2 = EditProfileForm(request.POST, instance=request.user.userprofile)
if form.is_valid() and form2.is_valid():
form.save()
form2.save()
return redirect(reverse('accounts:view_profile'))
else:
form = EditUserForm(instance=request.user)
form2 = EditProfileForm(instance=request.user.userprofile)
args = {'form': form, 'form2':form2}
return render(request, 'accounts/edit_profile.html', args)
models.py
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
description = models.CharField(max_length=100, default='')
city = models.CharField(max_length=100, default='')
website = models.URLField(default='')
phone = models.IntegerField(default=0)
image = models.ImageField(upload_to='profile_image', blank=True)
def __str__(self):
return self.user.username
edit_profile.html
<div class="container">
{% if form.errors %}
<ol>
{% for field in form %}
<H3 class="title">
<p class="error"> {% if field.errors %}<li>{{ field.errors|striptags }}</li>{% endif %}</p>
</H3>
{% endfor %}
</ol>
{% endif %}
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
{{ form2.as_p }}
<button type="submit">Submit</button>
</form>
<br>
</div>
If you are uploading files, you must instantiate the form with request.POST and request.FILES.
form2 = EditProfileForm(request.POST, request.FILES, instance=request.user.userprofile)
See the docs on file uploads for more info.

Can't get data in edit form

I'm trying to create an edit form for existing users, I have the User model and I associated to it a profile.
The problem is that the fields of profile are empty in the rendered html, however when I created a new user I filled these fields, and when I enter to administration I find the fields are filled.
models.py
from django.db import models
from django.contrib.auth.models import User
class Profile(models.Model):
DEPARTMENT_CHOICES = (('MI', 'Math et info'),
('ST', 'Science et Tech'),
('SM', 'Science de la matiere'))
user = models.OneToOneField(User, on_delete=models.CASCADE)
teacher = models.BooleanField(default=False)
description = models.TextField(blank=True)
department = models.CharField(max_length=35, choices=DEPARTMENT_CHOICES, blank=True)
picture = models.ImageField(upload_to='profile-images', blank=True)
def __str__(self):
return self.user.username
views.py
def profile_view(request):
if request.method == 'POST':
user_form = EditUserForm(request.POST, instance=request.user)
ins = Profile.objects.get(pk=5)
profile_form = EditProfileForm(request.POST, request.FILES, instance=ins)
if user_form.is_valid() and profile_form.is_valid():
user = user_form.save()
user.save()
profile = profile_form.save(commit=False)
profile.user = user
if 'picture' in request.FILES:
profile.picture = request.FILES['picture']
profile.save()
return redirect(home)
else:
user_form = EditUserForm(instance=request.user)
profile_form = EditProfileForm(request.FILES, instance=request.user)
return render(request, 'account/profile.html', {'user_form': user_form,
'profile_form': profile_form})
forms.py
class EditProfileForm(forms.ModelForm):
class Meta:
model = Profile
fields = ('description', 'department', 'picture', )
class EditUserForm(forms.ModelForm):
class Meta:
model = User
fields = ('username', 'email', )
profile.html
{% extends 'manhal/base.html' %}
{% load staticfiles %}
{% load crispy_forms_tags %}
{% block content %}
<div class="col-md-6">
<form method="post" enctype="multipart/form-data" action="{% url 'profile' %}" class="form-horizontal">{% csrf_token %}
<fieldset>
<legend>User Profile</legend>
{{ user_form|crispy }}
{{ profile_form|crispy}}
<input type="submit" value="Save" class="btn btn-primary">
</fieldset>
</form>
</div>
{% endblock %}
First, your if/else block is checking if the request is a POST. Since the else block is not a POST, you do not want to pass any POST data into your form. This will make the form think it's bound with no data.
Also, it looks like you are passing the request.user to your ProfileForm as the instance, but the model on the ProfileForm meta class is expecting a Profile object.
Can you fix those two things and see if it works or not? If it doesn't work, please post some more code (like your templates).