Creating multiple instances of the same model from one form - django

So I have a model Member:
class Member(models.Model):
first_name = models.CharField(max_length = 15)
last_name = models.CharField(max_length = 15)
house = models.ForeignKey('House', null = True)
created_on = models.DateTimeField('created on')
user = models.OneToOneField(User, null = True)
and a form to create the model:
class MemberForm(forms.Form):
first_name = forms.CharField()
last_name = forms.CharField()
email_address = forms.EmailField()
My app works where you create a House and specify the number of Members in your house. That's as far as I have working, but I would like it to continue to a new page where it displays an appropriate number of forms (one for each Member), and then creates a Member instance for each with the supplied data. I'm confused as to how I access the data from each form, since they're all technically in the same HTML form. More specifically how I identify what email field goes with which first name field and so on. Any help would be greatly appreciated, thanks.

This is what formsets are for.
Note that creating a member from a memberform would be easier if you used model forms (and model formsets).

Related

Is partial form a good practice in Django?

I'm new in Django and I try to find out if saving partial forms are a good practice or not. For example, I have Poll App and Candidate model with four fields: name, surname, targets andbiography. And I have a form where I have to fill all these fields. But if user only finished fill name, surname and targets, but even din't start filling biography field, how can I save his draft to user can finish it later and don't make any security mess?
models.py:
class Candidate(models.Model):
name = models.CharField(max_length=50)
surname = models.CharField(max_length=50)
biography = models.TextField()
targets = models.CharField(max_length=1000)
forms.py
class CandidateForm(ModelForm):
class Meta:
model = Candidate
fields = [
'name',
'surname',
'biography',
'targets',
]
widgets = {
'biography': forms.Textarea(attrs={'rows': 3})
}
I will be happy to see all ideas.
how can I save his draft to user can finish it later and don't make
any security mess?
You can either save the data to DB if you have designed the models to accept null or blank values, Or you can use Django sessions to temporarily store the form data until the form is completed...
In both case the security is not an issue since just like a DB access the django session data is also stored in a database and not in the browser... and so the end users cannot easily mess with the data...
check the following answer if you would like to know more...
Your problem is here :-
models.py:
class Candidate(models.Model):
name = models.CharField(max_length=50)
surname = models.CharField(max_length=50)
biography = models.TextField()
targets = models.CharField(max_length=1000)
If you put default='your default value':-
models.py:
class Candidate(models.Model):
name = models.CharField(max_length=50)
surname = models.CharField(max_length=50)
biography = models.TextField(default=' ')
targets = models.CharField(max_length=1000)
I think this is right what you need

Class based views how to handle OneToOneField in a model

I have 2 models:
class CompanyInfo(models.Model):
name = models.CharField(_('name'), max_length=100)
address = models.OneToOneField(Location)
class Location(models.Model):
address_1 = models.CharField(_("address"), max_length=128)
address_2 = models.CharField(_("address cont'd"), max_length=128, blank=True)
city = models.CharField(_("city"), max_length=64, default="")
state = USStateField(_("state"), default="")
zip_code = models.CharField(_("zip code"), max_length=5, default="")
When I use CBVs and prints out the form on the template. It shows name with an input field and address as a multiple choice selection.
Is there anyway in which I could convert the multiple choice to act as multiple input fields and the state to be multiple choice.
I figured I could have 2 form for these, but how would I incorporate a form inside of a form?
Also, the way in which the models and fields are must not be changed. For this example sure location fields could be in the company info, but I simply want how to do something similar when it doesn't make sense to include all these fields into the same model.
So, far only thing I can come up with is using function based views and just dealing with 2 forms at a time.
Here are my forms:
class CompanyInfoForm(ModelForm):
class Meta:
model = CompanyInfo
exclude = ['address']
class LocationForm(ModelForm):
class Meta:
model = Location
fields = '__all__'
then class based views:
class CompanyInfoCreate(CreateView):
model = CompanyInfo
form_class = CompanyInfoForm
class LocationCreate(CreateView):
model = Location
form_class = LocationForm
However, this is very helpful since these forms can only be done 1 at a time. I would like LocationView to be in place of the address location or of the sort.
Perhaps, these types of views have their strength in dealing with forms at an individual level.

