I have a question concerning a new project I'm creating. To put it simply, the website has user accounts, and each user has the ability to create a simple paragraph. The form is functioning perfectly, but I can't seem to assign the user's ID to the saved form.
model.py
class UserProfile(models.Model):
user = models.OneToOneField(User)
class Thoughts(models.Model):
user = models.ForeignKey(UserProfile, null=True)
title = models.CharField(max_length=150, default='')
description = models.CharField(max_length=5000, default='')
forms.py
class ThoughtForm(ModelForm):
class Meta:
model = Thoughts
fields = ['title', 'description']
views.py
#login_required(login_url='sign_in')
def add_thought(request):
context = {}
populateContext(request, context)
user_details = UserProfile.objects.get(user=request.user)
context.update(user_details=user_details)
if request.method == 'POST':
new_thought_form = ThoughtForm(request.POST)
if new_thought_form.is_valid():
new_thought_form.save()
return HttpResponse('Hurray, saved!')
else:
new_thought_form = ThoughtForm()
c = {'new_thought_form': new_thought_form,}
c.update(csrf(request))
return render_to_response('lala/add_new_thought.html', c)
Whenever I try adding "instance=user_details.id", it says that the 'int' object has no attribute '_meta'. Any thoughts?
You can simplify the models by removing the UserProfile model:
# models.py
class Thoughts(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(max_length=150, default='')
description = models.CharField(max_length=5000, default='')
Your forms.py looks good.
Change your views:
# views.py
#login_required(login_url='sign_in')
def add_thought(request):
if request.method == 'POST':
form = ThoughtForm(request.POST)
if form.is_valid():
thought = form.save(commit=False)
thought.user = request.user
thought.save()
return HttpResponse('Hurray, saved!')
else:
form = ThoughtForm()
return render(request, 'lala/add_new_thought.html', {
'form': form
})
Related
i have a an order model which is in m2m relationship with a product model, when i create an order, and after checking my DB, i can see the order saved but not in the through model
models.py
from inventory.models import Product
from user.models import User
class Order(models.Model):
product = models.ManyToManyField(Product, through='OrderItems' )
vendeur = models.ForeignKey(User, on_delete=models.CASCADE)
quantity = models.PositiveIntegerField()
class Customer(models.Model):
full_name = models.CharField(max_length=60, verbose_name='full name')
address = models.CharField(max_length=255)
phone = models.CharField(max_length=20)
city = models.CharField(max_length=30)
class OrderItems(models.Model):
product = models.ForeignKey(Product, on_delete=models.SET_NULL, null=True)
order = models.ForeignKey(Order,on_delete=models.CASCADE)
customer = models.ForeignKey(Customer, on_delete=models.SET_NULL, null=True)
views.py
#login_required
def add_order(request):
if request.method == 'POST':
form = NewOrderForm(request.POST)
if form.is_valid():
order = form.save(commit=False)
order.vendeur = request.user
order.save()
return redirect('dashboard-index', )
else :
form = NewOrderForm()
return render(request, 'dashboard/add_order.html', {'form': form})
forms.py
class NewOrderForm(forms.ModelForm):
class Meta:
model = Order
fields = ('product','quantity')
if you use save(commit=False), Calling save_m2m() is required.
because your form has a m2m field
refer to documentions
#login_required
def add_order(request):
if request.method == 'POST':
form = NewOrderForm(request.POST)
if form.is_valid():
order = form.save(commit=False)
order.vendeur = request.user
order.save()
form.save_m2m()
return redirect('dashboard-index', )
else :
form = NewOrderForm()
return render(request, 'dashboard/add_order.html', {'form': form})
I have the following Model/form/view:
Model
class Account(models.Model):
username = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
name = models.CharField(max_length=150)
identifier_type = models.ForeignKey(IdentifierType, on_delete=models.SET_NULL, null=True)
actflag = models.CharField(max_length=1, blank=True)
created_date = models.DateTimeField(blank=True, null=True)
comments = models.TextField(_(
'comments'), max_length=500, blank=True)
priority_type = models.ForeignKey(PriorityType, on_delete=models.SET_NULL, null=True)
deadline_date = models.DateTimeField(blank=True, null=True)
def __str__(self):
return self.name
Form
class PortfolioForm(forms.ModelForm):
portfolio = forms.CharField(widget=forms.Textarea)
class Meta:
model = Account
fields = ['name', 'comments', 'priority_type', 'deadline_date', 'identifier_type', 'portfolio']
View
def portfolios(request):
if request.user.is_authenticated:
if request.POST:
fm = PortfolioForm(request.POST)
user = User.objects.get(username=request.user)
if fm.is_valid():
messages.success(request, 'Portfolio has been created.')
fm.save()
return redirect('portfolios')
else:
fm = PortfolioForm()
context = {"name": request.user, "form": fm}
return render(request, 'portfolios.html', context)
else:
return redirect('login')
The form works fine with posting via my template, however you will notice there are some fields within my model that are not in my form I would like to fill in automatically without the user having to fill in - for example username field I would like this to be current user that submits the form and also created_date would like the current date time the user has submitted the form.
I tried to add the following to my view under if fm.is_valid(): attempting to save username as current user to the model but did not work:
Account.objects.username = request.user
How can I go about doing this? Thanks in advance
You can save these values after creating the Account object when you save the form. If you use the commit=False parameter in the save method, this does not hit the database and you can easy modify the Account object.
from django.utils import timezone
def portfolios(request):
if request.user.is_authenticated:
if request.POST:
fm = PortfolioForm(request.POST)
# user = User.objects.get(username=request.user)
if fm.is_valid():
account = fm.save(commit=False)
account.username = request.user
account.created_date = timezone.now()
account.save()
messages.success(request, 'Portfolio has been created.')
return redirect('portfolios')
else:
fm = PortfolioForm()
context = {"name": request.user, "form": fm}
return render(request, 'portfolios.html', context)
else:
return redirect('login')
You can use django forms instance for saving any predefined value without showing or render those fields to your users or html template. Here is an example how to automatically save your username and created_date fields .
if fm.is_valid():
fm = fm.save(commit=False)
fm.instance.username = request.user
fm.instance.created_date = timezone.now()
fm.save()
I have model from which I created a ModelForm:
models.py:
class City(models.Model):
name = models.CharField(max_length=50)
def __str__(self):
return f'{self.name}'
class Profile(models.Profile):
name = models.CharField(max_length=50)
user = models.OneToOneField(User, on_delete=models.CASCADE, unique=False)
location = models.ForeignKey('City', on_delete=models.SET_NULL, blank=True, null=True)
forms.py
from django import forms
from .models import Profile, City
class LocationField(forms.CharField):
def clean(self, value):
try:
city = City.objects.get(name=value)
except ObjectDoesNotExist:
city = City.objects.create(name=value)
return city
class ProfileForm(forms.ModelForm):
location = LocationField()
class Meta:
model = Profile
exclude = ['user']
views.py
def profile_update_view(request):
template_name = 'profiles/update.html'
user = request.user
profile = Profile.objects.get(user__id=user.id)
if request.method == 'GET':
form = ProfileForm(instance=profile)
else:
form = ProfileForm(request.POST, instance=profile)
if form.is_valid():
obj = form.save(commit=False)
obj.user = user
obj.save()
return redirect('profile_view')
context = {'form': form}
return render(request, template_name, context=context)
When I'm saving form, I'm satisfied how it's working, but when I load form again to update in, it fills LocationField() as an City pk integer, but I want it to load name instead. Is there a way to do this?
I've added in views.py:
if request.method == 'GET':
initial = {}
if profile.location:
initial = {'location': profile.location.name}
form = ProfileForm(instance=profile, initial=initial)
now it's working. But it's some workaround. I've thought there is some parameter maybe
I am using the same form for profile_edit and create_profile functionality. It is updating the multi-choice values in the profile_edit page but does not create in create_profile.
Below is the form code in forms.py
class ProfileForm(ModelForm):
full_name = forms.CharField(required=True)
current_position = forms.CharField(required=True)
about_me = forms.Textarea(attrs={'required':True})
topic_name = forms.ModelMultipleChoiceField(Topic.objects.all())
class Meta:
model = Profile
fields =(
"full_name",
"current_position",
"about_me",
"topic_name",
)
Below is the views.py for profile creation
def create_profile(request, user_id):
if request.method == "POST":
form = ProfileForm(request.POST)
if form.is_valid():
form = form.save(commit=False)
user = get_object_or_404(User, id=user_id)
form.user = user
print(form.topic_name.all()) # Prints empty queryset
form.save()
return redirect("profile_view", user_id=user_id)
else:
context = {"form": form}
return render(request, "profile/create_profile.html", context)
else:
form = ProfileForm()
context = {
"form": form
}
return render(request, "profile/create_profile.html", context)
Below is Model.py
class Topic(models.Model):
topic = models.CharField(max_length=12)
def __str__(self):
return self.topic
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True,)
full_name = models.CharField(max_length=60, null=True)
current_position = models.CharField(max_length=64, null=True)
about_me = models.TextField(max_length=255, null=True)
topic_name = models.ManyToManyField(Topic)
def __str__(self):
return self.full_name
Both create_profile and edit_profile templates are exactly the same.
It saves everything except Multichoice field.
When you do save(commit=False),
you need to use mymodelform.save_m2m() below save(commit=True) on your ModelForm,
because many to many relationships cannot be saved without an ID.
see this docs
so in your views.py
if form.is_valid():
profile = form.save(commit=False)
user = get_object_or_404(User, id=user_id)
profile.user = user
profile.save()
form.save_m2m()
return redirect("profile_view", user_id=user_id)
I'm trying to do a form so a user can upload a video, the problem is i can't get current user or it's id as a foreign key on my video model
Error: IntegrityError
Exception Value: (1048, "Column 'owner_id' cannot be null")
How can i solve the problem please, i looked at django documentation but doesn't find answer.
My models.py:
class Videowtm(models.Model):
name = models.CharField(max_length=50, blank=True)
description = models.CharField(max_length=255, blank=True)
uploaded_at = models.DateTimeField(auto_now_add=True)
owner = models.ForeignKey(User)
video = models.FileField(upload_to='videos/')
My forms.py:
class VideowtmForm(forms.ModelForm):
class Meta:
model = Videowtm
fields = ('name', 'description', 'video', )
My views:
#login_required
def model_form_upload(request):
if request.method == 'POST':
form = VideowtmForm(request.POST, request.FILES)
form.owner = request.user
if form.is_valid():
form.save()
return redirect('home')
else:
form = VideowtmForm()
return render(request, 'model_form_upload.html', {
'form': form
})
Try this one:
first add blank=True to the owner in your model:
###No need for this if you don't include it in your form fields###
class Videowtm(models.Model):
name = models.CharField(max_length=50, blank=True)
description = models.CharField(max_length=255, blank=True)
uploaded_at = models.DateTimeField(auto_now_add=True)
owner = models.ForeignKey(User, blank=True)
video = models.FileField(upload_to='videos/')
and then:
views.py:
#login_required
def model_form_upload(request):
if request.method == 'POST':
form = VideowtmForm(request.POST, request.FILES)
if form.is_valid():
video = form.save(commit=False)
video.owner = request.user
video.save()
return redirect('home')
else:
form = VideowtmForm()
return render(request, 'model_form_upload.html', {
'form': form
})