Working with multiple related django modelforms - python

I'm trying to get two forms derived from related models to display on the same page and save together.
This is my models.py:
class userinfo(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, primary_key= True,
on_delete=models.CASCADE)
name = models.CharField(max_length = 200, blank = True)
email = models.EmailField(max_length= 300, default = 'Null')
phone = models.CharField(max_length= 10, default = 'Null')
def __unicode__(self):
return self.user
class seller_event(models.Model):
event_id = models.AutoField(primary_key=True)
user = models.ForeignKey(settings.AUTH_USER_MODEL,
on_delete=models.CASCADE)
title = models.CharField(max_length = 300, default = 'Null')
description = models.CharField(max_length = 300, default = 'Null')
location = models.CharField(max_length= 300, default = 'Null')
cash_payment = models.BooleanField(default=False)
paytm_payment = models.BooleanField(default=False)
def __unicode__(self):
return str(self.event_id) + str(self.title)
As you can see, the user (saved as user_id in my sqlite3 db) is the foreign key from the userinfo table. I'm trying to get multiple events listed for each seller.
forms.py:
class Userinfo(forms.ModelForm):
class Meta:
model = userinfo
exclude = {'user'}
class Seller_event(forms.ModelForm):
class Meta:
model = seller_event
exclude = {'user'}
views.py:
def newlist(request):
if request.user.is_authenticated():
user = request.user
print user
if request.method == 'POST':
userinfo_form = Userinfo(request.POST, instance = user.userinfo)
seller_event_form = Seller_event(request.POST, instance =
user.seller_event)
if userinfo_form.is_valid() and seller_event_form.is_valid():
userinfo_form.save()
seller_event_form.save()
return redirect('/home')
else:
userinfo_form = Userinfo()
seller_event_form = Seller_event()
return render(request, 'home/newlist.html', {'userinfo_form':
userinfo_form, 'seller_event_form': seller_event_form })
html:
{% load static %}
<form action="/home/newlist/" method="post">
{% csrf_token %}
{{ userinfo_form.as_p }}
{{ seller_event_form.as_p }}
<input type="submit">
</form>
I suspect the problem is that while for userinfo, the user pk is a onetoone, there is no issue with identifying the model. However, this is not the case for seller_event. Here it is a fk. So, how do I get it to accept the user as an fk?
Thanks in advance!

After form validation, save your form without committing, then set your foreign key and save.
if userinfo_form.is_valid() and seller_event_form.is_valid():
userinfo_form.save()
new_seller_event = seller_event_form.save(commit=False)
new_seller_event.user = user
new_seller_event.save()
return redirect('/home')

Related

OrderForm' object has no attribute 'get' via request.post