form with manytomany object creation

I'm trying to make own form adding object Announcement
models.py:
class Announcement(models.Model):
person = models.ForeignKey('Person')
source = models.CharField(max_length=30)
date = models.DateField(default=datetime.now())
valid_date = models.DateField(null=True,blank=True)
class Person(models.Model):
names = models.ManyToManyField('Name')
birth_date = models.DateField(null=True, blank=True)
class Name(models.Model):
first_name = models.CharField(max_length=50,blank=True)
middle_name = models.CharField(max_length=50, blank=True)
last_name = models.CharField(max_length=50, blank=True)
(It maybe loos weird, but in my concept each Person can have more than one Name, and also the same Name can be assigned to different Persons)
forms.py
from django import forms
from backoffice.models import Announcement
class AnnouncementForm(forms.ModelForm):
class Meta:
model = Announcement
fields = ('person','signature','organisation','source', 'date')
And everything works perfectly but I have to choose Person from selectbox. And it is expected behaviour.
But in my case i'm definetely sure, that person doesn't exists in base (all announcements are for different person for very long time - so i want to change person select box to three fields, and create new person (with new names) everytime I save the announcement.
I think I know how to save many to many, that's why i don't put the views.py, but I don't know how to set the forms.py to get fields.
I tried
class AnnouncementForm(forms.ModelForm):
class Meta:
model = Announcement
fields = ('person__names__first_name','signature','organisation','source', 'date')
but got Unknown field(s) (person__names__first_name) specified for Announcement
person__name__first_name will not really work in the forms, that only works for the django admin
you have to create a custom field for the first name and then create a logic for saving on either
def clean(self):
// logic here
or
def save(self, commit=True):
// put clean data here
announcement_form = super(AnnouncementForm, self).save(commit=False)
announcement_form.save()

Issue regarding form on Django 1.5

This is the scenario: I have a form with many field filled with some his own data and the user can change them.
In this form I collect 3 kind of data:
the first type of data are user data,
the second type of data are user personal data and
the third type of data are user work data.
Work data and personal data are binding to user data using a foreign key.
When the user clicks submit, my view collect this data from the request and send them to a view.
This is the problem:
this 3 type of data already have a model and a modelform (I used it in another part of this website),
class User(models.Model):
username = models.CharField(max_length=30, unique=True)
password = models.CharField(max_length=30)
email = models.EmailField(unique=True)
confirmed = models.BooleanField(default=False)
class PersonalData(models.Model):
user = models.OneToOneField(AtgUser, primary_key=True)
name = models.CharField(max_length=100)
surname = models.CharField(max_length=100)
address = models.CharField(max_length=200, blank=True)
class WorkData(models.Model):
user = models.OneToOneField(AtgUser, primary_key=True)
companyname = models.CharField(max_length=100)
And their related modelforms:
class Form1(ModelForm):
class Meta:
model = user.User
class Form2(ModelForm):
class Meta:
model = user.PersonalData
exclude = 'user'
class Form3(ModelForm):
class Meta:
model = user.WorkData
exclude = 'user'
But now I must use a new form that includes all the data like this:
class Bigform(Forms.form):
username = models.CharField(max_length=30, unique=True)
password = models.CharField(max_length=30)
email = models.EmailField(unique=True)
name = models.CharField(max_length=100)
surname = models.CharField(max_length=100)
address = models.CharField(max_length=200, blank=True)
companyname = models.CharField(max_length=100)
so:
When I get my request in the view, How can I extract part of the collected data in Bigform and put this data in their own modelform or model in order to update this data in my Database?
I thought of extract some field from Bigform in order to fill an already exist model or model form.
Is this the correct way?
Suggestions?
Thanks in advance

Django - Linking my models to profiles (UserProfile) model

I'm trying to create a small app for users to have contacts. I'm using django-profiles as a base for my profiles. Now everything works well until I try to submit the edit contact form and I receive this error.
Cannot assign "<Contact: Contact object>": "Contact.user" must be a "UserProfile" instance.
Being pretty new to Django, I'm not even sure if I'm taking the right approach here. My end goal is for the user to be able to add as many contacts as neccessary.
Any advice is appreciated.
My UserProfile model which extends User looks like:
class UserProfile(models.Model):
#User's Info
user = models.ForeignKey(User, unique=True)
first_name = models.CharField("first name", max_length=30)
last_name = models.CharField("last name", max_length=30)
home_address = models.CharField(max_length=50)
primary_phone = PhoneNumberField()
city = models.CharField(max_length=50)
state = USStateField()
zipcode = models.CharField(max_length=5)
birth_date = models.DateField()
gender = models.CharField(max_length=1, choices=GENDER_CHOICES, blank=True)
and my contact model looks like this:
class Contact(models.Model):
user = models.ForeignKey(UserProfile)
contact_description = models.CharField("Relation or Description of Contact", max_length=50, blank=True)
contact_first_name = models.CharField("contact first name", max_length=30)
contact_last_name = models.CharField("contact last name", max_length=30)
contact_primary_phone = PhoneNumberField("contact primary phone number")
contact_secondary_phone = PhoneNumberField("contact secondary phone number",blank=True)
and my view:
def editContact(request, username, object_id=False, template_name='contacts/edit.html'):
user = UserProfile.user
AddContactFormset = inlineformset_factory(UserProfile,Contact, extra=1)
if object_id:
contact=Contact.objects.get(pk=object_id)
else:
contact=Contact()
if request.method == 'POST':
f= ContactForm(request.POST, request.FILES, instance=contact)
fs = AddContactFormset(request.POST, instance=contact)
if fs.is_valid() and f.is_valid():
f.save()
fs.save()
return HttpResponse('success')
else:
f = ContactForm(instance=contact)
fs = AddContactFormset(instance=contact)
return render_to_response(template_name ,{'fs':fs,'f':f,'contact': contact}, context_instance=RequestContext(request))
Basically, django-profiles is for something else - it's just helping to create and manage user profiles across an application.
First of all - you should link Contact models directly to the django.contrib.auth.models.User via ForeignKey. This way you can access given User's contacts by a simple query ie. User.contact_set.all() - it will return to you a list of User's contacts. This will also get rid off your error.
Second - fields like first_name, last_name are already definied in django.contrib.auth.models.User, so there is no need to define them again in UserProfile. Read the source of User model here
Third - if your user can only have one Profile and you're not intend to use very old versions of django then you should be using OneToOneField instead of ForeignKey.
Fourth thing - you could probably omit usage of RequestContext() by using one of the generic views bundled with django - read about that here
Last thing - remember that main model for handling the Users is the User model itself. Any custom Profile is just an extension, so link everything which is related to the User to the User model itself.
Happy coding!
To elaborate on bx2's answer, your Contact model should look more like this:
class Contact(models.Model):
user = models.ForeignKey(User, related_name='contacts')
contact_description = models.CharField("Relation or Description of Contact", max_length=50, blank=True)
contact_first_name = models.CharField("contact first name", max_length=30)
contact_last_name = models.CharField("contact last name", max_length=30)
contact_primary_phone = PhoneNumberField("contact primary phone number")
contact_secondary_phone = PhoneNumberField("contact secondary phone number",blank=True)
Your view, frankly, does not make much sense. In general an inline formset is meant to represent records related to some parent record. In your case, it would be the user record, with the contacts being the "children" records. But having both a Contact form and an AddContactFormset doesn't make a lot of sense.
Also, I'd recommend against using variable names like f and fs in Django. Apart from variables like indexes, counters, etc. it doesn't serve any purpose to use short 1-2 character variable names. Go ahead and use longer variable names like form and formset, or even contact_form and contact_formset. It makes it much, much easier to debug the code in the future.