I've created an orderform and was trying to extract information from the form. However, each time when i called for forms.get("firstname") or anything, i will face the error that the object has no attribute 'get" even though it is a form. more specifically, the error is "AttributeError: 'OrderForm' object has no attribute 'get'"
Here is the relevant code:
in models.py:
class BaseModel(models.Model):
eid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
date_created = models.DateTimeField(auto_now_add=True, db_index=True)
class Meta: abstract = True
#classmethod
def get_or_none(cls, **kwargs):
try:
return cls.objects.get(**kwargs)
except cls.DoesNotExist:
return None
class Order(BaseModel):
itemname = models.CharField(max_length =100, default="")
firstname = models.CharField(max_length = 20)
lastname = models.CharField(max_length = 20)
email = models.EmailField()
phone = PhoneNumberField(null=False, blank=False)
comments = models.TextField()
delivery = models.BooleanField(default=False)
def __str__(self):
return str(self.eid)
in forms.py:
class OrderForm(forms.ModelForm):
itemname = forms.ModelMultipleChoiceField(queryset=Post.objects.filter(title__contains="Bae"), required=True)
class Meta:
model = Order
fields = ('itemname', 'firstname', 'lastname', 'email', 'phone','delivery', 'comments')
labels = {'itemname': 'Order Item', 'firstname': 'First Name', 'lastname':"Last Name", 'email':"Email", 'phone':"Phone Number", 'delivery':'Deliver?', 'comments':'Comments'}
in views.py. This is where the error occurs:
def order(request):
if request.method == "POST":
form = OrderForm(request.POST)
if form.is_valid():
order = form.save(commit=False)
item_selected = form.get('itemname')
order.itemname = item_selected
order.save()
return render(request, 'Reddit_app/order_thankyou.html')
else:
form = OrderForm()
return render(request, 'Reddit_app/order_from_post.html', {"form": form})
finally, the order html code is :
<form method="POST" class="post-form">{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="save btn btn-primary">Submit</button>
</form>
item_selected = form.cleaned_data.get('itemname')
if you want to access data from form you need to access cleaned_data after the is_valid function is invoked

Django passing Foreign Keys with multiple forms on a page

I am fairly new to Django and struggling a bit on how to get the primary keys from form input on a multiform view. I cannot get the keys into the database.
I have 3 models: Human, Human_notes, and Location. My form is made of these separate models as forms on one view. I thought I should collect the primary key from each form once saved and apply that to the next form data as a foreign key...
<form action="human-add" method="POST">
{% csrf_token %}
{{ human_form.as_p }}
{{ location_form.as_p }}
{{ human_notes_form.as_p }}
<button type="submit" class="save btn btn-success">Save</button>
</form>
Human has FKs to Location...:
class Human(models.Model):
intaker = models.ForeignKey(User, default=None, on_delete=models.SET_NULL, null=True)
location = models.OneToOneField('Location', on_delete=models.SET_NULL, null=True, related_name='humans')
Human_notes has FK to Human...(maybe this will become an FK in Human but originally thought many notes for one human) :
class HumanNotes(models.Model):
human = models.ForeignKey(Human, on_delete=models.SET_NULL, null=True, related_name='humans_notes')
My view is:
def human_add(request):
if request.method == 'POST':
human_form = HumanForm(request.POST)
location_form = LocationForm(request.POST)
human_notes_form = HumanNotesForm(request.POST)
if human_form.is_valid() and location_form.is_valid() and human_notes_form.is_valid():
human_form.save(commit=False)
location_form.save()
locationKey = location_form.id
human_notes_form.save(commit=False)
human_notes_form.intaker = request.user
human_notes_form.save()
noteKey = human_notes_form.id
human_form.location = locationKey
human_form.note = noteKey
human_form.intaker = request.user
human_form.save()
return redirect('/intake/success-form')
else:
context = {
'human_form': human_form,
'location_form': location_form,
'human_notes_form': human_notes_form,
}
else:
context = {
'human_form': HumanForm(),
'location_form': LocationForm(),
'human_notes_form': HumanNotesForm(),
}
return render(request, 'intake/human-add.html', context)
The only error I am getting is that 'LocationForm' object has no attribute 'id' - but I even added it explicitly (thought I should not have to and don't want it visible):
class HumanNotesForm(forms.ModelForm):
class Meta:
model = HumanNotes
fields = ['id','intaker','note']
class LocationForm(forms.ModelForm):
class Meta:
model = Location
fields = ['id','st1','st2','cty','county','state','zip','lat','long','img','img_nm','img_id']
Any guidance appreciated.
This did the trick....as did getting excellent guidance from forum.djangoproject.com. Needed to understand the diff between forms and models.
def human_add(request):
if request.method == 'POST':
human_form = HumanForm(request.POST)
location_form = LocationForm(request.POST)
human_notes_form = HumanNotesForm(request.POST)
if human_form.is_valid() and location_form.is_valid() and human_notes_form.is_valid():
loc = location_form.save()
hum = human_form.save(commit=False)
humnote = human_notes_form.save(commit=False)
hum.intaker = request.user
hum.location = loc #.id NOTE YOU NEED THE ENTIRE INSTANCE
human_form.save()
humnote.intaker = request.user
humnote.human = hum #.id NOTE YOU NEED THE ENTIRE INSTANCE
human_notes_form.save()
return redirect('/intake/success-form')
else:
context = {
'human_form': human_form,
'location_form': location_form,
'human_notes_form': human_notes_form,
}
else:
context = {
'human_form': HumanForm(),
'location_form': LocationForm(),
'human_notes_form': HumanNotesForm(),
}
return render(request, 'intake/human-add.html', context)

Django: getting access to related fields in other modles

I have the below
class Chore(models.Model):
title = models.CharField(max_length=300)
reward = models.PositiveIntegerField( default= 1)
def __str__(self):
return self.title
class Child(models.Model):
created_by = models.ForeignKey(User,on_delete=models.PROTECT, blank = True, null = True)
name = models.CharField(max_length=300)
age = models.DecimalField (max_digits=2, decimal_places=1, default=3.0, blank = True )
class ChildChore(models.Model):
child = models.ForeignKey(Child, on_delete=models.PROTECT)
chore = models.ForeignKey(Chore, on_delete=models.PROTECT)
points = models.PositiveIntegerField( default= 0, blank = True, null = True)
Form:
class ProgressForm(ModelForm):
class Meta:
model = ChildChore
exclude = ()
ProgressFormSet = modelformset_factory(ChildChore, form=ProgressForm, extra=0, can_delete=[False])
html page:
{{ formset.management_form }}
{% for form in formset %}
{{form.chore}} # will return the title
{{form.child}} # will return the child name
{{form.points}}
View:
def ProgressCreate(request, cid):
template_name = 'chore/progress_form.html'
if request.method == 'GET':
formset = ProgressFormSet(queryset=ChildChore.objects.filter(child=cid))
elif request.method == 'POST':
formset = ProgressFormSet(request.POST)
if formset.is_valid():
for form in formset:
# only save if name is points
if form.cleaned_data.get('points'):
form.save()
return redirect('children-list')
else:
print (formset.errors)
return render(request, 'chore/progress_form.html', {'formset': formset})
my question here is how to get the other models fields in the template? For example, I want the "reward" from Chore Model and I need the "age" form Child.
something like {{form.child.age}} will not work and creating a function in the child model to return the age didn't work as well.
I tried to make

create a distinct model option in a dropdown using django

I have created this application but the problem I face now is one that has kept me up all night. I want users to be able to see and select only their own categories when they want to create a post. This is part of my codes and additional codes would be provided on request
category model
class Category(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, default=1,related_name='categories_created')
name = models.CharField(max_length = 120)
slug = models.SlugField(unique= True)
timestamp = models.DateTimeField(auto_now=False, auto_now_add=True)
post model
class Post(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, default=1,related_name='posts_created') #blank=True, null=True)
title = models.CharField(max_length = 120)
slug = models.SlugField(unique= True)
category = models.ForeignKey(Category, on_delete=models.CASCADE, related_name='category_created', null= True)
addition codes would be provided immediately on request. Thanks
View.py in post app
def create(request):
if not request.user.is_authenticated():
messages.error(request, "Kindly confirm Your mail")
#or raise Http404
form = PostForm(request.POST or None, request.FILES or None)
user = request.user
categories = Category.objects.filter(category_created__user=user).distinct()
if form.is_valid():
instance = form.save(commit=False)
instance.user = request.user
instance.save()
create_action(request.user, 'Posts', instance)
messages.success(request, "Post created")
return HttpResponseRedirect(instance.get_absolute_url())
context = {
"form": form,
}
template = 'create.html'
return render(request,template,context)
Form
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = [
"title",
"content",
"category",
]
html
{% if form %}
<form method="POST" action="" enctype="multipart/form-data">{% csrf_token %}
{{ form|crispy|safe }}
<input type="submit" name="submit" value="Publish">
</form>
{% endif %}
What you need to do is well-described here. Basically, you are using ModelForm which generates the form from your model. Your model doesn't know anything about filtering by user, so you will need to explicitly add a QuerySet to your form that only shows the desired categories. Change your "categories = ..." line to something like:
form.category.queryset = Category.objects.filter(user=user)
form.fields['category'].queryset = Category.objects.filter(user=user)</strike>

Django Cannot assign "<django.utils.functional.SimpleLazyObject object at 0x7fc7f010ef50>": "listings.user" must be a "CustomUser" instance

I want to save an add under the current user that i'm logged in as, but i keep getting the error outlined in the subject.
My models:
class CustomUser(User):
nickname = models.CharField(max_length=255)
phone = models.CharField(max_length=255)
address = models.CharField(max_length=255)
objects = UserManager()
city = models.ForeignKey(locations, unique=False)
def __str__(self):
return self.nickname
class Admin:
pass
class listings(models.Model):
title = models.CharField(max_length=255)
category = models.ForeignKey('category')
description = models.CharField(max_length=255)
published = models.DateField(auto_now=True)
user = models.ForeignKey(CustomUser, unique=False)
def __str__(self):
return self.naslov
class Admin:
pass
The form:
class jobOfferForm(forms.ModelForm):
title = forms.CharField(max_length=255)
description = forms.CharField(max_length=255)
category = forms.ModelChoiceField(queryset=kategorii.objects.all())
class Meta:
model = listings
The template:
<div class="span8">
<form action="" method="POST">
{% csrf_token %}
{{form.as_p}}
<input type="submit" name="submit" value="Save"/>
</form>
</div>
The view!
def displisting(request):
if request.method == 'POST':
form = jobOfferForm(request.POST)
if form.is_valid():
title = form.cleaned_data['title']
description = form.cleaned_data['description']
new_listng = form.save(commit = False)
new_listng.user = request.user
new_listng.object.save()
return HttpResponseRedirect('/listing/review')
else:
form = jobOfferForm()
return render(request,'listings.html',{'form':form,})
I fear the custom user is preventing me from doing that?
But i need the extra attributes?
this error will happen if your user is not logged in.
login using the bundled /admin site and your request.user object will be a valid User instance
request.User isn't an instance of your custom CustomerUser, it's a django.contrib.auth.models.User. Hence the assignment:
new_listng.user = request.user
isn't valid.
You probably want your request.User to be downcast to your CustomerUser (or other subclasses, if you have them). You can add a custom middleware, modeled off django.contrib.auth.middleware.AuthenticationMiddleware that does this.
django-model-util's InheritanceManager has some useful helpers like select_subclasses that make this easy.

Categories

Resources